@@ -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++) {
0 commit comments