diff --git a/headers/addons/he_trigger.h b/headers/addons/he_trigger.h index f8aeb99a2..d78e67781 100644 --- a/headers/addons/he_trigger.h +++ b/headers/addons/he_trigger.h @@ -26,6 +26,49 @@ #define HETRIGGER_S3_PIN -1 #endif +#ifndef HETRIGGER_SEPARATE_SELECT_PINS +#define HETRIGGER_SEPARATE_SELECT_PINS 0 +#endif + +#ifndef HETRIGGER_MUX1_S0_PIN +#define HETRIGGER_MUX1_S0_PIN -1 +#endif +#ifndef HETRIGGER_MUX1_S1_PIN +#define HETRIGGER_MUX1_S1_PIN -1 +#endif +#ifndef HETRIGGER_MUX1_S2_PIN +#define HETRIGGER_MUX1_S2_PIN -1 +#endif +#ifndef HETRIGGER_MUX1_S3_PIN +#define HETRIGGER_MUX1_S3_PIN -1 +#endif + +#ifndef HETRIGGER_MUX2_S0_PIN +#define HETRIGGER_MUX2_S0_PIN -1 +#endif +#ifndef HETRIGGER_MUX2_S1_PIN +#define HETRIGGER_MUX2_S1_PIN -1 +#endif +#ifndef HETRIGGER_MUX2_S2_PIN +#define HETRIGGER_MUX2_S2_PIN -1 +#endif +#ifndef HETRIGGER_MUX2_S3_PIN +#define HETRIGGER_MUX2_S3_PIN -1 +#endif + +#ifndef HETRIGGER_MUX3_S0_PIN +#define HETRIGGER_MUX3_S0_PIN -1 +#endif +#ifndef HETRIGGER_MUX3_S1_PIN +#define HETRIGGER_MUX3_S1_PIN -1 +#endif +#ifndef HETRIGGER_MUX3_S2_PIN +#define HETRIGGER_MUX3_S2_PIN -1 +#endif +#ifndef HETRIGGER_MUX3_S3_PIN +#define HETRIGGER_MUX3_S3_PIN -1 +#endif + #ifndef HETRIGGER_ADC0 #define HETRIGGER_ADC0 -1 #endif @@ -858,12 +901,12 @@ class HETriggerAddon : public GPAddon { virtual void reinit() {} virtual std::string name() { return HETriggerAddonName; } private: - void selectChannel(uint8_t channel); + void selectChannel(uint8_t mux, uint8_t channel); uint16_t emaSmoothing(uint16_t value, uint16_t previous); int muxTotal; int selectPins; Pin_t muxPinArray[4]; - Pin_t selectPinArray[4]; + Pin_t selectPinArray[4][4]; // Select pins indexed by [mux][selectBit] Pin_t lastADCSelected; uint16_t emaSmoothingReads[32]; diff --git a/proto/config.proto b/proto/config.proto index bdd4f4672..12a5b2e7d 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -929,13 +929,21 @@ message HETriggerInfo optional bool is_polarized = 9; } +message HETriggerMux +{ + optional int32 selectPin0 = 1; + optional int32 selectPin1 = 2; + optional int32 selectPin2 = 3; + optional int32 selectPin3 = 4; +} + message HETriggerOptions { optional bool enabled = 1; - optional int32 selectPin0 = 2; - optional int32 selectPin1 = 3; - optional int32 selectPin2 = 4; - optional int32 selectPin3 = 5; + optional int32 selectPin0 = 2 [deprecated = true]; // Deprecated in favor of muxes[] + optional int32 selectPin1 = 3 [deprecated = true]; + optional int32 selectPin2 = 4 [deprecated = true]; + optional int32 selectPin3 = 5 [deprecated = true]; optional int32 muxADCPin0 = 6; optional int32 muxADCPin1 = 7; optional int32 muxADCPin2 = 8; @@ -944,6 +952,8 @@ message HETriggerOptions repeated HETriggerInfo triggers = 11 [(nanopb).max_count = 32]; optional bool emaSmoothing = 12; optional int32 smoothingFactor = 13; + optional bool separateSelectPins = 14; + repeated HETriggerMux muxes = 15 [(nanopb).max_count = 4]; } message AddonOptions @@ -988,6 +998,7 @@ message MigrationHistory optional bool gpioMappingsMigrated = 2 [default = false]; optional bool buttonProfilesMigrated = 3 [default = false]; optional bool profileEnabledFlagsMigrated = 4 [default = false]; + optional bool heTriggerSelectPinsMigrated = 5 [default = false]; } message Config diff --git a/src/addons/he_trigger.cpp b/src/addons/he_trigger.cpp index 02e873c07..34021733a 100644 --- a/src/addons/he_trigger.cpp +++ b/src/addons/he_trigger.cpp @@ -43,15 +43,21 @@ void HETriggerAddon::setup() { break; } - selectPinArray[0] = options.selectPin0; - selectPinArray[1] = options.selectPin1; - selectPinArray[2] = options.selectPin2; - selectPinArray[3] = options.selectPin3; - for(int i = 0; i < selectPins; i++) { - if ( selectPinArray[i] != -1 ) { - gpio_init(selectPinArray[i]); - gpio_set_dir(selectPinArray[i], GPIO_OUT); - gpio_put(selectPinArray[i], 0); + for(int mux = 0; mux < 4; mux++) { + int src = options.separateSelectPins ? mux : 0; + selectPinArray[mux][0] = options.muxes[src].selectPin0; + selectPinArray[mux][1] = options.muxes[src].selectPin1; + selectPinArray[mux][2] = options.muxes[src].selectPin2; + selectPinArray[mux][3] = options.muxes[src].selectPin3; + } + + for(int mux = 0; mux < muxTotal; mux++) { + for(int i = 0; i < selectPins; i++) { + if ( selectPinArray[mux][i] != -1 ) { + gpio_init(selectPinArray[mux][i]); + gpio_set_dir(selectPinArray[mux][i], GPIO_OUT); + gpio_put(selectPinArray[mux][i], 0); + } } } @@ -65,7 +71,7 @@ void HETriggerAddon::setup() { continue; mux = (i / options.muxChannels); channel = (i % options.muxChannels); - selectChannel(channel); + selectChannel(mux, channel); // Only Switch ADC if we are not currently on the mux ADC if ( lastADCSelected != muxPinArray[mux]) { adc_select_input(muxPinArray[mux]-26); @@ -79,11 +85,11 @@ void HETriggerAddon::setup() { } } -void HETriggerAddon::selectChannel(uint8_t channel) { +void HETriggerAddon::selectChannel(uint8_t mux, uint8_t channel) { for(int i = 0; i < selectPins; i++) { - if ( selectPinArray[i] != -1 ) { - gpio_put(selectPinArray[i], (channel >> i) & 0x01); - } + if ( selectPinArray[mux][i] != -1 ) { + gpio_put(selectPinArray[mux][i], (channel >> i) & 0x01); + } } } @@ -102,7 +108,7 @@ void HETriggerAddon::preprocess() { continue; mux = (he / options.muxChannels); channel = (he % options.muxChannels); - selectChannel(channel); + selectChannel(mux, channel); // Only Switch ADC if we are not currently on the mux ADC if ( lastADCSelected != muxPinArray[mux]) { adc_select_input(muxPinArray[mux]-26); diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 00e109806..e658c0b74 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -939,10 +939,6 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) // addonOptions.heTriggerOptions INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, enabled, !!HETRIGGER_ENABLED); - INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, selectPin0, HETRIGGER_S0_PIN); - INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, selectPin1, HETRIGGER_S1_PIN); - INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, selectPin2, HETRIGGER_S2_PIN); - INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, selectPin3, HETRIGGER_S3_PIN); INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, muxADCPin0, HETRIGGER_ADC0); INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, muxADCPin1, HETRIGGER_ADC1); INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, muxADCPin2, HETRIGGER_ADC2); @@ -950,6 +946,24 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, muxChannels, HETRIGGER_MUX_CHANNELS); INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, emaSmoothing, HETRIGGER_SMOOTHING_ENABLED); INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, smoothingFactor, HETRIGGER_SMOOTHING_FACTOR); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions, separateSelectPins, !!HETRIGGER_SEPARATE_SELECT_PINS); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[0], selectPin0, HETRIGGER_S0_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[0], selectPin1, HETRIGGER_S1_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[0], selectPin2, HETRIGGER_S2_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[0], selectPin3, HETRIGGER_S3_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[1], selectPin0, HETRIGGER_MUX1_S0_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[1], selectPin1, HETRIGGER_MUX1_S1_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[1], selectPin2, HETRIGGER_MUX1_S2_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[1], selectPin3, HETRIGGER_MUX1_S3_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[2], selectPin0, HETRIGGER_MUX2_S0_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[2], selectPin1, HETRIGGER_MUX2_S1_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[2], selectPin2, HETRIGGER_MUX2_S2_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[2], selectPin3, HETRIGGER_MUX2_S3_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[3], selectPin0, HETRIGGER_MUX3_S0_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[3], selectPin1, HETRIGGER_MUX3_S1_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[3], selectPin2, HETRIGGER_MUX3_S2_PIN); + INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.muxes[3], selectPin3, HETRIGGER_MUX3_S3_PIN); + config.addonOptions.heTriggerOptions.muxes_count = 4; INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.triggers[0], action, HETRIGGER_HE0_ACTION); INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.triggers[0], active, HETRIGGER_HE0_ACTIVE); INIT_UNSET_PROPERTY(config.addonOptions.heTriggerOptions.triggers[0], idle, HETRIGGER_HE0_IDLE); @@ -1750,14 +1764,18 @@ void gpioMappingsMigrationCore(Config& config) // Set our HE trigger options if (config.addonOptions.heTriggerOptions.enabled) { - markAddonPinIfUsed(config.addonOptions.heTriggerOptions.muxADCPin0); - markAddonPinIfUsed(config.addonOptions.heTriggerOptions.muxADCPin1); - markAddonPinIfUsed(config.addonOptions.heTriggerOptions.muxADCPin2); - markAddonPinIfUsed(config.addonOptions.heTriggerOptions.muxADCPin3); - markAddonPinIfUsed(config.addonOptions.heTriggerOptions.selectPin0); - markAddonPinIfUsed(config.addonOptions.heTriggerOptions.selectPin1); - markAddonPinIfUsed(config.addonOptions.heTriggerOptions.selectPin2); - markAddonPinIfUsed(config.addonOptions.heTriggerOptions.selectPin3); + HETriggerOptions& heOptions = config.addonOptions.heTriggerOptions; + markAddonPinIfUsed(heOptions.muxADCPin0); + markAddonPinIfUsed(heOptions.muxADCPin1); + markAddonPinIfUsed(heOptions.muxADCPin2); + markAddonPinIfUsed(heOptions.muxADCPin3); + int muxSelectRows = heOptions.separateSelectPins ? 4 : 1; + for (int m = 0; m < muxSelectRows; m++) { + markAddonPinIfUsed(heOptions.muxes[m].selectPin0); + markAddonPinIfUsed(heOptions.muxes[m].selectPin1); + markAddonPinIfUsed(heOptions.muxes[m].selectPin2); + markAddonPinIfUsed(heOptions.muxes[m].selectPin3); + } } @@ -1909,6 +1927,28 @@ void profileEnabledFlagsMigration(Config& config) { config.migrations.profileEnabledFlagsMigrated = true; } +void heTriggerSelectPinsMigration(Config& config) { + // Migrate the legacy shared select pins (selectPin0-3) into muxes[0] + HETriggerOptions& heOptions = config.addonOptions.heTriggerOptions; + if (heOptions.has_selectPin0) { + heOptions.muxes[0].selectPin0 = heOptions.selectPin0; + heOptions.muxes[0].has_selectPin0 = true; + } + if (heOptions.has_selectPin1) { + heOptions.muxes[0].selectPin1 = heOptions.selectPin1; + heOptions.muxes[0].has_selectPin1 = true; + } + if (heOptions.has_selectPin2) { + heOptions.muxes[0].selectPin2 = heOptions.selectPin2; + heOptions.muxes[0].has_selectPin2 = true; + } + if (heOptions.has_selectPin3) { + heOptions.muxes[0].selectPin3 = heOptions.selectPin3; + heOptions.muxes[0].has_selectPin3 = true; + } + config.migrations.heTriggerSelectPinsMigrated = true; +} + void migrateMacroPinsToGpio(Config& config) { // Convert Macro pin mapping to GPIO mapping configs MacroOptions & macroOptions = config.addonOptions.macroOptions; @@ -2082,6 +2122,10 @@ void ConfigUtils::load(Config& config) // They were probably added with a newer version of the firmware. initUnsetPropertiesWithDefaults(config); + // Migrate legacy HE Trigger shared select pins into muxes[0] + if (!config.migrations.heTriggerSelectPinsMigrated) + heTriggerSelectPinsMigration(config); + // Run migrations that need to happen after initUnset... // ProtoBuf && Board Config settings are loaded here if (!config.migrations.gpioMappingsMigrated) @@ -2730,6 +2774,9 @@ bool ConfigUtils::fromJSON(Config& config, const char* data, size_t dataLen) initUnsetPropertiesWithDefaults(config); // we need to run migrations here too, in case the json document changed pins or things derived from pins + if (!config.migrations.heTriggerSelectPinsMigrated) + heTriggerSelectPinsMigration(config); + gpioMappingsMigrationCore(config); migrateTurboPinToGpio(config); migrateAuthenticationMethods(config); diff --git a/src/webconfig.cpp b/src/webconfig.cpp index 0fcaa03f7..1165d12ab 100644 --- a/src/webconfig.cpp +++ b/src/webconfig.cpp @@ -1893,7 +1893,8 @@ std::string setExpansionPins() } static uint32_t calibrationMuxChannels = 0; -static Pin_t calibrationSelectPins[4]; +static Pin_t calibrationSelectPins[4][4]; +static bool calibrationSeparateSelectPins = false; static Pin_t calibrationADCPins[4]; static bool calibrationSmoothing = false; static uint32_t calibrationSmoothingFactor = 0; @@ -1905,10 +1906,21 @@ std::string setHETriggerOptions() { DynamicJsonDocument doc = get_post_data(); calibrationMuxChannels = doc["muxChannels"]; - calibrationSelectPins[0] = doc["muxSelectPin0"]; - calibrationSelectPins[1] = doc["muxSelectPin1"]; - calibrationSelectPins[2] = doc["muxSelectPin2"]; - calibrationSelectPins[3] = doc["muxSelectPin3"]; + calibrationSeparateSelectPins = doc["separateSelectPins"]; + static const char* selectPinKeys[4] = { "selectPin0", "selectPin1", "selectPin2", "selectPin3" }; + for (int i = 0; i < 4; i++) { + for (int b = 0; b < 4; b++) { + calibrationSelectPins[i][b] = doc["muxes"][i][selectPinKeys[b]]; + } + } + if ( !calibrationSeparateSelectPins ) { + // Shared select lines: every mux mirrors mux 0. + for(int mux = 1; mux < 4; mux++) { + for(int i = 0; i < 4; i++) { + calibrationSelectPins[mux][i] = calibrationSelectPins[0][i]; + } + } + } calibrationADCPins[0] = doc["muxADCPin0"]; calibrationADCPins[1] = doc["muxADCPin1"]; @@ -1928,12 +1940,15 @@ std::string setHETriggerOptions() pinEnd = 47; #endif for (int i = 0; i < 4; i++) { - if ( calibrationSelectPins[i] != -1 && - calibrationSelectPins[i] >= 0 && - calibrationSelectPins[i] <= pinEnd ) { - gpio_init(calibrationSelectPins[i]); - gpio_set_dir(calibrationSelectPins[i], GPIO_OUT); - gpio_put(calibrationSelectPins[i], 0); + for (int mux = 0; mux < 4; mux++) { + Pin_t selectPin = calibrationSelectPins[mux][i]; + if ( selectPin != -1 && + selectPin >= 0 && + selectPin <= pinEnd ) { + gpio_init(selectPin); + gpio_set_dir(selectPin, GPIO_OUT); + gpio_put(selectPin, 0); + } } if ( calibrationADCPins[i] != -1 && calibrationADCPins[i] >= pinStart && @@ -1976,8 +1991,8 @@ std::string getHETriggerVoltage() return serialize_json(doc); } adcSelectPin = calibrationADCPins[adcNum]; - gpio_put(calibrationSelectPins[0], channel & 0x01); - gpio_put(calibrationSelectPins[1], (channel >> 1) & 0x01); + gpio_put(calibrationSelectPins[adcNum][0], channel & 0x01); + gpio_put(calibrationSelectPins[adcNum][1], (channel >> 1) & 0x01); } else if (calibrationMuxChannels == 8) { uint32_t adcNum = id / 8; uint32_t channel = (id % 8); @@ -1986,9 +2001,9 @@ std::string getHETriggerVoltage() return serialize_json(doc); } adcSelectPin = calibrationADCPins[adcNum]; - gpio_put(calibrationSelectPins[0], channel & 0x01); - gpio_put(calibrationSelectPins[1], (channel >> 1) & 0x01); - gpio_put(calibrationSelectPins[2], (channel >> 2) & 0x01); + gpio_put(calibrationSelectPins[adcNum][0], channel & 0x01); + gpio_put(calibrationSelectPins[adcNum][1], (channel >> 1) & 0x01); + gpio_put(calibrationSelectPins[adcNum][2], (channel >> 2) & 0x01); } else if (calibrationMuxChannels == 16) { uint32_t adcNum = id / 16; uint32_t channel = (id % 16); @@ -1997,10 +2012,10 @@ std::string getHETriggerVoltage() return serialize_json(doc); } adcSelectPin = calibrationADCPins[adcNum]; - gpio_put(calibrationSelectPins[0], channel & 0x01); - gpio_put(calibrationSelectPins[1], (channel >> 1) & 0x01); - gpio_put(calibrationSelectPins[2], (channel >> 2) & 0x01); - gpio_put(calibrationSelectPins[3], (channel >> 3) & 0x01); + gpio_put(calibrationSelectPins[adcNum][0], channel & 0x01); + gpio_put(calibrationSelectPins[adcNum][1], (channel >> 1) & 0x01); + gpio_put(calibrationSelectPins[adcNum][2], (channel >> 2) & 0x01); + gpio_put(calibrationSelectPins[adcNum][3], (channel >> 3) & 0x01); } else { doc["error"] = "mux channels incorrect"; return serialize_json(doc); @@ -2346,16 +2361,30 @@ std::string setAddonOptions() HETriggerOptions& heTriggerOptions = Storage::getInstance().getAddonOptions().heTriggerOptions; docToValue(heTriggerOptions.enabled, doc, "HETriggerEnabled"); docToValue(heTriggerOptions.muxChannels, doc, "muxChannels"); - docToPin(heTriggerOptions.selectPin0, doc, "muxSelectPin0"); - docToPin(heTriggerOptions.selectPin1, doc, "muxSelectPin1"); - docToPin(heTriggerOptions.selectPin2, doc, "muxSelectPin2"); - docToPin(heTriggerOptions.selectPin3, doc, "muxSelectPin3"); docToPin(heTriggerOptions.muxADCPin0, doc, "muxADCPin0"); docToPin(heTriggerOptions.muxADCPin1, doc, "muxADCPin1"); docToPin(heTriggerOptions.muxADCPin2, doc, "muxADCPin2"); docToPin(heTriggerOptions.muxADCPin3, doc, "muxADCPin3"); docToValue(heTriggerOptions.emaSmoothing, doc, "heTriggerSmoothing"); docToValue(heTriggerOptions.smoothingFactor, doc, "heTriggerSmoothingFactor"); + docToValue(heTriggerOptions.separateSelectPins, doc, "separateSelectPins"); + static const char* selectPinKeys[4] = { "selectPin0", "selectPin1", "selectPin2", "selectPin3" }; + for (int i = 0; i < 4; i++) { + Pin_t* muxSelectPins[4] = { + &heTriggerOptions.muxes[i].selectPin0, + &heTriggerOptions.muxes[i].selectPin1, + &heTriggerOptions.muxes[i].selectPin2, + &heTriggerOptions.muxes[i].selectPin3, + }; + for (int b = 0; b < 4; b++) { + if (doc["muxes"][i].containsKey(selectPinKeys[b])) { + Pin_t oldPin = *muxSelectPins[b]; + *muxSelectPins[b] = doc["muxes"][i][selectPinKeys[b]]; + cleanAddonGpioMappings(*muxSelectPins[b], oldPin); + } + } + } + heTriggerOptions.muxes_count = 4; EventManager::getInstance().triggerEvent(new GPStorageSaveEvent(true)); @@ -2831,16 +2860,20 @@ std::string getAddonOptions() const HETriggerOptions& heTriggerOptions = Storage::getInstance().getAddonOptions().heTriggerOptions; writeDoc(doc, "HETriggerEnabled", heTriggerOptions.enabled); writeDoc(doc, "muxChannels", heTriggerOptions.muxChannels); - writeDoc(doc, "muxSelectPin0", cleanPin(heTriggerOptions.selectPin0)); - writeDoc(doc, "muxSelectPin1", cleanPin(heTriggerOptions.selectPin1)); - writeDoc(doc, "muxSelectPin2", cleanPin(heTriggerOptions.selectPin2)); - writeDoc(doc, "muxSelectPin3", cleanPin(heTriggerOptions.selectPin3)); writeDoc(doc, "muxADCPin0", cleanPin(heTriggerOptions.muxADCPin0)); writeDoc(doc, "muxADCPin1", cleanPin(heTriggerOptions.muxADCPin1)); writeDoc(doc, "muxADCPin2", cleanPin(heTriggerOptions.muxADCPin2)); writeDoc(doc, "muxADCPin3", cleanPin(heTriggerOptions.muxADCPin3)); writeDoc(doc, "heTriggerSmoothing", heTriggerOptions.emaSmoothing); writeDoc(doc, "heTriggerSmoothingFactor", heTriggerOptions.smoothingFactor); + writeDoc(doc, "separateSelectPins", heTriggerOptions.separateSelectPins); + doc.createNestedArray("muxes"); + for (int i = 0; i < 4; i++) { + writeDoc(doc, "muxes", i, "selectPin0", cleanPin(heTriggerOptions.muxes[i].selectPin0)); + writeDoc(doc, "muxes", i, "selectPin1", cleanPin(heTriggerOptions.muxes[i].selectPin1)); + writeDoc(doc, "muxes", i, "selectPin2", cleanPin(heTriggerOptions.muxes[i].selectPin2)); + writeDoc(doc, "muxes", i, "selectPin3", cleanPin(heTriggerOptions.muxes[i].selectPin3)); + } return serialize_json(doc); } diff --git a/www/src/Addons/HETrigger.tsx b/www/src/Addons/HETrigger.tsx index f8c04e116..e6c87983c 100644 --- a/www/src/Addons/HETrigger.tsx +++ b/www/src/Addons/HETrigger.tsx @@ -71,22 +71,18 @@ export const HETriggerScheme = { .number() .label('Multiplexer ADC 3 Pin') .validatePinWhenValue('HETriggerEnabled'), - muxSelectPin0: yup + separateSelectPins: yup .number() - .label('Multiplexer Select 0 Pin') - .validatePinWhenValue('HETriggerEnabled'), - muxSelectPin1: yup - .number() - .label('Multiplexer Select 1 Pin') - .validatePinWhenValue('HETriggerEnabled'), - muxSelectPin2: yup - .number() - .label('Multiplexer Select 2 Pin') - .validatePinWhenValue('HETriggerEnabled'), - muxSelectPin3: yup - .number() - .label('Multiplexer Select 3 Pin') - .validatePinWhenValue('HETriggerEnabled'), + .label('Separate Select Pins') + .validateRangeWhenValue('HETriggerEnabled', 0, 1), + muxes: yup.array().of( + yup.object().shape({ + selectPin0: yup.number().label('Mux Select 0 Pin'), + selectPin1: yup.number().label('Mux Select 1 Pin'), + selectPin2: yup.number().label('Mux Select 2 Pin'), + selectPin3: yup.number().label('Mux Select 3 Pin'), + }), + ), heTriggerSmoothing: yup .number() .label('EMA Smoothing') @@ -104,10 +100,13 @@ export const HETriggerState = { muxADCPin1: 27, muxADCPin2: 28, muxADCPin3: -1, - muxSelectPin0: 0, - muxSelectPin1: 1, - muxSelectPin2: 2, - muxSelectPin3: -1, + separateSelectPins: 0, + muxes: [ + { selectPin0: 0, selectPin1: 1, selectPin2: 2, selectPin3: -1 }, + { selectPin0: -1, selectPin1: -1, selectPin2: -1, selectPin3: -1 }, + { selectPin0: -1, selectPin1: -1, selectPin2: -1, selectPin3: -1 }, + { selectPin0: -1, selectPin1: -1, selectPin2: -1, selectPin3: -1 }, + ], heTriggerSmoothing: 0, heTriggerSmoothingFactor: 5, }; @@ -192,7 +191,9 @@ const TriggerActionsForm = ({