summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gdbinit23
-rw-r--r--.gitignore5
-rw-r--r--.gitmodules3
-rw-r--r--SConstruct11
m---------laks0
-rw-r--r--main.cpp306
6 files changed, 348 insertions, 0 deletions
diff --git a/.gdbinit b/.gdbinit
new file mode 100644
index 0000000..ead22c6
--- /dev/null
+++ b/.gdbinit
@@ -0,0 +1,23 @@
+define flash
+file esc.elf
+load
+end
+
+define restart
+run
+end
+
+define attach_swd
+mon swdp_scan
+attach 1
+end
+
+define attach_jtag
+mon jtag_scan
+attach 1
+end
+
+file esc.elf
+target extended-remote /dev/cu.usbmodem7FC181B1
+
+set mem inaccessible-by-default off
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b137a4a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.o
+*.a
+*.elf
+*.swp
+.sconsign.dblite
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..cd4f3c2
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "laks"]
+ path = laks
+ url = git://git.jvnv.net/laks.git
diff --git a/SConstruct b/SConstruct
new file mode 100644
index 0000000..1790b7b
--- /dev/null
+++ b/SConstruct
@@ -0,0 +1,11 @@
+import os
+
+env = Environment(
+ ENV = os.environ,
+)
+
+SConscript('laks/build_rules')
+
+env.SelectMCU('stm32f103c8')
+
+env.Firmware('esc.elf', ['main.cpp'])
diff --git a/laks b/laks
new file mode 160000
+Subproject 9ae91599772ee81d352014a8ff293c5feec0439
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..105d89d
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,306 @@
+#include <interrupt/interrupt.h>
+#include <os/thread.h>
+#include <os/time.h>
+#include <can/can.h>
+#include <usart/usart.h>
+#include <gpio/pin.h>
+#include <timer/timer.h>
+#include <adc/adc.h>
+
+static Pin& led_ready = PB3;
+static Pin& led_error = PB4;
+
+static Pin& foo = PA9;
+
+static Pin& a_l = PA7;
+static Pin& b_l = PB0;
+static Pin& c_l = PB1;
+
+static Pin& a_h = PB6;
+static Pin& b_h = PB7;
+static Pin& c_h = PB8;
+
+static Pin& sense_a = PA1; // ADC IN1
+static Pin& sense_b = PA2; // ADC IN2
+static Pin& sense_c = PA3; // ADC IN3
+
+volatile bool sense_rising = 0;
+
+class Commutator {
+ private:
+ int state;
+ volatile uint32_t* active_pwm;
+
+ public:
+ Commutator() : state(0), active_pwm(&TIM4.CCR1) {}
+
+ void set_pwm(uint32_t pwm) {
+ *active_pwm = pwm;
+ }
+
+ void next() {
+ uint32_t temp;
+
+ switch(state++) {
+ case 0:
+ b_l.off();
+ c_l.on();
+ ADC1.JSQR = 2 << 15;
+ sense_rising = true;
+ break;
+
+ case 1:
+ temp = *active_pwm;
+ *active_pwm = 0;
+ active_pwm = &TIM4.CCR2;
+ *active_pwm = temp;
+ ADC1.JSQR = 1 << 15;
+ sense_rising = false;
+ break;
+
+ case 2:
+ c_l.off();
+ a_l.on();
+ ADC1.JSQR = 3 << 15;
+ sense_rising = true;
+ break;
+
+ case 3:
+ temp = *active_pwm;
+ *active_pwm = 0;
+ active_pwm = &TIM4.CCR3;
+ *active_pwm = temp;
+ ADC1.JSQR = 2 << 15;
+ sense_rising = false;
+ break;
+
+ case 4:
+ a_l.off();
+ b_l.on();
+ ADC1.JSQR = 1 << 15;
+ sense_rising = true;
+ break;
+
+ case 5:
+ temp = *active_pwm;
+ *active_pwm = 0;
+ active_pwm = &TIM4.CCR1;
+ *active_pwm = temp;
+ ADC1.JSQR = 3 << 15;
+ sense_rising = false;
+
+ state = 0;
+ break;
+ }
+ }
+};
+
+Commutator commutator;
+
+volatile uint32_t ctv = 170;
+
+volatile uint32_t ct = 0;
+volatile uint32_t cc = 200;
+
+volatile bool do_cc_est = 0;
+volatile bool done_cc_est = 0;
+
+template <>
+void interrupt<Interrupt::ADC1_2>() {
+ if(ADC1.SR & 0x04) {
+ USART1.reg.DR = ADC1.JDR1;
+
+ if(sense_rising ? ADC1.JDR1 > ctv : ADC1.JDR1 < ctv) {
+ //foo.on();
+ if(do_cc_est && !done_cc_est && ct > 10) {
+ cc = cc * 0.95 + (ct * 2) * 0.05;
+ done_cc_est = true;
+ }
+ } else {
+ //foo.off();
+ }
+ }
+
+ ADC1.SR = 0;
+}
+
+int main() {
+ // Initialize system timer.
+ STK.LOAD = 72000000 / 8 / 1000; // 1000 Hz.
+ STK.CTRL = 0x03;
+
+ RCC.enable(RCC.AFIO);
+ RCC.enable(RCC.GPIOA);
+ RCC.enable(RCC.GPIOB);
+
+ //AFIO.MAPR = 0x02000000; // Free JTAG pins used for LEDs.
+
+ //led_ready.set_mode(Pin::Output);
+ //led_error.set_mode(Pin::Output);
+
+ RCC.enable(RCC.CAN);
+ CAN1.enable();
+
+ PA12.set_mode(Pin::AF);
+
+ foo.set_mode(Pin::AF);
+ RCC.enable(RCC.USART1);
+ USART1.set_baudrate(1000000);
+ USART1.enable();
+ USART1.reg.CR1 |= 1 << 12;
+
+ // ADC.
+ RCC.enable(RCC.ADC1);
+
+ // Calibrate ADC.
+ ADC1.CR2 = 0x9;
+ while(ADC1.CR2 & 0x8);
+ ADC1.CR2 = 0x5;
+ while(ADC1.CR2 & 0x4);
+
+ sense_a.set_mode(Pin::Analog);
+ sense_b.set_mode(Pin::Analog);
+ sense_c.set_mode(Pin::Analog);
+
+ // Motor outputs.
+ a_l.off();
+ a_l.set_mode(Pin::Output);
+ //b_l.off();
+ b_l.on();
+ b_l.set_mode(Pin::Output);
+ c_l.off();
+ c_l.set_mode(Pin::Output);
+
+ a_h.set_mode(Pin::AF);
+ b_h.set_mode(Pin::AF);
+ c_h.set_mode(Pin::AF);
+
+ RCC.enable(RCC.TIM4);
+ TIM4.PSC = 0;
+ TIM4.ARR = 1000;
+ TIM4.CCER = 0x1111;
+ TIM4.CCMR1 = 0x6868;
+ TIM4.CCMR2 = 0x6868;
+
+ TIM4.CR2 = 0x70;
+
+ TIM4.CR1 = 0x40;
+ TIM4.CR1 = 0x41;
+
+ TIM4.CCR1 = 0;
+ TIM4.CCR2 = 0;
+ TIM4.CCR3 = 0;
+ TIM4.CCR4 = 1;
+
+ Interrupt::enable(Interrupt::ADC1_2);
+
+ ADC1.CR1 |= 0x80;
+ ADC1.CR2 |= 0xd001;
+
+ ADC1.JSQR = 3 << 15;
+
+ // Give all hardware enough time to initialize.
+ Time::sleep(200);
+
+ led_ready.on();
+
+ // Configure CAN.
+ CAN1.f_reg.FR[0][0] = 0;
+ CAN1.f_reg.FR[0][1] = 0;
+ CAN1.f_reg.FS1R[0] = 0x1;
+ CAN1.f_reg.FA1R[0] = 0x1;
+ CAN1.f_reg.FMR = 0;
+
+ uint32_t pwm = 0;
+
+ while(1) {
+ // Check for CAN message.
+ if(CAN1.reg.RF0R & 0x3) {
+ switch(CAN1.mb_reg.RDL0R) {
+ case '1':
+ led_ready.toggle();
+ break;
+
+ case '2':
+ led_error.toggle();
+ break;
+
+ case '+':
+ pwm += 10;
+ commutator.set_pwm(pwm);
+ break;
+
+ case '-':
+ if(pwm >= 10) {
+ pwm -= 10;
+ commutator.set_pwm(pwm);
+ }
+ break;
+
+ case 'e':
+ pwm += 1;
+ commutator.set_pwm(pwm);
+ break;
+
+ case 'd':
+ if(pwm) {
+ pwm -= 1;
+ commutator.set_pwm(pwm);
+ }
+ break;
+
+ case 'q':
+ cc += 10;
+ break;
+
+ case 'a':
+ cc -= 10;
+ break;
+
+ case 'w':
+ cc++;
+ break;
+
+ case 's':
+ cc--;
+ break;
+
+ case 'r':
+ ctv += 1;
+ break;
+
+ case 'f':
+ ctv -= 1;
+ break;
+
+ case 'y':
+ do_cc_est = !do_cc_est;
+ break;
+
+ case '0':
+ commutator.set_pwm(pwm = 0);
+ cc = 200;
+ do_cc_est = false;
+ break;
+ }
+
+ // Release mailbox.
+ CAN1.reg.RF0R = 0x20;
+ }
+
+ // Check for pwm update.
+ if(TIM4.SR & 0x01) {
+ TIM4.SR &= ~0x01;
+ if(++ct >= cc) {
+ commutator.next();
+ done_cc_est = false;
+ ct = 0;
+ }
+ }
+
+ // Check for pulse center.
+ if(TIM4.SR & 0x10) {
+ TIM4.SR &= ~0x10;
+ }
+ }
+}