First Commit

Dependencies:   mbed Crypto_light mbed-rtos

Spin it 2 win it

Committer:
henryeshbaugh
Date:
Fri Mar 23 18:54:18 2018 +0000
Revision:
29:e28682c4b4cb
Parent:
28:8076013fbef5
oops missed two lines

Who changed what in which revision?

UserRevisionLine numberNew contents of line
TrebleStick 0:88c3d6c8a4eb 1 #include "mbed.h"
andrebharath 3:2e32d7974962 2 #include "Crypto_light/hash/SHA256.h"
andrebharath 3:2e32d7974962 3 #include "mbed-rtos/rtos/rtos.h"
TrebleStick 0:88c3d6c8a4eb 4
henryeshbaugh 28:8076013fbef5 5 /* Photointerruptor input pins */
TrebleStick 0:88c3d6c8a4eb 6 #define I1pin D2
TrebleStick 0:88c3d6c8a4eb 7 #define I2pin D11
TrebleStick 0:88c3d6c8a4eb 8 #define I3pin D12
andrebharath 9:ecef1e8cbe3d 9
henryeshbaugh 28:8076013fbef5 10 /* Incremental encoder input pins */
TrebleStick 0:88c3d6c8a4eb 11 #define CHA D7
TrebleStick 12:1b2e2540e4e1 12 #define CHB D8
andrebharath 9:ecef1e8cbe3d 13
henryeshbaugh 28:8076013fbef5 14 /* Motor Drive output pins Mask in output byte */
henryeshbaugh 28:8076013fbef5 15 #define L1Lpin D4 /* 0x01 */
henryeshbaugh 28:8076013fbef5 16 #define L1Hpin D5 /* 0x02 */
henryeshbaugh 28:8076013fbef5 17 #define L2Lpin D3 /* 0x04 */
henryeshbaugh 28:8076013fbef5 18 #define L2Hpin D6 /* 0x08 */
henryeshbaugh 28:8076013fbef5 19 #define L3Lpin D9 /* 0x10 */
henryeshbaugh 28:8076013fbef5 20 #define L3Hpin D10 /* 0x20 */
TrebleStick 0:88c3d6c8a4eb 21
henryeshbaugh 28:8076013fbef5 22 /* max input length */
henryeshbaugh 27:d50f1914f23a 23 #define CHAR_ARR_SIZE 18
henryeshbaugh 27:d50f1914f23a 24
henryeshbaugh 28:8076013fbef5 25 /* pwm/motor control definitions */
andrebharath 17:80159ace5ddf 26 #define MAX_PWM_PERIOD 2000
andrebharath 18:05e5d280a082 27 #define MAX_TORQUE 1000
henryeshbaugh 27:d50f1914f23a 28 #define KP 20
henryeshbaugh 27:d50f1914f23a 29 #define KD 20
andrebharath 3:2e32d7974962 30
henryeshbaugh 28:8076013fbef5 31 /* function-like macros for utility */
henryeshbaugh 27:d50f1914f23a 32 #define sgn(x) ((x)/abs(x))
henryeshbaugh 27:d50f1914f23a 33 #define max(x,y) ((x)>=(y)?(x):(y))
henryeshbaugh 27:d50f1914f23a 34 #define min(x,y) ((x)>=(y)?(y):(x))
andrebharath 9:ecef1e8cbe3d 35
henryeshbaugh 28:8076013fbef5 36 #ifdef __GNUC__
henryeshbaugh 28:8076013fbef5 37 #define likely(x) __builtin_expect((x), 1)
henryeshbaugh 28:8076013fbef5 38 #define unlikely(x) __builtin_expect((x), 0)
henryeshbaugh 28:8076013fbef5 39 #else
henryeshbaugh 28:8076013fbef5 40 #define likely(x) (x)
henryeshbaugh 28:8076013fbef5 41 #define unlikely(x) (x)
henryeshbaugh 28:8076013fbef5 42 #endif
henryeshbaugh 28:8076013fbef5 43
henryeshbaugh 27:d50f1914f23a 44 enum MSG {MSG_RESET, MSG_HASHCOUNT, MSG_NONCE_OK, MSG_OVERFLOW, MSG_ROT_PEN,
henryeshbaugh 27:d50f1914f23a 45 MSG_MAX_SPD, MSG_NEW_KEY, MSG_INP_ERR, MSG_TORQUE, MSG_TEST,
henryeshbaugh 27:d50f1914f23a 46 MSG_CUR_SPD, MSG_POS, MSG_NEW_VEL, MSG_NEW_ROTOR_POS};
andrebharath 17:80159ace5ddf 47
andrebharath 9:ecef1e8cbe3d 48
henryeshbaugh 28:8076013fbef5 49 /* Instantiate the serial port */
andrebharath 9:ecef1e8cbe3d 50 RawSerial pc(SERIAL_TX, SERIAL_RX);
andrebharath 9:ecef1e8cbe3d 51
henryeshbaugh 28:8076013fbef5 52 /* Status LED */
andrebharath 9:ecef1e8cbe3d 53 DigitalOut led1(LED1);
andrebharath 9:ecef1e8cbe3d 54
henryeshbaugh 28:8076013fbef5 55 /* Photointerrupter inputs */
andrebharath 9:ecef1e8cbe3d 56 InterruptIn I1(I1pin);
andrebharath 9:ecef1e8cbe3d 57 InterruptIn I2(I2pin);
andrebharath 9:ecef1e8cbe3d 58 InterruptIn I3(I3pin);
andrebharath 9:ecef1e8cbe3d 59
henryeshbaugh 28:8076013fbef5 60 /* motor drive outputs */
andrebharath 17:80159ace5ddf 61 PwmOut L1L(L1Lpin);
henryeshbaugh 27:d50f1914f23a 62 PwmOut L2L(L2Lpin);
henryeshbaugh 27:d50f1914f23a 63 PwmOut L3L(L3Lpin);
andrebharath 9:ecef1e8cbe3d 64 DigitalOut L1H(L1Hpin);
andrebharath 9:ecef1e8cbe3d 65 DigitalOut L2H(L2Hpin);
andrebharath 9:ecef1e8cbe3d 66 DigitalOut L3H(L3Hpin);
andrebharath 9:ecef1e8cbe3d 67
henryeshbaugh 28:8076013fbef5 68 /* givens from coursework handouts - motor states etc */
henryeshbaugh 27:d50f1914f23a 69 const int8_t drive_table[] = {0x12,0x18,0x09,0x21,0x24,0x06,0x00,0x00};
henryeshbaugh 28:8076013fbef5 70 const int8_t state_map[] = {0x07,0x05,0x03,0x04,0x01,0x00,0x02,0x07};
henryeshbaugh 28:8076013fbef5 71
henryeshbaugh 28:8076013fbef5 72 volatile int8_t lead = 2, /* phase lead, -2 for backwards, 2 for forwards */
henryeshbaugh 27:d50f1914f23a 73 origin_state = 0;
TrebleStick 0:88c3d6c8a4eb 74
andrebharath 3:2e32d7974962 75
henryeshbaugh 28:8076013fbef5 76 /* threads for serial I/O and motor control */
henryeshbaugh 28:8076013fbef5 77 Thread comms_out_thrd(osPriorityLow, 1024);
henryeshbaugh 28:8076013fbef5 78 Thread comms_in_thrd(osPriorityLow, 1024);
henryeshbaugh 27:d50f1914f23a 79 Thread motor_ctrl_thrd(osPriorityNormal, 2048);
TrebleStick 20:a435105305fe 80
henryeshbaugh 27:d50f1914f23a 81
henryeshbaugh 28:8076013fbef5 82 /* IPC via Mail object; we instantiate here */
andrebharath 3:2e32d7974962 83 typedef struct {
henryeshbaugh 27:d50f1914f23a 84 char *stub;
TrebleStick 20:a435105305fe 85 uint8_t code;
TrebleStick 20:a435105305fe 86 int32_t data;
henryeshbaugh 27:d50f1914f23a 87 } message_t;
henryeshbaugh 27:d50f1914f23a 88
henryeshbaugh 27:d50f1914f23a 89 Mail<message_t, 16> msg_out_queue;
henryeshbaugh 27:d50f1914f23a 90
henryeshbaugh 28:8076013fbef5 91 /* bools are 8 bits and so access is atomic */
henryeshbaugh 28:8076013fbef5 92 volatile bool key_updated = false, spin_forever = false;
henryeshbaugh 27:d50f1914f23a 93
henryeshbaugh 28:8076013fbef5 94 /* instantiate a queue to buffer incoming characters */
henryeshbaugh 27:d50f1914f23a 95 Queue<void, 8> serial_in_queue;
henryeshbaugh 28:8076013fbef5 96 /* motor control global variables */
henryeshbaugh 27:d50f1914f23a 97 volatile int32_t motor_position = 0,
henryeshbaugh 27:d50f1914f23a 98 target_speed = 256,
henryeshbaugh 27:d50f1914f23a 99 torque = 1000;
henryeshbaugh 27:d50f1914f23a 100 volatile float rotations_pending = 0;
henryeshbaugh 27:d50f1914f23a 101
henryeshbaugh 28:8076013fbef5 102 volatile uint16_t hashcount = 0; /* hash count, reset every second when printed */
henryeshbaugh 28:8076013fbef5 103 volatile uint64_t new_key = 0; /* used when selecting a new hash key */
henryeshbaugh 27:d50f1914f23a 104
henryeshbaugh 28:8076013fbef5 105 /* logging function & shim macro for stringifying enum */
henryeshbaugh 27:d50f1914f23a 106 #define put_message(code, data) put_message_(#code, code, data)
henryeshbaugh 27:d50f1914f23a 107 void put_message_(char *, uint8_t, int32_t);
henryeshbaugh 28:8076013fbef5 108 void comms_out_fn(void); /* serial output thread main */
henryeshbaugh 28:8076013fbef5 109 void comms_in_fn(void); /* serial input thread main */
henryeshbaugh 28:8076013fbef5 110 void serial_isr(void); /* serial event ISR */
henryeshbaugh 28:8076013fbef5 111 void photointerrupter_isr(void); /* motor state change ISR */
henryeshbaugh 28:8076013fbef5 112 void motor_ctrl_fn(void); /* motor control thread main */
henryeshbaugh 28:8076013fbef5 113 void motor_ctrl_timer_isr(void); /* poke motor_ctrl at 100ms intervals */
henryeshbaugh 28:8076013fbef5 114 void parse_serial_in(char *); /* interpret serial command */
henryeshbaugh 28:8076013fbef5 115 void do_hashcount(void); /* print current hash count */
henryeshbaugh 28:8076013fbef5 116 inline int8_t read_rotor_state(void); /* get rotor position */
henryeshbaugh 28:8076013fbef5 117 int8_t motor_home(void); /* establish motor origin position */
henryeshbaugh 28:8076013fbef5 118 void motor_out(int8_t, uint32_t); /* do motor output */
henryeshbaugh 27:d50f1914f23a 119
henryeshbaugh 27:d50f1914f23a 120 int main(void)
henryeshbaugh 27:d50f1914f23a 121 {
henryeshbaugh 27:d50f1914f23a 122
henryeshbaugh 27:d50f1914f23a 123 comms_out_thrd.start(&comms_out_fn);
henryeshbaugh 27:d50f1914f23a 124 motor_ctrl_thrd.start(&motor_ctrl_fn);
henryeshbaugh 27:d50f1914f23a 125 comms_in_thrd.start(&comms_in_fn);
henryeshbaugh 27:d50f1914f23a 126
henryeshbaugh 27:d50f1914f23a 127 put_message(MSG_RESET, 0);
henryeshbaugh 27:d50f1914f23a 128
henryeshbaugh 28:8076013fbef5 129 /* sync motor to home */
henryeshbaugh 27:d50f1914f23a 130 rotations_pending = origin_state = motor_home();
henryeshbaugh 27:d50f1914f23a 131
henryeshbaugh 28:8076013fbef5 132 /* register ISRs */
henryeshbaugh 27:d50f1914f23a 133 I1.rise(&photointerrupter_isr);
henryeshbaugh 27:d50f1914f23a 134 I2.rise(&photointerrupter_isr);
henryeshbaugh 27:d50f1914f23a 135 I3.rise(&photointerrupter_isr);
henryeshbaugh 27:d50f1914f23a 136
henryeshbaugh 27:d50f1914f23a 137 I1.fall(&photointerrupter_isr);
henryeshbaugh 27:d50f1914f23a 138 I2.fall(&photointerrupter_isr);
henryeshbaugh 27:d50f1914f23a 139 I3.fall(&photointerrupter_isr);
andrebharath 3:2e32d7974962 140
TrebleStick 12:1b2e2540e4e1 141
henryeshbaugh 28:8076013fbef5 142 /* set PWM period */
henryeshbaugh 27:d50f1914f23a 143 L1L.period_us(MAX_PWM_PERIOD);
henryeshbaugh 27:d50f1914f23a 144 L2L.period_us(MAX_PWM_PERIOD);
henryeshbaugh 27:d50f1914f23a 145 L3L.period_us(MAX_PWM_PERIOD);
henryeshbaugh 27:d50f1914f23a 146
henryeshbaugh 28:8076013fbef5 147 /* Calling the ISR once starts the motor movement */
henryeshbaugh 27:d50f1914f23a 148 photointerrupter_isr();
henryeshbaugh 27:d50f1914f23a 149
henryeshbaugh 28:8076013fbef5 150 /* SHA256-related data */
henryeshbaugh 27:d50f1914f23a 151 SHA256 sha256;
henryeshbaugh 27:d50f1914f23a 152 uint8_t sequence[] = {0x45,0x6D,0x62,0x65,0x64,0x64,0x65,0x64,
henryeshbaugh 27:d50f1914f23a 153 0x20,0x53,0x79,0x73,0x74,0x65,0x6D,0x73,
henryeshbaugh 27:d50f1914f23a 154 0x20,0x61,0x72,0x65,0x20,0x66,0x75,0x6E,
henryeshbaugh 27:d50f1914f23a 155 0x20,0x61,0x6E,0x64,0x20,0x64,0x6F,0x20,
henryeshbaugh 27:d50f1914f23a 156 0x61,0x77,0x65,0x73,0x6F,0x6D,0x65,0x20,
henryeshbaugh 27:d50f1914f23a 157 0x74,0x68,0x69,0x6E,0x67,0x73,0x21,0x20,
henryeshbaugh 27:d50f1914f23a 158 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
henryeshbaugh 27:d50f1914f23a 159 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
henryeshbaugh 28:8076013fbef5 160
henryeshbaugh 28:8076013fbef5 161 uint64_t *key = (uint64_t*)((int)sequence + 48);
henryeshbaugh 28:8076013fbef5 162 uint64_t *nonce = (uint64_t*)((int)sequence + 56);
henryeshbaugh 28:8076013fbef5 163 uint8_t hash[32];
henryeshbaugh 27:d50f1914f23a 164
henryeshbaugh 27:d50f1914f23a 165 Ticker hashcounter;
henryeshbaugh 27:d50f1914f23a 166 hashcounter.attach(&do_hashcount, 1.0);
henryeshbaugh 27:d50f1914f23a 167
henryeshbaugh 28:8076013fbef5 168
henryeshbaugh 27:d50f1914f23a 169 while (1) {
henryeshbaugh 28:8076013fbef5 170 /* compute new hash - let gcc know this is not likely */
henryeshbaugh 28:8076013fbef5 171 if (unlikely(key_updated)) {
henryeshbaugh 28:8076013fbef5 172 /* no serialization is needed here; a new serial key *
henryeshbaugh 28:8076013fbef5 173 * command needs 18 bytes over serial (15ms) - we *
henryeshbaugh 28:8076013fbef5 174 * run at least 8k hashes per second, meaning this *
henryeshbaugh 28:8076013fbef5 175 * condition is hit roughly every 125us. Even if two *
henryeshbaugh 28:8076013fbef5 176 * key change commands were sent at once, we wouldn't *
henryeshbaugh 28:8076013fbef5 177 * hit a race condition. The worry is we get *
henryeshbaugh 28:8076013fbef5 178 * scheduled out in favor of serial in halfway *
henryeshbaugh 28:8076013fbef5 179 * through writing the new key (64 bits) specifically *
henryeshbaugh 28:8076013fbef5 180 * to get a new key from a user command, but that *
henryeshbaugh 28:8076013fbef5 181 * /can't/ happen because of the serial latency. */
henryeshbaugh 28:8076013fbef5 182 *key = new_key;
henryeshbaugh 28:8076013fbef5 183 key_updated = false;
henryeshbaugh 28:8076013fbef5 184 }
henryeshbaugh 28:8076013fbef5 185 /* compute the hash */
henryeshbaugh 27:d50f1914f23a 186 sha256.computeHash(hash, sequence, 64);
henryeshbaugh 27:d50f1914f23a 187
henryeshbaugh 27:d50f1914f23a 188 if (hash[0] == 0 && hash[1] == 0)
henryeshbaugh 27:d50f1914f23a 189 put_message(MSG_NONCE_OK, *nonce);
henryeshbaugh 27:d50f1914f23a 190
henryeshbaugh 27:d50f1914f23a 191 (*nonce)++;
henryeshbaugh 27:d50f1914f23a 192 hashcount++;
henryeshbaugh 27:d50f1914f23a 193 }
TrebleStick 12:1b2e2540e4e1 194 }
TrebleStick 12:1b2e2540e4e1 195
henryeshbaugh 27:d50f1914f23a 196 void put_message_(char *str, uint8_t code, int32_t data)
henryeshbaugh 27:d50f1914f23a 197 {
henryeshbaugh 27:d50f1914f23a 198 message_t *message = msg_out_queue.alloc();
henryeshbaugh 28:8076013fbef5 199
henryeshbaugh 27:d50f1914f23a 200 message->code = code;
henryeshbaugh 27:d50f1914f23a 201 message->data = data;
henryeshbaugh 27:d50f1914f23a 202 message->stub = str;
henryeshbaugh 28:8076013fbef5 203
henryeshbaugh 27:d50f1914f23a 204 msg_out_queue.put(message);
henryeshbaugh 27:d50f1914f23a 205 }
andrebharath 3:2e32d7974962 206
henryeshbaugh 27:d50f1914f23a 207 void comms_out_fn()
henryeshbaugh 27:d50f1914f23a 208 {
andrebharath 3:2e32d7974962 209 while(1) {
henryeshbaugh 27:d50f1914f23a 210 osEvent new_event = msg_out_queue.get();
henryeshbaugh 27:d50f1914f23a 211 message_t *message = (message_t*) new_event.value.p;
henryeshbaugh 28:8076013fbef5 212 pc.printf("[%d:%16s], data: %010d\r\n",
henryeshbaugh 28:8076013fbef5 213 message->code,
henryeshbaugh 27:d50f1914f23a 214 message->stub,
henryeshbaugh 27:d50f1914f23a 215 message->data);
henryeshbaugh 27:d50f1914f23a 216 msg_out_queue.free(message);
andrebharath 3:2e32d7974962 217 }
andrebharath 3:2e32d7974962 218 }
andrebharath 3:2e32d7974962 219
henryeshbaugh 28:8076013fbef5 220 /* serial port ISR to receive each incoming byte and place into queue */
henryeshbaugh 27:d50f1914f23a 221 void serial_isr()
henryeshbaugh 27:d50f1914f23a 222 {
henryeshbaugh 27:d50f1914f23a 223 uint8_t new_char = pc.getc();
henryeshbaugh 27:d50f1914f23a 224 serial_in_queue.put((void*) new_char);
henryeshbaugh 27:d50f1914f23a 225 }
andrebharath 9:ecef1e8cbe3d 226
henryeshbaugh 28:8076013fbef5 227 /* photointerrupter ISR drives the motors */
henryeshbaugh 27:d50f1914f23a 228 void photointerrupter_isr()
henryeshbaugh 27:d50f1914f23a 229 {
henryeshbaugh 27:d50f1914f23a 230 static int8_t old_rotor_state = 0;
henryeshbaugh 27:d50f1914f23a 231 int8_t rotor_state = read_rotor_state();
henryeshbaugh 27:d50f1914f23a 232
henryeshbaugh 28:8076013fbef5 233 motor_out((rotor_state-origin_state+lead+6)%6, torque); /* +6 to make sure the remainder is positive */
TrebleStick 20:a435105305fe 234
henryeshbaugh 27:d50f1914f23a 235 if (rotor_state - old_rotor_state == 5)
henryeshbaugh 27:d50f1914f23a 236 motor_position--;
henryeshbaugh 27:d50f1914f23a 237 else if (rotor_state - old_rotor_state == -5)
henryeshbaugh 27:d50f1914f23a 238 motor_position++;
henryeshbaugh 27:d50f1914f23a 239 else
henryeshbaugh 27:d50f1914f23a 240 motor_position += (rotor_state - old_rotor_state);
henryeshbaugh 27:d50f1914f23a 241
henryeshbaugh 27:d50f1914f23a 242 old_rotor_state = rotor_state;
TrebleStick 20:a435105305fe 243 }
TrebleStick 20:a435105305fe 244
henryeshbaugh 28:8076013fbef5 245 /* motor control thread sets a timer ISR, this is the handler */
henryeshbaugh 27:d50f1914f23a 246 void motor_ctrl_timer_isr() { motor_ctrl_thrd.signal_set(0x1); }
TrebleStick 20:a435105305fe 247
henryeshbaugh 28:8076013fbef5 248 /* motor control thread main */
henryeshbaugh 27:d50f1914f23a 249 void motor_ctrl_fn()
henryeshbaugh 27:d50f1914f23a 250 {
henryeshbaugh 27:d50f1914f23a 251 Ticker motor_control_ticker;
henryeshbaugh 27:d50f1914f23a 252 Timer timer;
henryeshbaugh 27:d50f1914f23a 253
henryeshbaugh 27:d50f1914f23a 254 uint8_t count = 0;
andrebharath 9:ecef1e8cbe3d 255
henryeshbaugh 27:d50f1914f23a 256 int32_t cur_pos = 0,
henryeshbaugh 27:d50f1914f23a 257 old_pos = 0,
henryeshbaugh 27:d50f1914f23a 258 cur_speed,
henryeshbaugh 27:d50f1914f23a 259 ys,
henryeshbaugh 27:d50f1914f23a 260 yr;
andrebharath 9:ecef1e8cbe3d 261
henryeshbaugh 27:d50f1914f23a 262 uint32_t cur_time = 0,
henryeshbaugh 27:d50f1914f23a 263 old_time = 0,
henryeshbaugh 27:d50f1914f23a 264 time_diff;
henryeshbaugh 27:d50f1914f23a 265
henryeshbaugh 27:d50f1914f23a 266 float cur_err = 0.0f,
henryeshbaugh 27:d50f1914f23a 267 old_err = 0.0f,
henryeshbaugh 27:d50f1914f23a 268 err_diff;
henryeshbaugh 27:d50f1914f23a 269
henryeshbaugh 27:d50f1914f23a 270 motor_control_ticker.attach_us(&motor_ctrl_timer_isr,100000);
henryeshbaugh 27:d50f1914f23a 271
andrebharath 23:58de87ec3997 272 timer.start();
henryeshbaugh 27:d50f1914f23a 273
henryeshbaugh 27:d50f1914f23a 274 while(1) {
henryeshbaugh 28:8076013fbef5 275 /* wait for the 100ms boundary */
henryeshbaugh 27:d50f1914f23a 276 motor_ctrl_thrd.signal_wait(0x1);
henryeshbaugh 27:d50f1914f23a 277
henryeshbaugh 28:8076013fbef5 278 /* read state & timestamp */
henryeshbaugh 27:d50f1914f23a 279 cur_time = timer.read();
henryeshbaugh 27:d50f1914f23a 280 cur_pos = motor_position;
henryeshbaugh 27:d50f1914f23a 281
henryeshbaugh 28:8076013fbef5 282 /* compute speed */
henryeshbaugh 27:d50f1914f23a 283 time_diff = cur_time - old_time;
henryeshbaugh 27:d50f1914f23a 284 cur_speed = (cur_pos - old_pos) / time_diff;
henryeshbaugh 27:d50f1914f23a 285
henryeshbaugh 28:8076013fbef5 286 /* prep values for next time through loop */
henryeshbaugh 27:d50f1914f23a 287 old_time = cur_time;
henryeshbaugh 27:d50f1914f23a 288 old_pos = cur_pos;
henryeshbaugh 27:d50f1914f23a 289
henryeshbaugh 27:d50f1914f23a 290 count = ++count % 10;
TrebleStick 20:a435105305fe 291
henryeshbaugh 28:8076013fbef5 292 /* update with motor status */
henryeshbaugh 27:d50f1914f23a 293 /*
henryeshbaugh 27:d50f1914f23a 294 * if (!count) {
henryeshbaugh 27:d50f1914f23a 295 * put_message(MSG_CUR_SPD, cur_speed);
henryeshbaugh 27:d50f1914f23a 296 * put_message(MSG_MAX_SPD, target_speed);
henryeshbaugh 27:d50f1914f23a 297 * put_message(MSG_POS, (cur_pos/6));
henryeshbaugh 27:d50f1914f23a 298 * put_message(MSG_ROT_PEN, rotations_pending);
henryeshbaugh 27:d50f1914f23a 299 * put_message(MSG_TORQUE, torque);
henryeshbaugh 27:d50f1914f23a 300 * }
henryeshbaugh 27:d50f1914f23a 301 */
henryeshbaugh 27:d50f1914f23a 302
henryeshbaugh 28:8076013fbef5 303 /* compute position error */
henryeshbaugh 28:8076013fbef5 304 cur_err = rotations_pending - (cur_pos/6.0f);
henryeshbaugh 27:d50f1914f23a 305 err_diff = cur_err - old_err;
henryeshbaugh 28:8076013fbef5 306 old_err = cur_err;
henryeshbaugh 27:d50f1914f23a 307
henryeshbaugh 28:8076013fbef5 308 /* compute torques */
henryeshbaugh 27:d50f1914f23a 309 ys = (int32_t) (20 * (target_speed - abs(cur_speed))) * sgn(cur_err);
henryeshbaugh 27:d50f1914f23a 310
henryeshbaugh 28:8076013fbef5 311 /* select minimum absolute value torque, or just take ys and spin forever */
henryeshbaugh 28:8076013fbef5 312 if (likely(!spin_forever)) {
henryeshbaugh 28:8076013fbef5 313 yr = (int32_t) ((20 * cur_err) + (40 * err_diff));
henryeshbaugh 28:8076013fbef5 314 if (cur_speed < 0)
henryeshbaugh 28:8076013fbef5 315 torque = max(ys, yr);
henryeshbaugh 28:8076013fbef5 316 else
henryeshbaugh 28:8076013fbef5 317 torque = min(ys, yr);
henryeshbaugh 28:8076013fbef5 318 } else
henryeshbaugh 28:8076013fbef5 319 torque = ys;
henryeshbaugh 27:d50f1914f23a 320
henryeshbaugh 28:8076013fbef5 321 /* fix torque if negative */
henryeshbaugh 27:d50f1914f23a 322 if (torque < 0)
henryeshbaugh 28:8076013fbef5 323 torque = -torque, /* <- comma operator in action */
henryeshbaugh 27:d50f1914f23a 324 lead = -2;
henryeshbaugh 27:d50f1914f23a 325 else
henryeshbaugh 27:d50f1914f23a 326 lead = 2;
henryeshbaugh 27:d50f1914f23a 327
henryeshbaugh 28:8076013fbef5 328 /* cap torque */
henryeshbaugh 27:d50f1914f23a 329 if (torque > MAX_TORQUE)
henryeshbaugh 27:d50f1914f23a 330 torque = MAX_TORQUE;
henryeshbaugh 27:d50f1914f23a 331
henryeshbaugh 28:8076013fbef5 332 /* finally, give the motor a kick */
henryeshbaugh 27:d50f1914f23a 333 photointerrupter_isr();
TrebleStick 20:a435105305fe 334 }
TrebleStick 19:526fd700e1b3 335 }
andrebharath 9:ecef1e8cbe3d 336
henryeshbaugh 28:8076013fbef5 337 /* parse input with sscanf() */
henryeshbaugh 27:d50f1914f23a 338 void parse_serial_in(char *s)
TrebleStick 14:66746291017c 339 {
henryeshbaugh 28:8076013fbef5 340 /* shadow output variables so writes are guaranteed atomic */
henryeshbaugh 27:d50f1914f23a 341 uint64_t new_key_;
henryeshbaugh 27:d50f1914f23a 342 int32_t torque_;
henryeshbaugh 27:d50f1914f23a 343 int32_t target_speed_;
henryeshbaugh 27:d50f1914f23a 344 float rotations_pending_;
henryeshbaugh 27:d50f1914f23a 345
henryeshbaugh 27:d50f1914f23a 346 if (sscanf(s, "R%f", &rotations_pending_)) {
henryeshbaugh 27:d50f1914f23a 347
henryeshbaugh 27:d50f1914f23a 348 rotations_pending += rotations_pending_;
henryeshbaugh 28:8076013fbef5 349 if (rotations_pending_ == 0.0f) spin_forever = true;
henryeshbaugh 28:8076013fbef5 350 else spin_forever = false;
henryeshbaugh 28:8076013fbef5 351 /* put_message(MSG_ROT_PEN, rotations_pending); */
henryeshbaugh 27:d50f1914f23a 352
henryeshbaugh 27:d50f1914f23a 353 } else if (sscanf(s, "V%d", &target_speed_)) {
henryeshbaugh 27:d50f1914f23a 354
henryeshbaugh 27:d50f1914f23a 355 target_speed = target_speed_;
henryeshbaugh 28:8076013fbef5 356 /* put_message(MSG_NEW_VEL, target_speed); */
henryeshbaugh 27:d50f1914f23a 357
henryeshbaugh 27:d50f1914f23a 358 } else if (sscanf(s, "K%llx", &new_key_)) {
henryeshbaugh 27:d50f1914f23a 359
henryeshbaugh 27:d50f1914f23a 360 new_key = new_key_;
henryeshbaugh 28:8076013fbef5 361 key_updated = true;
henryeshbaugh 28:8076013fbef5 362 /* put_message(MSG_NEW_KEY, new_key); */
henryeshbaugh 27:d50f1914f23a 363
henryeshbaugh 27:d50f1914f23a 364 } else if (sscanf(s, "T%u", &torque_)) {
henryeshbaugh 27:d50f1914f23a 365 torque = torque_;
henryeshbaugh 27:d50f1914f23a 366 photointerrupter_isr(); //Give it a kick
henryeshbaugh 28:8076013fbef5 367 /* put_message(MSG_TORQUE, torque); */
henryeshbaugh 27:d50f1914f23a 368 } else
henryeshbaugh 27:d50f1914f23a 369 put_message(MSG_INP_ERR, 0x404);
TrebleStick 14:66746291017c 370 }
TrebleStick 12:1b2e2540e4e1 371
henryeshbaugh 27:d50f1914f23a 372 void comms_in_fn()
henryeshbaugh 27:d50f1914f23a 373 {
henryeshbaugh 28:8076013fbef5 374 /* register serial interrupt handler */
henryeshbaugh 27:d50f1914f23a 375 pc.attach(&serial_isr);
TrebleStick 12:1b2e2540e4e1 376
henryeshbaugh 27:d50f1914f23a 377 char char_seq[CHAR_ARR_SIZE] = "";
henryeshbaugh 27:d50f1914f23a 378 uint8_t buf_pos = 0;
henryeshbaugh 27:d50f1914f23a 379
henryeshbaugh 27:d50f1914f23a 380 while (1) {
henryeshbaugh 27:d50f1914f23a 381 if (buf_pos >= CHAR_ARR_SIZE) {
henryeshbaugh 27:d50f1914f23a 382 put_message(MSG_OVERFLOW, buf_pos);
henryeshbaugh 27:d50f1914f23a 383 buf_pos = 0;
henryeshbaugh 27:d50f1914f23a 384 } else {
henryeshbaugh 27:d50f1914f23a 385 osEvent new_event = serial_in_queue.get();
henryeshbaugh 27:d50f1914f23a 386 uint8_t new_char = (uint8_t)new_event.value.p;
TrebleStick 12:1b2e2540e4e1 387
henryeshbaugh 27:d50f1914f23a 388 if (new_char == '\r' || new_char == '\n') {
henryeshbaugh 27:d50f1914f23a 389 char_seq[buf_pos] = '\0';
henryeshbaugh 27:d50f1914f23a 390 buf_pos = 0;
henryeshbaugh 27:d50f1914f23a 391 parse_serial_in(char_seq);
henryeshbaugh 27:d50f1914f23a 392 } else
henryeshbaugh 27:d50f1914f23a 393 char_seq[buf_pos++] = new_char;
TrebleStick 12:1b2e2540e4e1 394 }
andrebharath 9:ecef1e8cbe3d 395 }
andrebharath 9:ecef1e8cbe3d 396 }
andrebharath 9:ecef1e8cbe3d 397
henryeshbaugh 28:8076013fbef5 398 /* timer ISR to print/reset hash counts every second */
henryeshbaugh 27:d50f1914f23a 399 void do_hashcount()
henryeshbaugh 27:d50f1914f23a 400 {
henryeshbaugh 27:d50f1914f23a 401 put_message(MSG_HASHCOUNT, hashcount);
andrebharath 3:2e32d7974962 402 hashcount = 0;
andrebharath 3:2e32d7974962 403 }
andrebharath 9:ecef1e8cbe3d 404
andrebharath 9:ecef1e8cbe3d 405
henryeshbaugh 28:8076013fbef5 406 /* Set a given drive state */
henryeshbaugh 27:d50f1914f23a 407 void motor_out(int8_t driveState, uint32_t t){
TrebleStick 12:1b2e2540e4e1 408
henryeshbaugh 28:8076013fbef5 409 /* Lookup the output byte from the drive state. */
henryeshbaugh 27:d50f1914f23a 410 int8_t driveOut = drive_table[driveState & 0x07];
TrebleStick 12:1b2e2540e4e1 411
henryeshbaugh 28:8076013fbef5 412 /* Turn off first */
andrebharath 17:80159ace5ddf 413 if (~driveOut & 0x01) L1L.pulsewidth_us(0);
TrebleStick 0:88c3d6c8a4eb 414 if (~driveOut & 0x02) L1H = 1;
andrebharath 17:80159ace5ddf 415 if (~driveOut & 0x04) L2L.pulsewidth_us(0);
TrebleStick 0:88c3d6c8a4eb 416 if (~driveOut & 0x08) L2H = 1;
andrebharath 17:80159ace5ddf 417 if (~driveOut & 0x10) L3L.pulsewidth_us(0);
TrebleStick 0:88c3d6c8a4eb 418 if (~driveOut & 0x20) L3H = 1;
TrebleStick 12:1b2e2540e4e1 419
henryeshbaugh 28:8076013fbef5 420 /* Then turn on */
andrebharath 17:80159ace5ddf 421 if (driveOut & 0x01) L1L.pulsewidth_us(t);
TrebleStick 0:88c3d6c8a4eb 422 if (driveOut & 0x02) L1H = 0;
andrebharath 17:80159ace5ddf 423 if (driveOut & 0x04) L2L.pulsewidth_us(t);
TrebleStick 0:88c3d6c8a4eb 424 if (driveOut & 0x08) L2H = 0;
andrebharath 17:80159ace5ddf 425 if (driveOut & 0x10) L3L.pulsewidth_us(t);
TrebleStick 0:88c3d6c8a4eb 426 if (driveOut & 0x20) L3H = 0;
andrebharath 17:80159ace5ddf 427 }
TrebleStick 12:1b2e2540e4e1 428
henryeshbaugh 28:8076013fbef5 429 /* Convert photointerrupter inputs to a rotor state */
henryeshbaugh 27:d50f1914f23a 430 inline int8_t read_rotor_state()
henryeshbaugh 27:d50f1914f23a 431 {
henryeshbaugh 27:d50f1914f23a 432 return state_map[I1 + 2*I2 + 4*I3];
andrebharath 17:80159ace5ddf 433 }
andrebharath 9:ecef1e8cbe3d 434
henryeshbaugh 28:8076013fbef5 435 /* Basic synchronisation routine */
henryeshbaugh 27:d50f1914f23a 436 int8_t motor_home()
henryeshbaugh 27:d50f1914f23a 437 {
henryeshbaugh 28:8076013fbef5 438 /* Put the motor in drive state 0 and wait for it to stabilise */
henryeshbaugh 27:d50f1914f23a 439 motor_out(0, MAX_TORQUE);
andrebharath 3:2e32d7974962 440 wait(2.0);
TrebleStick 12:1b2e2540e4e1 441
henryeshbaugh 28:8076013fbef5 442 /* Get the rotor state */
henryeshbaugh 27:d50f1914f23a 443 return read_rotor_state();
henryeshbaugh 28:8076013fbef5 444 }
henryeshbaugh 28:8076013fbef5 445
henryeshbaugh 28:8076013fbef5 446 /* hank rulez */