fix: review fixes for the boot pin warnings

- The backup record's fallback RX pin is 35, as the radio's default is.
- BootPins.h, pins.js and Transceiver.cpp say to keep the pins, the radio
  pins checked and the shared RX/TX rule in step.
- index.js reads the chip model through one chipModel().
- BootPins.RADIO is RADIO_PINS; the P4 test builds its config once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-29 22:44:23 +01:00
parent 8a59f51111
commit 658f5eabeb
6 changed files with 20 additions and 14 deletions

View file

@ -418,6 +418,9 @@ function sendEdit(name, fields, target, cb) {
// A command's repeat count, when the caller gave one. // A command's repeat count, when the caller gave one.
function repeatOf(repeat) { return typeof repeat === 'number' ? repeat : undefined; } function repeatOf(repeat) { return typeof repeat === 'number' ? repeat : undefined; }
function gone(what) { ui.errorMessage(`The ${what} is no longer there.`); } function gone(what) { ui.errorMessage(`The ${what} is no longer there.`); }
// The chip model the header sent: '' for the original ESP32, then s3, p4es
// and so on.
function chipModel() { return document.getElementById('divContainer').getAttribute('data-chipmodel') || ''; }
// The lists redraw from the model after events, a burst of them at once. // The lists redraw from the model after events, a burst of them at once.
// While the socket is down they wait for the next sync. // While the socket is down they wait for the next sync.
var renderPending = {}; var renderPending = {};
@ -1601,7 +1604,7 @@ class Wifi {
this.onETHBoardTypeChanged(document.getElementById('selETHBoardType')); this.onETHBoardTypeChanged(document.getElementById('selETHBoardType'));
this.initialized = true; this.initialized = true;
} }
isP4() { return (document.getElementById('divContainer').getAttribute('data-chipmodel') || '').startsWith('p4'); } isP4() { return chipModel().startsWith('p4'); }
clockModes() { return this.isP4() ? this.ethClockModesP4 : this.ethClockModes; } clockModes() { return this.isP4() ? this.ethClockModesP4 : this.ethClockModes; }
// The board presets, clock modes and pins of the chip: the ESP32's or the // The board presets, clock modes and pins of the chip: the ESP32's or the
// P4's. The chip comes with the sync, after init(). // P4's. The chip comes with the sync, after init().
@ -1976,8 +1979,7 @@ class Somfy {
// Warns of radio pins that can stop the board booting (issue #34). // Warns of radio pins that can stop the board booting (issue #34).
checkBootPins() { checkBootPins() {
let trans = ui.fromElement(document.getElementById('divTransceiverSettings')).transceiver; let trans = ui.fromElement(document.getElementById('divTransceiverSettings')).transceiver;
let chip = document.getElementById('divContainer').getAttribute('data-chipmodel') || ''; let warnings = BootPins.radioWarnings(chipModel(), trans.config);
let warnings = BootPins.radioWarnings(chip, trans.config);
let div = document.getElementById('divRadioBootPins'); let div = document.getElementById('divRadioBootPins');
div.innerText = warnings.join('\n'); div.innerText = warnings.join('\n');
div.style.display = warnings.length > 0 ? '' : 'none'; div.style.display = warnings.length > 0 ? '' : 'none';
@ -2753,7 +2755,7 @@ class Somfy {
loadPins(type, sel, opt) { loadPins(type, sel, opt) {
while (sel.firstChild) sel.removeChild(sel.firstChild); while (sel.firstChild) sel.removeChild(sel.firstChild);
let cm = document.getElementById('divContainer').getAttribute('data-chipmodel'); let cm = chipModel();
// The pre-v3 P4 build has the same pins. // The pre-v3 P4 build has the same pins.
if (cm === 'p4es') cm = 'p4'; if (cm === 'p4es') cm = 'p4';
let pm = this.pinMaps.find(x => x.name === cm) || { name: '', maxPins: 39, inputs: [], outputs: [] }; let pm = this.pinMaps.find(x => x.name === cm) || { name: '', maxPins: 39, inputs: [], outputs: [] };
@ -4200,7 +4202,7 @@ class Firmware {
div.style.display = ''; div.style.display = '';
} }
updateFirmware() { updateFirmware() {
let chip = document.getElementById('divContainer').getAttribute('data-chipmodel') || ''; let chip = chipModel();
// Firmware from before the field leaves it out: undefined, not false. // Firmware from before the field leaves it out: undefined, not false.
if (proto.model.header.hasOtaSlot === false) { if (proto.model.header.hasOtaSlot === false) {
ui.infoMessage(`This device has no OTA slot, so its firmware is flashed over USB with SomfyController.onboard.esp32${chip}.bin, from the release's SomfyController.onboard.esp32${chip}.bin.zip. That image holds the web UI and an empty configuration too, so take a backup first and restore it afterwards.`); ui.infoMessage(`This device has no OTA slot, so its firmware is flashed over USB with SomfyController.onboard.esp32${chip}.bin, from the release's SomfyController.onboard.esp32${chip}.bin.zip. That image holds the web UI and an empty configuration too, so take a backup first and restore it afterwards.`);
@ -4223,7 +4225,7 @@ class Firmware {
let div = this.createFileUploader('/updateApplication'); let div = this.createFileUploader('/updateApplication');
general.reloadApp = true; general.reloadApp = true;
let inst = div.querySelector('div[id=divInstText]'); let inst = div.querySelector('div[id=divInstText]');
let chip = document.getElementById('divContainer').getAttribute('data-chipmodel') || ''; let chip = chipModel();
inst.innerHTML = `<div style="font-size:14px;">Select a binary file [SomfyController.littlefs.esp32${chip}.bin] containing the littlefs data for the application then press the Upload File button.</div>`; inst.innerHTML = `<div style="font-size:14px;">Select a binary file [SomfyController.littlefs.esp32${chip}.bin] containing the littlefs data for the application then press the Upload File button.</div>`;
if (this.isMobile()) { if (this.isMobile()) {
inst.innerHTML += `<div style="width:100%;color:red;text-align:center;font-weight:bold;"><span style="margin-top:7px;width:100%;background:yellow;padding:3px;display:inline-block;border-radius:5px;background:white;">WARNING<span></div>`; inst.innerHTML += `<div style="width:100%;color:red;text-align:center;font-weight:bold;"><span style="margin-top:7px;width:100%;background:yellow;padding:3px;display:inline-block;border-radius:5px;background:white;">WARNING<span></div>`;

View file

@ -1,6 +1,8 @@
// The strapping pins whose level at reset can keep each chip from starting // The strapping pins whose level at reset can keep each chip from starting
// the firmware, as src/BootPins.h has them for the log. A radio that drives // the firmware, as src/BootPins.h has them for the log. A radio that drives
// one at power-up stops the board booting until EN is pressed (issue #34). // one at power-up stops the board booting until EN is pressed (issue #34).
// Keep the pins, the radio pins checked and the shared RX/TX rule in step
// with that file.
// The minify step joins this file into index.js; Node loads it on its own for // The minify step joins this file into index.js; Node loads it on its own for
// the tests (test/js). // the tests (test/js).
class BootPins { class BootPins {
@ -9,7 +11,7 @@ class BootPins {
static radioWarnings(chipModel, config) { static radioWarnings(chipModel, config) {
const chip = BootPins.CHIPS[chipModel || ''] || {}; const chip = BootPins.CHIPS[chipModel || ''] || {};
const warnings = []; const warnings = [];
for (const [field, name] of BootPins.RADIO) { for (const [field, name] of BootPins.RADIO_PINS) {
const pin = config[field]; const pin = config[field];
if (field === 'RXPin' && pin === config.TXPin) continue; if (field === 'RXPin' && pin === config.TXPin) continue;
const effect = chip[pin]; const effect = chip[pin];
@ -32,5 +34,5 @@ BootPins.CHIPS = {
// The radio pins the CC1101 drives at power-up, before it is set up: GDO0 // The radio pins the CC1101 drives at power-up, before it is set up: GDO0
// puts out a clock, GDO2 CHIP_RDYn, and SO follows CHIP_RDYn while CSN is // puts out a clock, GDO2 CHIP_RDYn, and SO follows CHIP_RDYn while CSN is
// low. // low.
BootPins.RADIO = [['TXPin', 'TX'], ['RXPin', 'RX'], ['MISOPin', 'MISO']]; BootPins.RADIO_PINS = [['TXPin', 'TX'], ['RXPin', 'RX'], ['MISOPin', 'MISO']];
if (typeof module !== 'undefined' && module.exports) module.exports = { BootPins }; if (typeof module !== 'undefined' && module.exports) module.exports = { BootPins };

View file

@ -9,7 +9,9 @@
// the firmware. The ROM reads them before any code runs, so a radio that // the firmware. The ROM reads them before any code runs, so a radio that
// drives one at power-up stops the board booting until EN is pressed (issue // drives one at power-up stops the board booting until EN is pressed (issue
// #34). The strapping pins that only pick a download mode, quiet the boot // #34). The strapping pins that only pick a download mode, quiet the boot
// log or set the SDIO timing aren't listed. web UI: data-src/js/pins.js. // log or set the SDIO timing aren't listed. The web UI has the same pins in
// data-src/js/pins.js, and checks the same radio pins as
// transceiver_config_t::apply(): keep the three in step.
// //
// Returns what the pin does at reset, or nullptr for a pin that can't stop // Returns what the pin does at reset, or nullptr for a pin that can't stop
// the boot. // the boot.

View file

@ -183,7 +183,7 @@ struct trans_record_t {
uint8_t MOSIPin = 23; uint8_t MOSIPin = 23;
uint8_t MISOPin = 19; uint8_t MISOPin = 19;
uint8_t TXPin = 13; uint8_t TXPin = 13;
uint8_t RXPin = 12; uint8_t RXPin = 35;
float frequency = 433.42; float frequency = 433.42;
float rxBandwidth = 99.97; float rxBandwidth = 99.97;
float deviation = 47.60; float deviation = 47.60;

View file

@ -605,7 +605,7 @@ void transceiver_config_t::apply() {
ESP_LOGD(TAG, "Applying radio settings - Setting Data Pins RX:%u TX:%u", this->RXPin, this->TXPin); ESP_LOGD(TAG, "Applying radio settings - Setting Data Pins RX:%u TX:%u", this->RXPin, this->TXPin);
// The pins the CC1101 drives at power-up, before it is set up: GDO0 // The pins the CC1101 drives at power-up, before it is set up: GDO0
// puts out a clock, GDO2 CHIP_RDYn, and SO follows CHIP_RDYn while CSN // puts out a clock, GDO2 CHIP_RDYn, and SO follows CHIP_RDYn while CSN
// is low. // is low. The web UI checks the same (data-src/js/pins.js).
warnBootPin("TX", this->TXPin); warnBootPin("TX", this->TXPin);
if(this->RXPin != this->TXPin) warnBootPin("RX", this->RXPin); if(this->RXPin != this->TXPin) warnBootPin("RX", this->RXPin);
warnBootPin("MISO", this->MISOPin); warnBootPin("MISO", this->MISOPin);

View file

@ -38,7 +38,7 @@ test('MISO and TX warn, the pins the radio only reads do not', () => {
}); });
test('the pre-v3 P4 has the P4 pins', () => { test('the pre-v3 P4 has the P4 pins', () => {
assert.deepEqual(BootPins.radioWarnings('p4es', { SCKPin: 27, CSNPin: 46, MOSIPin: 32, MISOPin: 33, TXPin: 2, RXPin: 35 }), const p4 = { SCKPin: 27, CSNPin: 46, MOSIPin: 32, MISOPin: 33, TXPin: 2, RXPin: 35 };
BootPins.radioWarnings('p4', { SCKPin: 27, CSNPin: 46, MOSIPin: 32, MISOPin: 33, TXPin: 2, RXPin: 35 })); assert.equal(BootPins.radioWarnings('p4', p4).length, 1);
assert.equal(BootPins.radioWarnings('p4', { SCKPin: 27, CSNPin: 46, MOSIPin: 32, MISOPin: 33, TXPin: 2, RXPin: 35 }).length, 1); assert.deepEqual(BootPins.radioWarnings('p4es', p4), BootPins.radioWarnings('p4', p4));
}); });