Skip to content

Commit 20effdd

Browse files
committed
AWG initial test
1 parent 4ffac30 commit 20effdd

File tree

2 files changed

+287
-0
lines changed

2 files changed

+287
-0
lines changed

m4/src/Peripherals/God.h

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class God {
2222
registerMemberFunction(initialize, "INNIT");
2323
registerMemberFunctionVector(timeSeriesBufferRampWrapper, "TIME_SERIES_BUFFER_RAMP");
2424
registerMemberFunctionVector(dacLedBufferRampWrapper, "DAC_LED_BUFFER_RAMP");
25+
registerMemberFunctionVector(AWGBufferRampWrapper, "AWG_BUFFER_RAMP");
2526
registerMemberFunctionVector(timeSeriesAdcRead, "TIME_SERIES_ADC_READ");
2627
registerMemberFunction(dacChannelCalibration, "DAC_CH_CAL");
2728
registerMemberFunctionVector(boxcarAverageRamp, "BOXCAR_BUFFER_RAMP");
@@ -747,6 +748,282 @@ class God {
747748
return OperationResult::Success();
748749
}
749750

751+
752+
static OperationResult AWGBufferRampWrapper(std::vector<float> args) {
753+
// Expected argument order:
754+
// [numDacChannels, numAdcChannels, numLoops, numDacStepsPerLoop, numAdcAverages, dac_interval_us, dac_settling_time_us, <dacChannels...>, <adcChannels...>, <dacVoltageLists...>]
755+
// The number of DAC and ADC channels determines how many channel indices and voltage lists to expect.
756+
757+
if (args.size() < 7) {
758+
return OperationResult::Failure("Insufficient arguments for AWGBufferRampWrapper");
759+
}
760+
761+
int idx = 0;
762+
int numDacChannels = static_cast<int>(args[idx++]);
763+
int numAdcChannels = static_cast<int>(args[idx++]);
764+
int numLoops = static_cast<int>(args[idx++]);
765+
int numDacStepsPerLoop = static_cast<int>(args[idx++]);
766+
int numAdcAverages = static_cast<int>(args[idx++]);
767+
uint32_t dac_interval_us = static_cast<uint32_t>(args[idx++]);
768+
uint32_t dac_settling_time_us = static_cast<uint32_t>(args[idx++]);
769+
770+
// Check for valid channel counts
771+
if (numDacChannels < 1 || numAdcChannels < 1 || numLoops < 1 || numDacStepsPerLoop < 1 || numAdcAverages < 1) {
772+
return OperationResult::Failure("Invalid channel or loop/step/average count");
773+
}
774+
775+
// Check if enough arguments for channel indices
776+
if (args.size() < idx + numDacChannels + numAdcChannels) {
777+
return OperationResult::Failure("Insufficient arguments for channel indices");
778+
}
779+
780+
// Parse DAC channel indices
781+
int dacChannels[numDacChannels];
782+
for (int i = 0; i < numDacChannels; ++i) {
783+
dacChannels[i] = static_cast<int>(args[idx++]);
784+
}
785+
786+
// Parse ADC channel indices
787+
int adcChannels[numAdcChannels];
788+
for (int i = 0; i < numAdcChannels; ++i) {
789+
adcChannels[i] = static_cast<int>(args[idx++]);
790+
}
791+
792+
// Now, expect numDacChannels blocks of numDacStepsPerLoop floats for the DAC voltage lists
793+
int expectedVoltageListSize = numDacChannels * numDacStepsPerLoop;
794+
if (args.size() < idx + expectedVoltageListSize) {
795+
return OperationResult::Failure("Insufficient arguments for DAC voltage lists");
796+
}
797+
798+
// Allocate and fill DAC voltage lists
799+
float* dacVoltageLists[numDacChannels];
800+
for (int i = 0; i < numDacChannels; ++i) {
801+
dacVoltageLists[i] = new float[numDacStepsPerLoop];
802+
for (int j = 0; j < numDacStepsPerLoop; ++j) {
803+
dacVoltageLists[i][j] = args[idx++];
804+
}
805+
}
806+
807+
// Call the base function
808+
OperationResult result = AWGBufferRampBase(
809+
numDacChannels, numAdcChannels, numLoops, numDacStepsPerLoop, numAdcAverages,
810+
dac_interval_us, dac_settling_time_us, dacChannels, dacVoltageLists, adcChannels
811+
);
812+
813+
// Clean up allocated memory
814+
for (int i = 0; i < numDacChannels; ++i) {
815+
delete[] dacVoltageLists[i];
816+
}
817+
818+
return result;
819+
}
820+
821+
822+
static OperationResult AWGBufferRampBase(
823+
int numDacChannels, int numAdcChannels, int numLoops, int numDacStepsPerLoop, int numAdcAverages,
824+
uint32_t dac_interval_us, uint32_t dac_settling_time_us, int* dacChannels,
825+
float** dacVoltageLists, int* adcChannels) {
826+
if (dac_settling_time_us < 1 || dac_interval_us < 1) {
827+
return OperationResult::Failure("Invalid interval or settling time");
828+
}
829+
if (numAdcAverages < 1) {
830+
return OperationResult::Failure("Invalid number of ADC averages");
831+
}
832+
if (numLoops < 1 || numDacStepsPerLoop < 1) {
833+
return OperationResult::Failure("Invalid number of loops or steps per loop");
834+
}
835+
if (numDacChannels < 1 || numAdcChannels < 1) {
836+
return OperationResult::Failure("Invalid number of channels");
837+
}
838+
839+
double packets[numAdcChannels];
840+
double numAdcAveragesInv = 1.0 / static_cast<double>(numAdcAverages);
841+
842+
setStopFlag(false);
843+
PeripheralCommsController::dataLedOn();
844+
845+
ADCController::resetToPreviousConversionTimes();
846+
847+
#ifdef __NEW_DAC_ADC__
848+
digitalWrite(adc_sync, LOW);
849+
850+
static void (*isrFunctions[])() = {
851+
TimingUtil::adcSyncISR<0>,
852+
TimingUtil::adcSyncISR<1>,
853+
TimingUtil::adcSyncISR<2>,
854+
TimingUtil::adcSyncISR<3>
855+
};
856+
857+
std::vector<uint8_t> boards;
858+
859+
for (int i = 0; i < numAdcChannels; ++i) {
860+
int ch = adcChannels[i];
861+
if (ch < 0) continue; // skip invalid values
862+
uint8_t board = ch / 4; // 0‑based board index
863+
if (std::find(boards.begin(), boards.end(), board) == boards.end())
864+
boards.push_back(board); // keep only unique board numbers
865+
}
866+
867+
std::sort(boards.begin(), boards.end());
868+
869+
int numAdcBoards = boards.size();
870+
871+
//check to see if buffer ramp is compatible with the current ADC configuration
872+
float convTimeSum[4] = {0.0, 0.0, 0.0, 0.0};
873+
uint8_t board_num = 0;
874+
int chNum = 0;
875+
for (int i = 0; i < numAdcChannels; i++) {
876+
chNum = adcChannels[i];
877+
board_num = chNum / 4; // 0-based board index
878+
convTimeSum[board_num] += ADCController::getConversionTimeFloat(adcChannels[i]);
879+
}
880+
float maxConvTime = *std::max_element(std::begin(convTimeSum), std::end(convTimeSum));
881+
uint32_t totalDacSweepTime = numDacStepsPerLoop * dac_interval_us;
882+
if(maxConvTime*numAdcAverages + dac_settling_time_us + 180 >= totalDacSweepTime) {
883+
return OperationResult::Failure("DAC sweep time is too short for specified ADC conversion time, please increase dac_interval_us or reduce numDacStepsPerLoop");
884+
}
885+
886+
//We will also throw an error if the settling time is too short:
887+
if (dac_settling_time_us < 100) {
888+
return OperationResult::Failure("DAC settling time is too short, please increase it");
889+
}
890+
891+
for (int i = 0; i < numAdcBoards; i++) {
892+
attachInterrupt(digitalPinToInterrupt(ADCController::getDataReadyPin(boards[i])), isrFunctions[i], FALLING);
893+
}
894+
#endif
895+
896+
uint8_t adcMask = 0u;
897+
#ifdef __NEW_DAC_ADC__
898+
for (int i = 0; i < numAdcBoards; i++) {
899+
adcMask |= 1 << i;
900+
}
901+
#else
902+
adcMask = 1;
903+
#endif
904+
905+
// Initialize timing flags
906+
TimingUtil::dacFlag = false;
907+
TimingUtil::adcFlag = 0;
908+
909+
// Track current position in voltage lists and loop
910+
int currentLoop = 0;
911+
int currentStep = 0;
912+
int totalDacSteps = numLoops * numDacStepsPerLoop;
913+
int currentDacStep = 0;
914+
int currentAdcReads = 0;
915+
916+
// Set initial DAC voltages (first step of first loop)
917+
for (int i = 0; i < numDacChannels; i++) {
918+
DACController::setVoltageNoTransactionNoLdac(dacChannels[i], dacVoltageLists[i][0]);
919+
}
920+
currentDacStep++;
921+
currentStep = 1; // We've already set step 0
922+
923+
// Start ADC continuous conversion
924+
for (int i = 0; i < numAdcChannels; i++) {
925+
ADCController::startContinuousConversion(adcChannels[i]);
926+
#ifdef __NEW_DAC_ADC__
927+
ADCController::setRDYFN(adcChannels[i]);
928+
#endif
929+
}
930+
931+
// Setup timers for DAC and ADC events
932+
TimingUtil::setupTimersDacLed(dac_interval_us, dac_settling_time_us);
933+
TimingUtil::stopAndResetAdcTimer();
934+
TimingUtil::dacFlag = false;
935+
936+
// Main event loop using interrupt-based timing
937+
while (currentLoop < numLoops && !getStopFlag()) {
938+
__WFE(); // Wait for event (interrupt)
939+
940+
// Handle DAC flag - time to set next DAC voltage
941+
if (TimingUtil::dacFlag && currentDacStep < totalDacSteps) {
942+
#if !defined(__NEW_SHIELD__)
943+
PeripheralCommsController::beginDacTransaction();
944+
#endif
945+
for (int i = 0; i < numDacChannels; i++) {
946+
float voltage = dacVoltageLists[i][currentStep];
947+
DACController::setVoltageNoTransactionNoLdac(dacChannels[i], voltage);
948+
}
949+
#if !defined(__NEW_SHIELD__)
950+
PeripheralCommsController::endTransaction();
951+
#endif
952+
953+
TimingUtil::dacFlag = false;
954+
currentDacStep++;
955+
currentStep++;
956+
957+
// Check if we've completed a full sweep of voltages for this loop
958+
if (currentStep >= numDacStepsPerLoop) {
959+
currentStep = 0; // Reset to beginning of voltage list for next loop
960+
TimingUtil::stopAndResetAdcTimer();
961+
}
962+
}
963+
964+
// Handle ADC flag - time to read ADC after settling
965+
if (TimingUtil::adcFlag == adcMask) {
966+
#if !defined(__NEW_SHIELD__)
967+
PeripheralCommsController::beginAdcTransaction();
968+
#endif
969+
for (int i = 0; i < numAdcChannels; i++) {
970+
double total = 0.0;
971+
for (int j = 0; j < numAdcAverages; j++) {
972+
total += ADCController::getVoltageDataNoTransaction(adcChannels[i]);
973+
}
974+
packets[i] = total * numAdcAveragesInv;
975+
}
976+
#if !defined(__NEW_SHIELD__)
977+
PeripheralCommsController::endTransaction();
978+
#endif
979+
m4SendVoltage(packets, numAdcChannels);
980+
981+
#ifdef __NEW_DAC_ADC__
982+
digitalWrite(adc_sync, LOW);
983+
#endif
984+
TimingUtil::adcFlag = 0;
985+
currentAdcReads++;
986+
currentLoop++; // Each ADC read marks completion of one loop
987+
}
988+
TimingUtil::stopAndResetAdcTimer();
989+
}
990+
991+
// Clean up timers
992+
TimingUtil::disableDacInterrupt();
993+
TimingUtil::disableAdcInterrupt();
994+
TimingUtil::dacFlag = false;
995+
TimingUtil::adcFlag = 0;
996+
997+
// Clean up
998+
for (int i = 0; i < numAdcChannels; i++) {
999+
ADCController::idleMode(adcChannels[i]);
1000+
#ifdef __NEW_DAC_ADC__
1001+
ADCController::unsetRDYFN(adcChannels[i]);
1002+
#endif
1003+
}
1004+
1005+
#ifdef __NEW_DAC_ADC__
1006+
for (int i = 0; i < numAdcBoards; i++) {
1007+
detachInterrupt(digitalPinToInterrupt(ADCController::getDataReadyPin(boards[i])));
1008+
}
1009+
#endif
1010+
1011+
ADCController::resetToPreviousConversionTimes();
1012+
PeripheralCommsController::dataLedOff();
1013+
1014+
if (getStopFlag()) {
1015+
setStopFlag(false);
1016+
return OperationResult::Failure("RAMPING_STOPPED");
1017+
}
1018+
1019+
return OperationResult::Success();
1020+
}
1021+
1022+
1023+
1024+
1025+
1026+
7501027
static OperationResult dacChannelCalibration() {
7511028
CalibrationData calibrationData;
7521029
for (int i = 0; i < NUM_DAC_CHANNELS; i++) {

m4/src/Utils/TimingUtil.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ struct TimingUtil {
3838
delayMicroseconds(5);
3939
}
4040

41+
inline static void stopAndResetAdcTimer() {
42+
TIM8->CR1 &= ~TIM_CR1_CEN; // Stop the timer (clear Counter Enable bit)
43+
TIM8->CNT = 0; // Reset counter to zero
44+
}
45+
46+
inline static void startAdcTimer() {
47+
TIM8->CR1 |= TIM_CR1_CEN; // Start the timer (set Counter Enable bit)
48+
}
49+
50+
4151
inline static void setupTimerOnlyDac(uint32_t period_us) {
4252
resetTimers();
4353

0 commit comments

Comments
 (0)