Shield Code 6.0
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1
41//========== Libraries ==========//
42#include <Arduino.h>
43#include <Pip.hpp> //note, Max1148 isn't included because it's included in Pip
44#include <PDC.hpp>
45#include <AT25M02.hpp>
46#include <PipController.hpp>
47//========== For IMU ==========//
48#include <IMU.hpp> // Library to initialize and sample IMU
49#include <Wire.h> // I2C communications
50#include <LSM6.h> // Library for the gyro/accelerometer
51#include <LIS3MDL.h> // Library for the LIS3MDL 3-axis magnetometer
52
53//========== Timing ==========//
54// SAMPLE_PERIOD defined in sweep_values_v5.1h
55#define BUFFER 1000 // buffer to wait period of missed measurement
56#define SWEEP_OFFSET 500
57#define RAM_BUFFER_DELAY 10 // Delay in seconds until the chip starts sending saved data.
58
59//========== Debugging ==========//
60void blink();
61bool debug = false;
63
64//========== Sweep Parameters ==========//
65#define SWEEP_STEPS 28 // Number of steps in sweep
66// Sweep range set with SHIELD_NUMBER in sweep_values_v5_1.h
67#define SHIELD_NUMBER 5
68#include "sweep_values_v5_1.h"
69
70// These two set the step duration, which sets the sweep duration (11.23 ms).
71// This works out to being 2.0 degrees rotation of the main payload while sweeping.
72// Natural delay of ~76 us after setting DAC.
73// Adding 124 us delay to make it 200 us between DAC and ADC.
74
75#define SWEEP_DELAY 46.875 // Old version was 1500 clock cycles on a 32 MHz processor. comes out to this in us
76#define SWEEP_AVERAGES 8 // each sample ~20-21 us
77
78//========== Class Declarations ==========//
80
83
87
88LIS3MDL compass;
89LSM6 gyro;
91
92//========== Sweep Variable ==========//
93uint8_t shieldID = 60;
94
95//========== Buffers and Messaging ==========//
96int16_t IMUData[10];
97uint32_t IMUTimeStamp;
99// Use J & T for buffered messages (sentinel + 1)
100uint8_t sweepSentinel[3] = {'#', '#', 'S'}; // 3 bytes: "##S"
101uint8_t sweepSentinelBuf[3] = {'#', '#', 'T'}; // 3 bytes: "##T"
102uint8_t imuSentinel[3] = {'#', '#', 'I'};
103uint8_t imuSentinelBuf[3] = {'#', '#', 'J'};
104
105bool savedSweep = false; // If we have a saved sweep to send
106bool sendFromRam = false; // When to send from ram
107bool storeToRam = true; // Save data to the ram chip
108
109//buffer for combined sweep data
110uint16_t sweep_buffer[2*SWEEP_STEPS]; //112 bytes
111
112
113
114//========== Main Loop Timing ==========//
115uint32_t startTime = 0;
116uint32_t sweepStartTime = 0;
117uint32_t sweepTimeStamp = 0;
119
120//========== Buffer for Ram ==========//
121#define IMU_TIMESTAMP_OFFSET 0
122#define IMU_DATA_OFFSET (sizeof(IMUTimeStamp) + IMU_TIMESTAMP_OFFSET)
123#define SWEEP_TIMESTAMP_OFFSET (sizeof(IMUData) + IMU_DATA_OFFSET)
124#define SWEEP_DATA_OFFSET (sizeof(sweepTimeStamp) + SWEEP_TIMESTAMP_OFFSET)
125#define RAM_BUF_LEN (sizeof(IMUTimeStamp) + sizeof(IMUData) + sizeof(sweepTimeStamp) + sizeof(sweep_buffer)) //140 bytes, plus 7 bytes for sentinels/id
126// Stores the IMU data then the Sweep data
128
129const size_t totalSize = 294;
132//========== Interrupt Timing ==========//
133#define SYNC_PIN 53
134volatile uint32_t timer;
135volatile bool syncPulse;
136volatile bool newCycle;
138void syncHandler();
139
140//========== Finite State Machine States ==========//
152 read
155
156//FSM function prototypes
157void FSMUpdate();
158void FSMAction();
159void startSweepOnShield();
162void takeIMUData();
164void storeData();
165void readData();
166void sendData();
167
168bool isFirst = true;
169
170void setup() {
171 if(debug){
172 // Configure serial, 230.4 kb/s baud rate
173 //12.4 ms per message
174 Serial.begin(230400);
175 // Setup IMU
176 initIMU(&compass, &gyro);
177
178
179 // Setup PDC
180 pdc.init();
181 SPI.begin();
182
183 // Initialize time
184 //startTime = micros();
185 }
186 else{
187 // Configure serial, 230.4 kb/s baud rate
188 delay(200);
189 pinMode(LED_BUILTIN, OUTPUT);
190 digitalWrite(LED_BUILTIN, LOW);
191
192 Serial.begin(230400);
193 // Setup IMU
194 initIMU(&compass, &gyro);
195
196 SPI.begin();
197
198 // Setup RAM
199 ram.init();
200
201 // Setup PDC - must be called after Serial.begin()
202 pdc.init();
203
204 // Initialize time
205 startTime = micros();
206
207 // Configure the timer interrupt
209 //configure the external interrupt
210 pinMode(SYNC_PIN, INPUT_PULLUP);
211 attachInterrupt(digitalPinToInterrupt(SYNC_PIN), syncHandler, FALLING);
212 pinMode(7, OUTPUT);
213
214 }
215}
216
217void loop() {
218 if(debug){
219 takeIMUData();
220 //sendIMUData();
221 delay(500);
222 }
223 else{
224 FSMUpdate();
225 FSMAction();
226 }
227}
228
236 switch(currentState){
237 case idle: {
238 if (syncPulse) {
239 syncPulse = false;
240 return;
241 }
242 volatile uint32_t irq_state = __get_PRIMASK();
243 __disable_irq();
244 if (micros() - timer > SWEEP_OFFSET) {
245 if (isFirst){
246 isFirst = false;
247 timer = micros();
248 newCycle = false;
249 }
251 }
252 __set_PRIMASK(irq_state);
253 break;
254 }
255
256 case startSweep: {
257 if (syncPulse) {
259 syncPulse = false;
260 } else {
262 }
263 break;
264 }
265
266 case takeIMU: {
267 if (syncPulse) {
269 syncPulse = false;
270 } else {
272 }
273 break;
274 }
275 case read:
276 if (syncPulse) {
278 syncPulse = false;
279 } else {
281 }
282 break;
283 case store: {
284 if (syncPulse) {
286 syncPulse = false;
287 } else {
289 }
290 break;
291 }
292
293 case waitForNewCycle: {
294 if (newCycle || syncPulse) {
296 newCycle = false;
297 syncPulse = false;
298 }
299 break;
300 }
301 case interrupted: {
303 break;
304 }
305 default: {
307 break;
308 }
309}
310
311/*
312 case sendSweep: {
313 if (syncPulse) {
314 currentState = interrupted;
315 syncPulse = false;
316 } else {
317 currentState = startSweep;
318 }
319 break;
320 }
321 case sendIMU: {
322 if (syncPulse) {
323 currentState = interrupted;
324 syncPulse = false;
325 } else {
326 currentState = sendStored;
327 }
328 break;
329 }
330 case sendStored: {
331 if (syncPulse) {
332 currentState = interrupted;
333 syncPulse = false;
334 } else {
335 currentState = waitForNewCycle;
336 }
337 break;
338 }
339
340 */
341
342
343
344
345
346
347}
348
355 switch(currentState){
356 case idle:
357 break;
358 case startSweep:
360 break;
361 case sendSweep:
362 //sendSweepData();
363 break;
364 case takeIMU:
365 takeIMUData();
366 break;
367 case sendIMU:
368 //sendIMUData();
369 break;
370 case sendStored:
371 //sendStoredData();
372 break;
373 case waitForNewCycle:
374 break;
375 case store:
376 storeData();
377 break;
378 case read:
379 readData();
380 break;
381 case interrupted:
382 savedSweep = false;
383 break;
384 default:
385 break;
386 }
387}
388
392void blink(){
393 digitalWrite(LED_BUILTIN, HIGH);
394 delay(200);
395 digitalWrite(LED_BUILTIN, LOW);
396 delay(200);
397}
398
402bool goLow = true;
404 if (goLow){
405 goLow=false;
406 }
407 // Clear the status register. This is necessary to prevent the interrupt from being called repeatedly.
408 TC_GetStatus(TC0, 0);
409
410 if (micros() - timer >= SAMPLE_PERIOD) {
411 goLow=true;
412 newCycle = true;
413 timer = micros();
414 }
415}
416
418 timer = micros();
419 syncPulse = true;
420}
421
432 // Enable the clock to the TC0 peripheral
433 pmc_enable_periph_clk(ID_TC0);
434
435 /*Configures the timer:
436 - First two parameters set it to RC compare waveform mode. This means the timer resets when it reaches the value in RC.
437 - The third parameter sets the clock source to MCK/128. MCK is at 84 MHz, so this sets the clock to 656.25 kHz.
438 */
439 TC_Configure(TC0, 0, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
440 //RC sets the value that the counter reaches before triggering the interrupt
441 //This sets it to 10kHz
442 TC_SetRC(TC0, 0, 64.625); //
443
444 // Enable the interrupt RC compare interrupt
445 TC0->TC_CHANNEL[0].TC_IER = TC_IER_CPCS;
446 // Disable all other TC0 interrupts
447 TC0->TC_CHANNEL[0].TC_IDR = ~TC_IER_CPCS;
448 NVIC_EnableIRQ(TC0_IRQn);
449 NVIC_SetPriority(TC0_IRQn, 0);
450
451 TC_Start(TC0, 0);
452}
453
454
455
460 //take timestamp
461 int lastTime = sweepTimeStamp;
462 sweepStartTime = micros();
464 //this was here for debugging state machine timing discontinuities
465 if(sweepTimeStamp-lastTime<22000){
466 pinMode(6, OUTPUT);
467 digitalWrite(6, HIGH);
468 }
469 else{
470 pinMode(6, OUTPUT);
471 digitalWrite(6, LOW);
472 }
473 sendData();
475 memcpy(sweep_buffer, pip0.data, SWEEP_STEPS*sizeof(uint16_t));
476 //copy pip data into combined buffer
477 memcpy(sweep_buffer + SWEEP_STEPS, pip1.data, SWEEP_STEPS*sizeof(uint16_t));
478 savedSweep=true;
479}
480
481
483 IMUTimeStamp = micros() - startTime;
485}
486
488 if (storeToRam){
489 ram.writeData((uint8_t *)&IMUTimeStamp, sizeof(IMUTimeStamp));
490 ram.writeData((uint8_t *)IMUData, sizeof(IMUData));
491 ram.writeData((uint8_t *)&sweepTimeStamp, sizeof(sweepTimeStamp));
492 ram.writeData((uint8_t *)sweep_buffer, sizeof(sweep_buffer));
493 }
494}
495
496void readData(){
497 if(sendFromRam){
499 }
500}
501
502int shortSize = sizeof(sweepSentinel)+sizeof(sweepTimeStamp)+sizeof(sweep_buffer)+sizeof(imuSentinel)+sizeof(IMUTimeStamp)+sizeof(IMUData);
503
504void sendData(){
505 if(!savedSweep){
506 return;
507 }
508 if (!sendFromRam && micros() - startTime > RAM_BUFFER_DELAY * 1000000) {
509 sendFromRam = true;
510 }
513 // 1. Copy sweepSentinel (3 bytes: e.g., { '#', '#', 'S' }).
515 p_memory_block += sizeof(sweepSentinel);
516
517 // 3. Copy sweep timestamp from ramBuf (4 bytes).
520
521 // 2. Copy payload ID (1 byte) using shieldID.
522 memcpy(p_memory_block, &shieldID, sizeof(shieldID));
523 p_memory_block += sizeof(shieldID);
524
525
526 // 4. Copy sweep ADC data (sweep_buffer).
527 memcpy(p_memory_block, sweep_buffer, sizeof(sweep_buffer));
528 p_memory_block += sizeof(sweep_buffer);
529
530 memcpy(p_memory_block, imuSentinel, sizeof(imuSentinel));
531 p_memory_block += sizeof(imuSentinel);
533 p_memory_block += sizeof(IMUTimeStamp);
534 memcpy(p_memory_block, IMUData, sizeof(IMUData));
535 p_memory_block += sizeof(IMUData);
539 p_memory_block += sizeof(IMUTimeStamp);
540 memcpy(p_memory_block, ramBuf + IMU_DATA_OFFSET, sizeof(IMUData));
541 p_memory_block += sizeof(IMUData);
546 memcpy(p_memory_block, &shieldID, sizeof(shieldID));
547 p_memory_block += sizeof(shieldID);
549
552 } else {
553 // Non-RAM branch:
554 // 1. Copy sweepSentinel (3 bytes).
556 p_memory_block += sizeof(sweepSentinel);
557 // 3. Copy sweep timestamp from p_sweepTimeStamp (4 bytes).
560 // 2. Copy payload ID (1 byte) as shieldID.
561 memcpy(p_memory_block, &shieldID, sizeof(shieldID));
562 p_memory_block += sizeof(shieldID);
563
564
565
566
567 // 4. Copy sweep ADC data.
568 memcpy(p_memory_block, sweep_buffer, sizeof(sweep_buffer));
569 p_memory_block += sizeof(sweep_buffer);
570
571 memcpy(p_memory_block, imuSentinel, sizeof(imuSentinel));
572 p_memory_block += sizeof(imuSentinel);
574 p_memory_block += sizeof(IMUTimeStamp);
575 memcpy(p_memory_block, IMUData, sizeof(IMUData));
576
577 // Structure: [3-byte sentinel]["4-byte timestamp"]["1-byte payload ID"][sweep data]...
578 p_memory_block += sizeof(IMUData);
580 }
581
582}
583
584/* void sendSweepData(){
585 if(!savedSweep){
586 return;
587 }
588
589
590 pdc.send(sweepSentinel, sizeof(sweepSentinel));
591 pdc.send_next(p_sweepTimeStamp, sizeof(sweepTimeStamp));
592 pdc.send_next(sweep_buffer, sizeof(sweep_buffer));
593 savedSweep = false;
594
595}
596
597void sendIMUData(){
598 pdc.send(imuSentinel, sizeof(imuSentinel));
599 pdc.send_next(p_IMUTimeStamp, sizeof(IMUTimeStamp));
600 pdc.send(IMUData, sizeof(IMUData));
601} */
602/* void sendStoredData(){
603 if (!sendFromRam && micros() - startTime > RAM_BUFFER_DELAY * 1000000) {
604 sendFromRam = true;
605 }
606 // Send from ram when ready & have data
607 if (sendFromRam && ram.usedBytes()>=RAM_BUF_LEN) {
608 ram.readData(ramBuf, RAM_BUF_LEN);
609 pdc.send(imuSentinelBuf, sizeof(imuSentinelBuf));
610 pdc.send(ramBuf, sizeof(IMUTimeStamp));
611 pdc.send(ramBuf + IMU_DATA_OFFSET, sizeof(IMUData));
612 pdc.send(sweepSentinelBuf, sizeof(sweepSentinelBuf));
613 pdc.send(ramBuf + SWEEP_TIMESTAMP_OFFSET, sizeof(sweepTimeStamp));
614 pdc.send(ramBuf + SWEEP_DATA_OFFSET, sizeof(sweep_buffer));
615 }
616 // Write IMU then sweep data to the ram at once.
617 if (storeToRam){
618 ram.writeData((uint8_t *)&IMUTimeStamp, sizeof(IMUTimeStamp));
619 ram.writeData((uint8_t *)IMUData, sizeof(IMUData));
620 ram.writeData((uint8_t *)&sweepTimeStamp, sizeof(sweepTimeStamp));
621 ram.writeData((uint8_t *)sweep_buffer, sizeof(sweep_buffer));
622 //ram.writeData((uint8_t*)pip0.data, sizeof(pip0.data));
623 //ram.writeData((uint8_t*)pip1.data, sizeof(pip1.data));
624 }
625} */
Provides a library to interact with Microchip's AT25M02 chip. This treats the chip as a circular queu...
void initIMU(LIS3MDL *mag, LSM6 *gyro_acc)
Definition: IMU.cpp:15
void sampleIMU(LIS3MDL *mag, LSM6 *imu, int16_t *data)
Definition: IMU.cpp:80
Header file for the IMU library for Dartmouth's 317 Lab.
Header file for the PDC library for Dartmouth's 317 Lab.
Header file for the Pip library for Dartmouth's 317 Lab.
Interfaces with the AT25M02 EEPROM chip.
Definition: AT25M02.hpp:33
int readData(byte *dest, uint32_t length)
Write the given number of bytes from the ram into the destination array. These bytes are taken from t...
Definition: AT25M02.cpp:172
void init()
Initialize the AT25M02 EEPROM device. Define spi settings, chip select pin, and set initial variables...
Definition: AT25M02.cpp:39
bool writeData(byte *bytes, uint32_t length)
Write from the given array to the memory. This data is appended to the end of the queue....
Definition: AT25M02.cpp:98
uint32_t usedBytes()
Returns the number of bytes currently being used.
Definition: AT25M02.cpp:63
Manages interfacing with Max1148 ADC.
Definition: Max1148.hpp:57
Manages UART transmits through peripheral DMA controller (PDC).
Definition: PDC.hpp:33
void init()
Turns on PDC, waits until ready. Must be called AFTER Serial.begin() in setup().
Definition: PDC.hpp:67
void send(T *buffer, int size)
Adds data to the PDC buffer to be sent out through UART.
Definition: PDC.hpp:96
Manages simultaneous sweep for two Pip sensors. A bit hacky, but allows easily managing simultaneous ...
void sweep()
Sweeps both DACs simultaneously, reads both ADC channels. Note that ADC sampling alternates between e...
Manages the Pip sensor sweep and associated data.
Definition: Pip.hpp:33
uint16_t data[SWEEP_MAX_SAMPLES]
The data array for the sweep.
Definition: Pip.hpp:81
Pip pip0(SWEEP_DELAY, SWEEP_AVERAGES, SWEEP_STEPS, 339, 3752, DAC0, adc0)
void syncHandler()
Definition: main.cpp:417
AT25M02 ram
Definition: main.cpp:90
bool isFirst
Definition: main.cpp:168
bool sendFromRam
Definition: main.cpp:106
const size_t totalSize
Definition: main.cpp:129
bool goLow
Interrupt handler for the TC0 timer.
Definition: main.cpp:402
int shortSize
Definition: main.cpp:502
uint8_t shieldID
Definition: main.cpp:93
void FSMAction()
Finite State Machine action function.
Definition: main.cpp:354
PipController pipController(pip0, pip1)
BobState currentState
Definition: main.cpp:154
void TC0_Handler()
Definition: main.cpp:403
int16_t IMUData[10]
Definition: main.cpp:96
uint8_t memory_block[totalSize]
Definition: main.cpp:130
void configureTimerInterrupt()
Configures timer counter for interrupt Documentation for internal functions - see tc....
Definition: main.cpp:431
#define RAM_BUFFER_DELAY
Definition: main.cpp:57
bool debug
Definition: main.cpp:61
LSM6 gyro
Definition: main.cpp:89
void takeIMUData()
Definition: main.cpp:482
void setup()
Definition: main.cpp:170
uint32_t IMUTimeStamp
Definition: main.cpp:97
void blink()
Blinks the onboard LED. Used for debugging.
Definition: main.cpp:392
uint8_t imuSentinel[3]
Definition: main.cpp:102
uint8_t sweepSentinelBuf[3]
Definition: main.cpp:101
uint8_t * p_memory_block
Definition: main.cpp:131
#define SYNC_PIN
Definition: main.cpp:133
#define SWEEP_TIMESTAMP_OFFSET
Definition: main.cpp:123
void storeData()
Definition: main.cpp:487
#define SWEEP_STEPS
Definition: main.cpp:65
uint32_t startTime
Definition: main.cpp:115
bool storeToRam
Definition: main.cpp:107
uint16_t sweep_buffer[2 *SWEEP_STEPS]
Definition: main.cpp:110
uint8_t ramBuf[RAM_BUF_LEN]
Definition: main.cpp:127
Pip pip1(SWEEP_DELAY, SWEEP_AVERAGES, SWEEP_STEPS, 339, 3752, DAC1, adc1)
void sendData()
Definition: main.cpp:504
#define IMU_DATA_OFFSET
Definition: main.cpp:122
int cycle_counter
Definition: main.cpp:62
void startSweepOnShield()
Attaches last data buffer to UART PDC, runs DAC sweep, and saves pip data into a combined buffer.
Definition: main.cpp:459
void FSMUpdate()
Finite State Machine update function.
Definition: main.cpp:235
void sendIMUData()
PDC pdc
Definition: main.cpp:79
void readData()
Definition: main.cpp:496
uint32_t * p_IMUTimeStamp
Definition: main.cpp:98
LIS3MDL compass
Definition: main.cpp:88
Max1148 adc0(Channel::CHAN2)
volatile bool syncPulse
Definition: main.cpp:135
uint8_t imuSentinelBuf[3]
Definition: main.cpp:103
uint8_t sweepSentinel[3]
Definition: main.cpp:100
volatile uint32_t timer
Definition: main.cpp:134
uint32_t sweepTimeStamp
Definition: main.cpp:117
void sendSweepData()
#define SWEEP_OFFSET
Definition: main.cpp:56
#define IMU_TIMESTAMP_OFFSET
Definition: main.cpp:121
void sendStoredData()
bool savedSweep
Definition: main.cpp:105
Max1148 adc1(Channel::CHAN1)
BobState
Definition: main.cpp:141
@ interrupted
Definition: main.cpp:150
@ store
Definition: main.cpp:151
@ idle
Definition: main.cpp:142
@ sendTimeStamps
Definition: main.cpp:148
@ sendIMU
Definition: main.cpp:146
@ takeIMU
Definition: main.cpp:145
@ sendSweep
Definition: main.cpp:144
@ startSweep
Definition: main.cpp:143
@ sendStored
Definition: main.cpp:147
@ waitForNewCycle
Definition: main.cpp:149
@ read
Definition: main.cpp:152
uint32_t sweepStartTime
Definition: main.cpp:116
#define SWEEP_DELAY
Definition: main.cpp:75
#define RAM_BUF_LEN
Definition: main.cpp:125
#define SWEEP_DATA_OFFSET
Definition: main.cpp:124
uint32_t * p_sweepTimeStamp
Definition: main.cpp:118
volatile bool newCycle
Definition: main.cpp:136
void loop()
Definition: main.cpp:217
#define SWEEP_AVERAGES
Definition: main.cpp:76