Skip to content

Commit da3fc74

Browse files
committed
Attempt to add ADC calib to flash, pops correctly from shared memory, but not after arduino power cycle.
1 parent cae3e84 commit da3fc74

File tree

9 files changed

+131
-21
lines changed

9 files changed

+131
-21
lines changed

m4/src/Peripherals/ADC/ADCBoard.h

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class ADCBoard {
7373
int cs_pin;
7474
int data_ready_pin;
7575
int reset_pin;
76-
int conversion_times[NUM_CHANNELS_PER_ADC_BOARD];
76+
int board_idx;
7777
PeripheralCommsController commsController;
7878

7979
void waitDataReady() {
@@ -90,8 +90,8 @@ class ADCBoard {
9090
public:
9191
bool data_ready = false;
9292

93-
ADCBoard(int cs_pin, int data_ready_pin, int reset_pin)
94-
: cs_pin(cs_pin), data_ready_pin(data_ready_pin), reset_pin(reset_pin), commsController(cs_pin) {}
93+
ADCBoard(int cs_pin, int data_ready_pin, int reset_pin, int board_idx )
94+
: cs_pin(cs_pin), data_ready_pin(data_ready_pin), reset_pin(reset_pin), board_idx(board_idx), commsController(cs_pin) {}
9595

9696
void setup() {
9797
pinMode(reset_pin, OUTPUT);
@@ -173,6 +173,11 @@ class ADCBoard {
173173
uint32_t zeroScaleCalibrations[NUM_CHANNELS_PER_ADC_BOARD];
174174
uint32_t fullScaleCalibrations[NUM_CHANNELS_PER_ADC_BOARD];
175175

176+
float conversion_times[NUM_CHANNELS_PER_ADC_BOARD];
177+
for (int i = 0; i < NUM_CHANNELS_PER_ADC_BOARD; i++) {
178+
conversion_times[i] = getConversionTime(i);
179+
}
180+
176181
for(int i = 0; i<NUM_CHANNELS_PER_ADC_BOARD; i++) {
177182
zeroScaleCalibrations[i] = getZeroScaleCalibration(i);
178183
fullScaleCalibrations[i] = getFullScaleCalibration(i);
@@ -190,6 +195,7 @@ class ADCBoard {
190195
}
191196

192197
int getDataReadyPin() const { return data_ready_pin; }
198+
int getBoardIndex() const { return board_idx; }
193199

194200
void setReadyFlag() { data_ready = true; }
195201
void clearReadyFlag() { data_ready = false; }
@@ -353,6 +359,28 @@ class ADCBoard {
353359
return (status & (1 << adc_channel)) != 0;
354360
}
355361

362+
void hardReset() {
363+
digitalWrite(reset_pin, HIGH);
364+
digitalWrite(reset_pin, LOW);
365+
delay(5);
366+
digitalWrite(reset_pin, HIGH);
367+
368+
for (int i = 0; i < NUM_CHANNELS_PER_ADC_BOARD; i++) {
369+
idleMode(i);
370+
}
371+
}
372+
373+
void restoreCalibrationFromFlash() {
374+
CalibrationData data;
375+
m4ReceiveCalibrationData(data);
376+
int boardIndex = getBoardIndex();
377+
378+
for (int i = 0; i < NUM_CHANNELS_PER_ADC_BOARD; i++) {
379+
setZeroScaleCalibration(i, data.adc_offset[NUM_CHANNELS_PER_ADC_BOARD * boardIndex + i]);
380+
setFullScaleCalibration(i, data.adc_gain[NUM_CHANNELS_PER_ADC_BOARD * boardIndex + i]);
381+
}
382+
}
383+
356384
void reset() {
357385
digitalWrite(reset_pin, HIGH);
358386
digitalWrite(reset_pin, LOW);
@@ -372,6 +400,8 @@ class ADCBoard {
372400
data[0] = WRITE | ADDR_IO;
373401
data[1] = 0b00010001;
374402
commsController.transferADC(data, 2);
403+
404+
restoreCalibrationFromFlash();
375405
}
376406

377407
uint8_t talkADC(byte command) {
@@ -412,8 +442,6 @@ class ADCBoard {
412442
// could've done the calculation with user-given values but it's good to check
413443
float time_us = getConversionTime(channel, moreThanOneChannelActive);
414444

415-
conversion_times[channel] = time_us;
416-
417445
delayMicroseconds(100);
418446

419447
return time_us;
@@ -503,6 +531,17 @@ class ADCBoard {
503531
#endif
504532
commsController.transferADC(data, 2);
505533
waitDataReady();
534+
535+
// wait for the data ready flag to be set then store the calibration data in flash
536+
int boardIndex = getBoardIndex();
537+
538+
uint32_t zeroScaleCalibration = getZeroScaleCalibration(channel);
539+
540+
CalibrationData calibrationData;
541+
m4ReceiveCalibrationData(calibrationData);
542+
calibrationData.adc_offset[NUM_CHANNELS_PER_ADC_BOARD * boardIndex + channel] = zeroScaleCalibration;
543+
m4SendCalibrationData(calibrationData);
544+
506545
}
507546

508547
void fullScaleChannelSystemSelfCalibration(int channel) {
@@ -514,6 +553,16 @@ class ADCBoard {
514553
#endif
515554
commsController.transferADC(data, 2);
516555
waitDataReady();
556+
557+
// wait for the data ready flag to be set then store the calibration data in flash
558+
int boardIndex = getBoardIndex();
559+
560+
uint32_t fullScaleCalibration = getFullScaleCalibration(channel);
561+
562+
CalibrationData calibrationData;
563+
m4ReceiveCalibrationData(calibrationData);
564+
calibrationData.adc_gain[NUM_CHANNELS_PER_ADC_BOARD * boardIndex + channel] = fullScaleCalibration;
565+
m4SendCalibrationData(calibrationData);
517566
}
518567
};
519568

m4/src/Peripherals/ADC/ADCController.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,12 @@ class ADCController {
7171
registerMemberFunction(setChZeroScaleCalibration, "SET_ZERO_SCALE_CAL");
7272
registerMemberFunction(setChFullScaleCalibration, "SET_FULL_SCALE_CAL");
7373
registerMemberFunction(resetToPreviousConversionTimesSerial,"RESET_MAINTAIN");
74+
registerMemberFunction(hardResetAllADCBoards, "HARD_RESET");
7475
}
7576

7677
inline static void addBoard(int cs_pin, int data_ready,
77-
int reset_pin) {
78-
ADCBoard newBoard = ADCBoard(cs_pin, data_ready, reset_pin);
78+
int reset_pin, int board_idx) {
79+
ADCBoard newBoard = ADCBoard(cs_pin, data_ready, reset_pin, board_idx);
7980
adc_boards.push_back(newBoard);
8081
}
8182

@@ -249,6 +250,20 @@ class ADCController {
249250
return result.substring(0, result.length() - 1);
250251
}
251252

253+
inline static OperationResult hardResetAllADCBoards() {
254+
for (auto& board : adc_boards) {
255+
board.hardReset();
256+
}
257+
258+
// Tell system is not calibrated
259+
CalibrationData data;
260+
m4ReceiveCalibrationData(data);
261+
data.adcCalibrated = false;
262+
m4SendCalibrationData(data);
263+
264+
return OperationResult::Success("All ADC boards have been hard reset");
265+
}
266+
252267
inline static OperationResult resetAllADCBoards() {
253268
for (auto board : adc_boards) {
254269
board.reset();
@@ -289,7 +304,7 @@ class ADCController {
289304
return OperationResult::Success("CALIBRATION_FINISHED");
290305
}
291306

292-
static OperationResult setConversionTime(int adc_channel, int time_us) {
307+
static OperationResult setConversionTime(int adc_channel, float time_us) {
293308
if (!isChannelIndexValid(adc_channel)) {
294309
return OperationResult::Failure("Invalid channel index");
295310
}

m4/src/Peripherals/God.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,7 @@ class God {
139139

140140
// Attach interrupts for each ADC board's data ready pin
141141
for (int i = 0; i < numAdcBoards; i++) {
142-
uint8_t boardIndex = adcBoards[i];
143-
attachInterrupt(digitalPinToInterrupt(ADCController::getDataReadyPin(boardIndex)), isrFunctions[boardIndex], FALLING);
142+
attachInterrupt(digitalPinToInterrupt(ADCController::getDataReadyPin(adcBoards[i])), isrFunctions[i], FALLING);
144143
}
145144
#endif
146145

m4/src/UserIOHandler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct UserIOHandler {
4040
// I HIGHLY recommend using the following format: __SERIAL_NUMBER__ {2 characters representing the instrument} {4 digits for the year} {3 characters for the device ID}
4141
// The serial number ideally should be set to a default value here and then changed post-compile time using the firmware_uploader.py or patch_serial_number.py scripts.
4242
__attribute__((section(".serial_number")))
43-
inline static const char serial_number[29] = "__SERIAL_NUMBER__DA_2025_ABC";
43+
inline static const char serial_number[29] = "__SERIAL_NUMBER__DA_2025_001";
4444

4545
static OperationResult serialNumber() {
4646
return OperationResult::Success(serial_number + 17);

m4/src/Utils/CalibrationData.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@
33
struct CalibrationData {
44
float gain[16];
55
float offset[16];
6+
7+
bool adcCalibrated = false;
8+
uint32_t adc_offset[16];
9+
uint32_t adc_gain[16];
610
};

m4/src/Utils/TimingUtil.h

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,34 @@ struct TimingUtil {
115115
TIM8->CR1 |= TIM_CR1_CEN;
116116
}
117117

118-
inline static void setupTimersTimeSeries(uint32_t dac_period_us,
119-
uint32_t adc_period_us) {
118+
inline static void setupTimersTimeSeries(uint32_t dac_period_us, uint32_t adc_period_us) {
119+
//******************************************************************/
120+
// setupTimersTimeSeries takes in two periods in microseconds and
121+
// setups two individual timers to trigger interrupts based on their
122+
// respective counter over flow. The two timers run indpendent of
123+
// each other, but are synchronized to the same clock source.
124+
// The first timer (TIM1) is used for DAC updates, and the second timer
125+
// (TIM8) is used for ADC sampling.
126+
//******************************************************************/
120127
resetTimers();
121128

122129
// Enable TIM1 and TIM8 clocks
123130
__HAL_RCC_TIM1_CLK_ENABLE();
124131
__HAL_RCC_TIM8_CLK_ENABLE();
125132

133+
// Get the timer clock frequency
126134
uint64_t timerClock = 2 * HAL_RCC_GetPCLK2Freq();
127135

136+
// Calculate total timer ticks for the desired periods (in µs)
128137
uint64_t total_ticks_dac = (dac_period_us * timerClock) / 1000000;
129138

130139
uint16_t psc_dac;
131140
uint16_t arr_dac;
132141

142+
// Determine prescaler and 16-bit auto-reload value for TIM1 (DAC)
143+
// If total_ticks_dac is less than or equal to 65536, no prescaling is needed and we can use the full 16-bit resolution of the timer.
144+
// Otherwise, we need to compute the minimal prescaler (clock division = (PSC+1)) so that ARR <= 65535 and adjust the ARR value accordingly.
145+
133146
if (total_ticks_dac <= 65536) {
134147
psc_dac = 0; // No prescaling
135148
arr_dac = total_ticks_dac - 1; // Full resolution within 16 bits
@@ -140,6 +153,7 @@ struct TimingUtil {
140153
arr_dac = (total_ticks_dac / prescaler_dac) - 1; // ARR counts from 0 to ARR, hence subtract 1
141154
}
142155

156+
// Determine prescaler and 16-bit auto-reload value for TIM8 (ADC)
143157
uint64_t total_ticks_adc = (adc_period_us * timerClock) / 1000000;
144158

145159
uint16_t psc_adc;
@@ -161,21 +175,19 @@ struct TimingUtil {
161175
TIM1->CR1 = TIM_CR1_ARPE;
162176
TIM1->DIER |= TIM_DIER_UIE;
163177

178+
// Clear update interrupt flag and enable update event generation flags for TIM1
164179
TIM1->EGR |= 0x01;
165180
TIM1->SR &= ~TIM_SR_UIF;
166-
TIM1->EGR |= 0x02;
167-
TIM1->CCR1 &= ~TIM_SR_CC1IF;
168181

169182
// Configure TIM8
170183
TIM8->PSC = psc_adc;
171184
TIM8->ARR = arr_adc;
172185
TIM8->CR1 = TIM_CR1_ARPE;
173186
TIM8->DIER |= TIM_DIER_UIE;
174187

188+
// Clear update interrupt flag and enable update event generation flags for TIM8
175189
TIM8->EGR |= 0x01;
176190
TIM8->SR &= ~TIM_SR_UIF;
177-
TIM8->EGR |= 0x02;
178-
TIM8->CCR1 &= ~TIM_SR_CC1IF;
179191

180192
// Enable interrupts
181193
NVIC_SetPriority(TIM1_UP_IRQn, 2);
@@ -252,15 +264,21 @@ struct TimingUtil {
252264
// No phase shift: use the update interrupt for ADC triggering.
253265
TIM8->DIER |= TIM_DIER_UIE;
254266
}
267+
// Clear update interrupt flag and enable update event generation flags for TIM1
255268
TIM1->EGR |= 0x01;
256269
TIM1->SR &= ~TIM_SR_UIF;
257270
TIM1->EGR |= 0x02;
258-
TIM1->CCR1 &= ~TIM_SR_CC1IF;
271+
TIM1->SR &= ~TIM_SR_CC1IF;
272+
273+
//Clear update interrupt flag and enable update event generation flags for TIM8
274+
TIM8->EGR |= 0x01;
275+
TIM8->SR &= ~TIM_SR_UIF;
276+
TIM8->EGR |= 0x02;
277+
TIM8->SR &= ~TIM_SR_CC1IF;
259278

260279
NVIC_SetPriority(TIM1_UP_IRQn, 2);
261280
NVIC_EnableIRQ(TIM1_UP_IRQn);
262281

263-
264282
NVIC_SetPriority(TIM8_CC_IRQn, 3);
265283
NVIC_EnableIRQ(TIM8_CC_IRQn);
266284

m4/src/main.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void setup() {
4343
}
4444

4545
for (int i=0; i<NUM_ADC_BOARDS; i++) {
46-
ADCController::addBoard(adc_cs_pins[i], drdy[i], reset[i]);
46+
ADCController::addBoard(adc_cs_pins[i], drdy[i], reset[i], i);
4747
}
4848

4949
DACController::setup();
@@ -67,9 +67,27 @@ void setup() {
6767
DACController::setCalibration(i, calibrationData.offset[i], calibrationData.gain[i]);
6868
}
6969

70-
}
70+
// Set calibrations for ADC
71+
if (!calibrationData.adcCalibrated) {
72+
// If ADC is not calibrated, reset ADC to all initial values
73+
ADCController::hardResetAllADCBoards();
74+
for (int i = 0; i < NUM_ADC_BOARDS * NUM_CHANNELS_PER_ADC_BOARD; i++) {
75+
uint32_t zeroScaleCalibration = ADCController::getChZeroScaleCalibration(i).getMessage().toInt();
76+
uint32_t fullScaleCalibration = ADCController::getChFullScaleCalibration(i).getMessage().toInt();
7177

78+
calibrationData.adc_offset[i] = zeroScaleCalibration;
79+
calibrationData.adc_gain[i] = fullScaleCalibration;
7280

81+
calibrationData.adcCalibrated = true;
82+
}
83+
m4SendCalibrationData(calibrationData);
84+
} else {
85+
for (int i=0; i<NUM_ADC_BOARDS * NUM_CHANNELS_PER_ADC_BOARD; i++) {
86+
ADCController::setChZeroScaleCalibration(i, calibrationData.adc_offset[i]);
87+
ADCController::setChFullScaleCalibration(i, calibrationData.adc_gain[i]);
88+
}
89+
}
90+
}
7391

7492
void loop() {
7593
UserIOHandler::handleUserIO();

m7/src/Utils/CalibrationData.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@
33
struct CalibrationData {
44
float gain[16];
55
float offset[16];
6+
7+
bool adcCalibrated = false; // Flag to indicate if ADC calibration is done
8+
uint32_t adc_offset[16];
9+
uint32_t adc_gain[16];
610
};

m7/src/main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ void setup()
157157
{
158158
calibrationData.gain[i] = 1.0f;
159159
calibrationData.offset[i] = 0.0f;
160+
calibrationData.adc_offset[i] = 0x800000; // Default ADC offset
161+
calibrationData.adc_gain[i] = 0x200000; // Default ADC gain
162+
160163
}
161164
}
162165
else

0 commit comments

Comments
 (0)