diff --git a/src/html/elrs.css b/src/html/elrs.css index a99d38a691..5e96ed4594 100644 --- a/src/html/elrs.css +++ b/src/html/elrs.css @@ -41,6 +41,19 @@ body, input, select, textarea { line-height: 1.65em; } +.fixed-column { + width: 20px; + padding-left: 4px !important; + padding-right: 4px !important; +} + +.compact { + padding-left: 10px !important; + padding-right: 10px !important; + padding-top: 5px !important; + margin-bottom: 5px !important; +} + @media screen and (max-width: 800px) { .logo { width:25%; diff --git a/src/html/index.html b/src/html/index.html index e00500111d..ce981cde7c 100644 --- a/src/html/index.html +++ b/src/html/index.html @@ -177,11 +177,11 @@

PWM Output

Set PWM output mode and failsafe positions. -

diff --git a/src/html/scan.js b/src/html/scan.js index 13d9c67865..95e79d2f6f 100644 --- a/src/html/scan.js +++ b/src/html/scan.js @@ -41,49 +41,73 @@ function getPwmFormData() { function enumSelectGenerate(id, val, arOptions) { // Generate a ` + - arOptions.map((item, idx) => { - if (item) return ``; - return ''; - }).join('') + ''; + const retVal = `
'; + return retVal; +} + +function generateFeatureBadges(features) { + let str = ''; + if (!!(features & 1)) str += `TX`; + else if (!!(features & 2)) str += `RX`; + if ((features & 12) === 12) str += `I2C`; + else if (!!(features & 4)) str += `SCL`; + else if (!!(features & 8)) str += `SDA`; + return str; } @@if not isTX: -function updatePwmSettings(arPwm, allowDshot) { +function updatePwmSettings(arPwm) { if (arPwm === undefined) { if (_('model_tab')) _('model_tab').style.display = 'none'; return; } - let pin1Index = undefined; - let pin1SerialIndex = undefined; - let pin3Index = undefined; - let pin3SerialIndex = undefined; + var pinRxIndex = undefined; + var pinTxIndex = undefined; + var pinModes = [] // arPwm is an array of raw integers [49664,50688,51200]. 10 bits of failsafe position, 4 bits of input channel, 1 bit invert, 4 bits mode, 1 bit for narrow/750us - const htmlFields = ['
']; + const htmlFields = ['
OutputModeInputInvert?750us?Failsafe
']; arPwm.forEach((item, index) => { const failsafe = (item.config & 1023) + 988; // 10 bits const ch = (item.config >> 10) & 15; // 4 bits const inv = (item.config >> 14) & 1; const mode = (item.config >> 15) & 15; // 4 bits const narrow = (item.config >> 19) & 1; - const pin = item.pin; + const features = item.features; const modes = ['50Hz', '60Hz', '100Hz', '160Hz', '333Hz', '400Hz', '10KHzDuty', 'On/Off']; - // only ESP32 devices allow DShot - if (allowDshot === true) { - if (pin !== 0) - modes.push('DShot'); - else - modes.push(undefined); + if (features & 16) { + modes.push('DShot'); + } else { + modes.push(undefined); } - if (pin === 1) { + if (features & 1) { modes.push('Serial TX'); - pin1Index = index; - pin1SerialIndex = modes.length-1; - } - if (pin === 3) { + modes.push(undefined); // SCL + modes.push(undefined); // SDA + modes.push(undefined); // true PWM + pinRxIndex = index; + } else if (features & 2) { modes.push('Serial RX'); - pin3Index = index; - pin3SerialIndex = modes.length-1; + modes.push(undefined); // SCL + modes.push(undefined); // SDA + modes.push(undefined); // true PWM + pinTxIndex = index; + } else { + modes.push(undefined); // Serial + if (features & 4) { + modes.push('I2C SCL'); + } else { + modes.push(undefined); + } + if (features & 8) { + modes.push('I2C SDA'); + } else { + modes.push(undefined); + } + modes.push(undefined); // true PWM } modes.push(undefined); // true PWM const modeSelect = enumSelectGenerate(`pwm_${index}_mode`, mode, modes); @@ -92,12 +116,14 @@ function updatePwmSettings(arPwm, allowDshot) { 'ch5 (AUX1)', 'ch6 (AUX2)', 'ch7 (AUX3)', 'ch8 (AUX4)', 'ch9 (AUX5)', 'ch10 (AUX6)', 'ch11 (AUX7)', 'ch12 (AUX8)', 'ch13 (AUX9)', 'ch14 (AUX10)', 'ch15 (AUX11)', 'ch16 (AUX12)']); - htmlFields.push(` + htmlFields.push(` + - `); + `); + pinModes[index] = mode; }); htmlFields.push('
OutputFeaturesModeInputInvert?750us?Failsafe
${index+1}
${index + 1}${generateFeatureBadges(features)} ${modeSelect} ${inputSelect}
'); @@ -107,47 +133,70 @@ function updatePwmSettings(arPwm, allowDshot) { _('pwm').appendChild(grp); - let setDisabled = (index, onoff) => { + const setDisabled = (index, onoff) => { _(`pwm_${index}_ch`).disabled = onoff; _(`pwm_${index}_inv`).disabled = onoff; _(`pwm_${index}_nar`).disabled = onoff; _(`pwm_${index}_fs`).disabled = onoff; } - // put some constraints on pin1/3 mode selects - if (pin1Index !== undefined && pin3Index !== undefined) { - const pin1Mode = _(`pwm_${pin1Index}_mode`); - const pin3Mode = _(`pwm_${pin3Index}_mode`); - pin1Mode.onchange = () => { - if (Number(pin1Mode.value) === pin1SerialIndex) { // Serial - pin3Mode.value = pin3SerialIndex; - setDisabled(pin1Index, true); - setDisabled(pin3Index, true); - pin3Mode.disabled = true; - _('serial-config').style.display = _('is-airport').checked ? 'none' : 'block'; + arPwm.forEach((item,index)=>{ + const pinMode = _(`pwm_${index}_mode`) + pinMode.onchange = () => { + setDisabled(index, pinMode.value > 9); + const updateOthers = (value, enable) => { + if (value > 9) { // disable others + arPwm.forEach((item, other) => { + if (other != index) { + document.querySelectorAll(`#pwm_${other}_mode option`).forEach(opt => { + if (opt.value == value) { + opt.disabled = enable; + } + }); + } + }) + } + } + updateOthers(pinMode.value, true); // disable others + updateOthers(pinModes[index], false); // enable others + pinModes[index] = pinMode.value; + } + pinMode.onchange(); + }); + // put some contraints on pinRx/Tx mode selects + if (pinRxIndex !== undefined && pinTxIndex !== undefined) { + const pinRxMode = _(`pwm_${pinRxIndex}_mode`); + const pinTxMode = _(`pwm_${pinTxIndex}_mode`); + pinRxMode.onchange = () => { + if (pinRxMode.value == 9) { // Serial + pinTxMode.value = 9; + setDisabled(pinRxIndex, true); + setDisabled(pinTxIndex, true); + pinTxMode.disabled = true; + _('serial-config').style.display = 'block'; _('baud-config').style.display = 'block'; } else { - pin3Mode.value = 0; - setDisabled(pin1Index, false); - setDisabled(pin3Index, false); - pin3Mode.disabled = false; + pinTxMode.value = 0; + setDisabled(pinRxIndex, false); + setDisabled(pinTxIndex, false); + pinTxMode.disabled = false; _('serial-config').style.display = 'none'; _('baud-config').style.display = 'none'; } } - pin3Mode.onchange = () => { - if (Number(pin3Mode.value) === pin3SerialIndex) { // Serial - pin1Mode.value = pin1SerialIndex; - setDisabled(pin1Index, true); - setDisabled(pin3Index, true); - pin3Mode.disabled = true; - _('serial-config').style.display = _('is-airport').checked ? 'none' : 'block'; + pinTxMode.onchange = () => { + if (pinTxMode.value == 9) { // Serial + pinRxMode.value = 9; + setDisabled(pinRxIndex, true); + setDisabled(pinTxIndex, true); + pinTxMode.disabled = true; + _('serial-config').style.display = 'block'; _('baud-config').style.display = 'block'; } } - const pin3 = pin3Mode.value; - pin1Mode.onchange(); - if(Number(pin1Mode.value) !== pin1SerialIndex) pin3Mode.value = pin3; + const pinTx = pinTxMode.value; + pinRxMode.onchange(); + if(pinRxMode.value != 9) pinTxMode.value = pinTx; } } @@end @@ -279,7 +328,7 @@ function updateConfig(data, options) { _('sbus-config').style.display = 'none'; } } - updatePwmSettings(data.pwm, data['allow-dshot']); + updatePwmSettings(data.pwm); _('serial-protocol').value = data['serial-protocol']; _('serial-protocol').onchange(); _('is-airport').onchange = _('serial-protocol').onchange; diff --git a/src/include/common.h b/src/include/common.h index 79225d3c26..ad2cb45522 100644 --- a/src/include/common.h +++ b/src/include/common.h @@ -175,10 +175,10 @@ enum eServoOutputMode : uint8_t som400Hz, som10KHzDuty, somOnOff, // Digital 0/1 mode -#if defined(PLATFORM_ESP32) somDShot, // DShot300 -#endif somSerial, // Serial TX or RX depending on pin + somSCL, // I2C clock signal + somSDA, // I2C data line somPwm, // True PWM mode (NOT SUPPORTED) }; diff --git a/src/lib/Baro/devBaro.cpp b/src/lib/Baro/devBaro.cpp index dee46d1d61..f76341c014 100644 --- a/src/lib/Baro/devBaro.cpp +++ b/src/lib/Baro/devBaro.cpp @@ -15,11 +15,13 @@ extern Telemetry telemetry; static SPL06 *baro; static eBaroReadState BaroReadState; +extern bool i2c_enabled; + static bool Baro_Detect() { // I2C Baros #if defined(USE_I2C) - if (GPIO_PIN_SCL != UNDEF_PIN && GPIO_PIN_SDA != UNDEF_PIN) + if (i2c_enabled) { if (SPL06::detect()) { @@ -27,10 +29,9 @@ static bool Baro_Detect() baro = new SPL06(); return true; } + // DBGLN("No baro detected"); } // I2C #endif - - //DBGLN("No baro detected"); return false; } diff --git a/src/lib/CONFIG/config.cpp b/src/lib/CONFIG/config.cpp index 5e0802cbe4..530630d30d 100644 --- a/src/lib/CONFIG/config.cpp +++ b/src/lib/CONFIG/config.cpp @@ -970,7 +970,22 @@ RxConfig::SetDefaults(bool commit) #if defined(GPIO_PIN_PWM_OUTPUTS) for (unsigned int ch=0; ch f); @@ -11,15 +11,8 @@ extern bool InLoanBindingMode; extern bool returnModelFromLoan; static char modelString[] = "000"; -#if defined(PLATFORM_ESP32) -static const char *pwmModes = "50Hz;60Hz;100Hz;160Hz;333Hz;400Hz;10kHzDuty;On/Off;DShot"; -static const char *noDShot = "50Hz;60Hz;100Hz;160Hz;333Hz;400Hz;10kHzDuty;On/Off"; -static const char *txModes = "50Hz;60Hz;100Hz;160Hz;333Hz;400Hz;10kHzDuty;On/Off;DShot;Serial TX"; -static const char *rxModes = "50Hz;60Hz;100Hz;160Hz;333Hz;400Hz;10kHzDuty;On/Off;DShot;Serial RX"; -#else -static const char *pwmModes = "50Hz;60Hz;100Hz;160Hz;333Hz;400Hz;10kHzDuty;On/Off"; -static const char *txModes = "50Hz;60Hz;100Hz;160Hz;333Hz;400Hz;10kHzDuty;On/Off;Serial TX"; -static const char *rxModes = "50Hz;60Hz;100Hz;160Hz;333Hz;400Hz;10kHzDuty;On/Off;Serial RX"; +#if defined(GPIO_PIN_PWM_OUTPUTS) +static char pwmModes[] = "50Hz;60Hz;100Hz;160Hz;333Hz;400Hz;10kHzDuty;On/Off;DShot;Serial RX;Serial TX;I2C SCL;I2C SDA"; #endif static struct luaItem_selection luaSerialProtocol = { @@ -162,30 +155,68 @@ static struct luaItem_command luaReturnModel = { //---------------------------- Model Loan Out ----------------------------- #if defined(GPIO_PIN_PWM_OUTPUTS) - static void luaparamMappingChannelOut(struct luaPropertiesCommon *item, uint8_t arg) { - setLuaUint8Value(&luaMappingChannelOut, arg); - // Must trigger an event because this is not a persistent config item - if (GPIO_PIN_PWM_OUTPUTS[arg-1] == 3) - { - luaMappingOutputMode.options = rxModes; - } - else if (GPIO_PIN_PWM_OUTPUTS[arg-1] == 1) - { - luaMappingOutputMode.options = txModes; - } - #if defined(PLATFORM_ESP32) - else if (GPIO_PIN_PWM_OUTPUTS[arg-1] == 0) - { - luaMappingOutputMode.options = noDShot; - } - #endif - else - { - luaMappingOutputMode.options = pwmModes; - } - devicesTriggerEvent(); + setLuaUint8Value(&luaMappingChannelOut, arg); + + // When the selected output channel changes, update the available PWM modes for that pin + // Truncate the select options before the ; following On/Off + pwmModes[50] = '\0'; + +#if defined(PLATFORM_ESP32) + // DShot output (1 option) + // ;DShot + // ESP8266 enum skips this, so it is never present + if (GPIO_PIN_PWM_OUTPUTS[arg-1] != 0) + { + strcat(pwmModes, ";DShot"); + } + else +#endif + { + strcat(pwmModes, ";"); + } + + // SerialIO outputs (1 option) + // ;[Serial RX] | [Serial TX] + if (GPIO_PIN_PWM_OUTPUTS[arg-1] == 3) + { + strcat(pwmModes, ";Serial RX"); + } + else if (GPIO_PIN_PWM_OUTPUTS[arg-1] == 1) + { + strcat(pwmModes, ";Serial TX"); + } + else + { + strcat(pwmModes, ";"); + } + + // I2C pins (2 options) + // ;[I2C SCL] ;[I2C SDA] + // If the target defines SCL/SDA then those pins MUST be used, + // otherwise allow any pin to be either SCL or SDA + if (GPIO_PIN_PWM_OUTPUTS[arg-1] == GPIO_PIN_SCL) + { + strcat(pwmModes, ";I2C SCL;"); + } + else if (GPIO_PIN_PWM_OUTPUTS[arg-1] == GPIO_PIN_SDA) + { + strcat(pwmModes, ";;I2C SDA"); + } + else if (GPIO_PIN_SCL == UNDEF_PIN || GPIO_PIN_SDA == UNDEF_PIN) + { + strcat(pwmModes, ";I2C SCL;I2C SDA"); + } + + // trim off trailing semicolons (assumes pwmModes has at least 1 non-semicolon) + for (auto lastPos = strlen(pwmModes)-1; pwmModes[lastPos] == ';'; lastPos--) + { + pwmModes[lastPos] = '\0'; + } + + // Trigger an event to update the related fields to represent the selected channel + devicesTriggerEvent(); } static void luaparamMappingChannelIn(struct luaPropertiesCommon *item, uint8_t arg) @@ -198,7 +229,7 @@ static void luaparamMappingChannelIn(struct luaPropertiesCommon *item, uint8_t a config.SetPwmChannelRaw(ch, newPwmCh.raw); } -static uint8_t configureSerialPin(uint8_t pin, uint8_t sibling, uint8_t oldMode, uint8_t newMode) +static uint8_t configureSerialPin(uint8_t sibling, uint8_t oldMode, uint8_t newMode) { for (int ch=0 ; chraw; @@ -238,21 +270,18 @@ static void luaparamMappingOutputMode(struct luaPropertiesCommon *item, uint8_t // Check if pin == 1/3 and do other pin adjustment accordingly if (GPIO_PIN_PWM_OUTPUTS[ch] == 1) { - newPwmCh.val.mode = configureSerialPin(1, 3, oldMode, arg); + newPwmCh.val.mode = configureSerialPin(3, oldMode, newPwmCh.val.mode); } else if (GPIO_PIN_PWM_OUTPUTS[ch] == 3) { - newPwmCh.val.mode = configureSerialPin(3, 1, oldMode, arg); - } - else if (arg == somSerial) - { - newPwmCh.val.mode = oldMode; + newPwmCh.val.mode = configureSerialPin(1, oldMode, newPwmCh.val.mode); } config.SetPwmChannelRaw(ch, newPwmCh.raw); } static void luaparamMappingInverted(struct luaPropertiesCommon *item, uint8_t arg) { + UNUSED(item); const uint8_t ch = luaMappingChannelOut.properties.u.value - 1; rx_config_pwm_t newPwmCh; newPwmCh.raw = config.GetPwmChannel(ch)->raw; @@ -280,8 +309,8 @@ static void luaparamSetFalisafe(struct luaPropertiesCommon *item, uint8_t arg) for (unsigned ch=0; ch<(unsigned)GPIO_PIN_PWM_OUTPUTS_COUNT; ++ch) { rx_config_pwm_t newPwmCh; - newPwmCh.raw = config.GetPwmChannel(ch)->raw; // The value must fit into the 10 bit range of the failsafe + newPwmCh.raw = config.GetPwmChannel(ch)->raw; newPwmCh.val.failsafe = CRSF_to_UINT10(constrain(ChannelData[config.GetPwmChannel(ch)->val.inputChannel], CRSF_CHANNEL_VALUE_MIN, CRSF_CHANNEL_VALUE_MAX)); //DBGLN("FSCH(%u) crsf=%u us=%u", ch, ChannelData[ch], newPwmCh.val.failsafe+988U); config.SetPwmChannelRaw(ch, newPwmCh.raw); @@ -302,6 +331,7 @@ static void luaparamSetFalisafe(struct luaPropertiesCommon *item, uint8_t arg) static void luaparamSetPower(struct luaPropertiesCommon* item, uint8_t arg) { + UNUSED(item); uint8_t newPower = arg + POWERMGNT::getMinPower(); if (newPower > POWERMGNT::getMaxPower()) { @@ -356,14 +386,14 @@ static void registerLuaParameters() config.SetRateInitialIdx(newRate); }); registerLUAParameter(&luaLoanModel, [](struct luaPropertiesCommon* item, uint8_t arg){ - // Do it when polling for status i.e. going back to idle, because we're going to lose conenction to the TX + // Do it when polling for status i.e. going back to idle, because we're going to lose connection to the TX if (arg == 6) { deferExecution(200, [](){ InLoanBindingMode = true; }); } sendLuaCommandResponse(&luaLoanModel, arg < 5 ? lcsExecuting : lcsIdle, arg < 5 ? "Sending..." : ""); }); registerLUAParameter(&luaReturnModel, [](struct luaPropertiesCommon* item, uint8_t arg){ - // Do it when polling for status i.e. going back to idle, because we're going to lose conenction to the TX + // Do it when polling for status i.e. going back to idle, because we're going to lose connection to the TX if (arg == 6) { deferExecution(200, []() { returnModelFromLoan = true; }); } @@ -372,6 +402,7 @@ static void registerLuaParameters() #if defined(GPIO_PIN_PWM_OUTPUTS) if (OPT_HAS_SERVO_OUTPUT) { + luaparamMappingChannelOut(&luaMappingOutputMode.common, luaMappingChannelOut.properties.u.value); registerLUAParameter(&luaMappingFolder); registerLUAParameter(&luaMappingChannelOut, &luaparamMappingChannelOut, luaMappingFolder.common.id); registerLUAParameter(&luaMappingChannelIn, &luaparamMappingChannelIn, luaMappingFolder.common.id); @@ -383,7 +414,7 @@ static void registerLuaParameters() registerLUAParameter(&luaModelNumber); registerLUAParameter(&luaELRSversion); - registerLUAParameter(NULL); + registerLUAParameter(nullptr); } static int event() @@ -435,7 +466,7 @@ static int timeout() { luaHandleUpdateParameter(); // Receivers can only `UpdateParamReq == true` every 4th packet due to the transmitter cadence in 1:2 - // Channels, Downlink Telem Slot, Uplink Telem (the write command), Downlink Telem Slot... + // Channels, Downlink Telemetry Slot, Uplink Telemetry (the write command), Downlink Telemetry Slot... // (interval * 4 / 1000) or 1 second if not connected return (connectionState == connected) ? ExpressLRS_currAirRate_Modparams->interval / 250 : 1000; } @@ -448,7 +479,7 @@ static int start() } device_t LUA_device = { - .initialize = NULL, + .initialize = nullptr, .start = start, .event = event, .timeout = timeout diff --git a/src/lib/ServoOutput/devServoOutput.cpp b/src/lib/ServoOutput/devServoOutput.cpp index 8ed5d385fd..164bc43387 100644 --- a/src/lib/ServoOutput/devServoOutput.cpp +++ b/src/lib/ServoOutput/devServoOutput.cpp @@ -158,9 +158,9 @@ static void initialize() pin = UNDEF_PIN; } #endif - // Mark servo pins that are being used for serial as disconnected + // Mark servo pins that are being used for serial (or other purposes) as disconnected eServoOutputMode mode = (eServoOutputMode)config.GetPwmChannel(ch)->val.mode; - if (mode == somSerial) + if (mode >= somSerial) { pin = UNDEF_PIN; } diff --git a/src/lib/WIFI/devWIFI.cpp b/src/lib/WIFI/devWIFI.cpp index e37792feb8..bb8e130047 100644 --- a/src/lib/WIFI/devWIFI.cpp +++ b/src/lib/WIFI/devWIFI.cpp @@ -16,10 +16,13 @@ #include #include #include +#include #else #include #include #define wifi_mode_t WiFiMode_t +#define U0TXD_GPIO_NUM (1) +#define U0RXD_GPIO_NUM (3) #endif #include @@ -330,13 +333,21 @@ static void GetConfiguration(AsyncWebServerRequest *request) json["config"]["modelid"] = config.GetModelId(); json["config"]["force-tlm"] = config.GetForceTlmOff(); #if defined(GPIO_PIN_PWM_OUTPUTS) - #if defined(PLATFORM_ESP32) - json["config"]["allow-dshot"] = true; - #endif for (uint8_t ch=0; chraw; - json["config"]["pwm"][ch]["pin"] = GPIO_PIN_PWM_OUTPUTS[ch]; + json["config"]["pwm"][ch]["config"] = config.GetPwmChannel(ch)->raw; + json["config"]["pwm"][ch]["pin"] = GPIO_PIN_PWM_OUTPUTS[ch]; + uint8_t features = 0; + auto pin = GPIO_PIN_PWM_OUTPUTS[ch]; + if (pin == U0TXD_GPIO_NUM) features |= 1; // SerialTX supported + else if (pin == U0RXD_GPIO_NUM) features |= 2; // SerialRX supported + else if (pin == GPIO_PIN_SCL) features |= 4; // I2C SCL supported (only on this pin) + else if (pin == GPIO_PIN_SDA) features |= 8; // I2C SCL supported (only on this pin) + else if (GPIO_PIN_SCL == UNDEF_PIN || GPIO_PIN_SDA == UNDEF_PIN) features |= 12; // Both I2C SCL/SDA supported (on any pin) + #if defined(PLATFORM_ESP32) + if (pin != 0) features |= 16; // DShot supported + #endif + json["config"]["pwm"][ch]["features"] = features; } #endif #endif diff --git a/src/lua/elrsV3.lua b/src/lua/elrsV3.lua index 3223954b88..5e9d7881e7 100644 --- a/src/lua/elrsV3.lua +++ b/src/lua/elrsV3.lua @@ -71,15 +71,6 @@ local function getField(line) end end -local function constrain(x, low, high) - if x < low then - return low - elseif x > high then - return high - end - return x -end - local function incrField(step) local field = getField(lineIndex) local min, max = 0, 0 @@ -91,7 +82,22 @@ local function incrField(step) min = 0 max = #field.values - 1 end - field.value = constrain(field.value + step, min, max) + + local newval = field.value + repeat + newval = newval + step + if newval < min then + newval = min + elseif newval > max then + newval = max + end + + -- keep looping until a non-blank selection value is found + if field.values == nil or #field.values[newval+1] ~= 0 then + field.value = newval + return + end + until (newval == min or newval == max) end -- Select the next or previous editable field diff --git a/src/python/serve_html.py b/src/python/serve_html.py index 9290190808..b2d63b2cad 100644 --- a/src/python/serve_html.py +++ b/src/python/serve_html.py @@ -44,24 +44,30 @@ "modelid":255, "pwm":[ { - "config": 512, - "pin": 0 + # 10fs 4ch 1inv 4mode 1narrow + "config": 0 + 0<<10 + 0<14 + 0<<15 + 0<<19, + "pin": 0, + "features": 12 }, { "config": 1536, - "pin": 4 + "pin": 4, + "features": 12 + 16 }, { "config": 2048, - "pin": 5 + "pin": 5, + "features": 12 + 16 }, { "config": 3584, - "pin": 1 + "pin": 1, + "features": 1 + 16 }, { "config": 4608, - "pin": 3 + "pin": 3, + "features": 2 + 16 } ], "serial-protocol": 3, @@ -163,7 +169,11 @@ def update_config(): if 'button-actions' in request.json: config['config']['button-actions'] = request.json['button-actions'] if 'pwm' in request.json: - config['config']['pwm'] = request.json['pwm'] + i=0 + for x in request.json['pwm']: + print(x) + config['config']['pwm'][i]['config'] = x + i = i + 1 if 'protocol' in request.json: config['config']['serial-protocol'] = request.json['protocol'] if 'modelid' in request.json: diff --git a/src/src/rx_main.cpp b/src/src/rx_main.cpp index 9725da602f..5f94efa5f8 100644 --- a/src/src/rx_main.cpp +++ b/src/src/rx_main.cpp @@ -1725,10 +1725,12 @@ void setup() #endif initUID(); - setupTarget(); // Init EEPROM and load config, checking powerup count setupConfigAndPocCheck(); + + setupTarget(); + #if defined(OPT_HAS_SERVO_OUTPUT) // If serial is not already defined, then see if there is serial pin configured in the PWM configuration if (GPIO_PIN_RCSIGNAL_RX == UNDEF_PIN && GPIO_PIN_RCSIGNAL_TX == UNDEF_PIN) diff --git a/src/src/rxtx_common.cpp b/src/src/rxtx_common.cpp index 39bd3eb914..606c07c062 100644 --- a/src/src/rxtx_common.cpp +++ b/src/src/rxtx_common.cpp @@ -1,5 +1,7 @@ #include "targets.h" #include "common.h" +#include "config.h" +#include "logging.h" #include @@ -11,22 +13,53 @@ static uint32_t startDeferredTime = 0; static uint32_t deferredTimeout = 0; static std::function deferredFunction = nullptr; +boolean i2c_enabled = false; + static void setupWire() { #if defined(USE_I2C) - if(GPIO_PIN_SDA != UNDEF_PIN && GPIO_PIN_SCL != UNDEF_PIN) + int gpio_scl = GPIO_PIN_SCL; + int gpio_sda = GPIO_PIN_SDA; + +#if defined(TARGET_RX) && defined(GPIO_PIN_PWM_OUTPUTS) + for (uint8_t ch = 0 ; ch < GPIO_PIN_PWM_OUTPUTS_COUNT ; ++ch) + { + auto pin = GPIO_PIN_PWM_OUTPUTS[ch]; + auto pwm = config.GetPwmChannel(ch); + // if the PWM pin is nominated as SDA or SCL, and it's not configured for I2C then undef the pins + if ((pin == GPIO_PIN_SCL && pwm->val.mode != somSCL) || (pin == GPIO_PIN_SDA && pwm->val.mode != somSDA)) + { + gpio_scl = UNDEF_PIN; + gpio_sda = UNDEF_PIN; + break; + } + // If I2C pins are not defined in the hardware, then look for configured I2C + if (GPIO_PIN_SCL == UNDEF_PIN && pwm->val.mode == somSCL) + { + gpio_scl = pin; + } + if (GPIO_PIN_SCL == UNDEF_PIN && pwm->val.mode == somSDA) + { + gpio_sda = pin; + } + } +#endif + if(gpio_sda != UNDEF_PIN && gpio_scl != UNDEF_PIN) { + DBGLN("Starting wire on SCL %d, SDA %d", gpio_scl, gpio_sda); #if defined(PLATFORM_STM32) // Wire::begin() passing ints is ambiguously overloaded, use the set functions // which themselves might get the PinName overloads - Wire.setSCL(GPIO_PIN_SCL); - Wire.setSDA(GPIO_PIN_SDA); + Wire.setSCL(gpio_scl); + Wire.setSDA(gpio_sda); Wire.begin(); #else // ESP hopes to get Wire::begin(int, int) // ESP32 hopes to get Wire::begin(int = -1, int = -1, uint32 = 0) - Wire.begin((int)GPIO_PIN_SDA, (int)GPIO_PIN_SCL); + Wire.begin(gpio_sda, gpio_scl); + Wire.setClock(400000); #endif + i2c_enabled = true; } #endif }