Skip to content

firmware2 M1: HAL bring-up for bench 1–2 - #9

Open
NT7S wants to merge 1 commit into
masterfrom
cursor/firmware2-m1-a805
Open

NT7S wants to merge 1 commit into
masterfrom
cursor/firmware2-m1-a805

Conversation

@NT7S

@NT7S NT7S commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Summary

Milestone M1 for firmware2 on the AVR128DA48. One bring-up sketch: Optiboot/UPDI notes, SH1106 OLED, buttons, SYNC LED, section 2.2 relay codes as GPIO, ADC on TX_ISENSE and CC1/CC2, the 50 ms / 20 ms soft-start gates, Si5351 CLK0 at a fixed in-band carrier, MCP4725 bias, and a 24AA64 presence check. The SAMD21 tree and the license files are untouched. Not merged.

Relays are fully on. Nothing in this firmware PWM-holds them, and nothing calls delay(). PA4 stays low until DSP1, and only after both soft-start gates.

K3 — DS40002183E timer check

Checked against Microchip DS40002183E (the E revision of DS40002183), not only the DxCore docs. The record is firmware2/OpenBeacon2/ob2_pwm.h, and the host test locks it. Shipped firmware does not enable any of these outputs.

Pin Timer outputs that exist Source
PA5 TCA0 WO5 when TCA0 is on PORTA. TCD0 WOB on the default TCD route. TCAROUTEA 16.3.7 p.161; TCDROUTEA 16.3.9 p.163
PA6 TCD0 WOC only. No TCA waveform. I/O mux table; TCDROUTEA
PB1 TCA1 WO1 on PORTB (default). TCA0 WO1 only when TCA0 is moved to PORTB. TCAROUTEA
PA4 TCD0 WOA on the default route. TCDROUTEA. This is the TX key.
PB0 TCA1 WO0, and TCA0 WO0 if TCA0 is on PORTB. TCAROUTEA. This is USART3 TX to the GPS.

TCBROUTEA 16.3.8 p.162: TCB0 is PA2/PF4, TCB1 is PA3/PF5, TCB2 is PC0/PB4, TCB3 is PB5/PC1, TCB4 is PG3/PC6. No TCB waveform on PA5, PA6, or PB1.

The spec's three traps match the datasheet:

  1. TCD0 WOA is PA4. Enabling it keys the 12 V PA supply. analogWrite() on PA4–PA7 is not used; DxCore can route that range onto TCD0.
  2. TCA1 WO0 is PB0. A bench PWM build would have to leave that compare output disabled.
  3. TCA0 cannot serve PA5 and PB1 at once. PORTA and PORTB are different TCAROUTEA values.

TCD.CTRLC (23.5.3 p.321): CMPCSEL resets to 0, so WOC follows PWMA (WOA, which is PA4). The proposed bench allocation (PA5+PA6 on TCD0, PB1 on TCA1 WO1) only works if CMPCSEL is set to PWMB, and then PA5 and PA6 share one duty. FAULTCTRL CMPAEN has to stay off so WOA is not driven. That allocation is not built here.

CI

Green on 12ea8e3e. Both jobs passed.

https://github.com/etherkit/OpenBeacon2/actions/runs/40565439892

Build size

From the DxCore job log:

Sketch uses 21750 bytes (16%) of program storage space. Maximum is 130560 bytes.
Global variables use 1268 bytes (7%) of dynamic memory, leaving 15116 bytes for local variables. Maximum is 16384 bytes.

FQBN DxCore:megaavr:avrdaopti:chip=avr128da48,clock=24internal,millis=tcb2,bootloaderusart=ser0. The only compiler warnings were in Etherkit Si5351 2.4.0 (set_clock_disable, comparison always true). Same size as the local build.

Host tests

From the host job log (ctest --test-dir firmware2/host/build --output-on-failure):

Test project /home/runner/work/OpenBeacon2/OpenBeacon2/firmware2/host/build
    Start 1: host
1/1 Test #1: host .............................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.09 sec

ctest does not print doctest's summary on success. The same binary, run directly, reports 18 cases and 771 assertions, all passing. That covers the pin table from M0 plus the four legal relay codes, the four forbidden codes, all 14 bands, the soft-start edges (49 ms, 50 ms without a CC sample, 19 ms / 20 ms of boost), CC thresholds in both orientations, 200 ms CC debounce, isense, and the MCP4725 code.

Bench 1 — Optiboot, for Jason

Programmer is DxCore serialupdi at 230400 baud on the UPDI dongle at J13. The later upload is the CP2102N at 115200, DTR through C37/R36. Use a dummy load. DSP1 transmits.

arduino-cli compile --show-properties on this FQBN resolves:

Fuse Value Meaning
0 WDTCFG 0x00 Watchdog off
1 BODCFG 0x00 BOD off, the menu default
2 OSCCFG 0x00 Internal HF oscillator
5 SYSCFG0 0xC0 What burn-bootloader would write. Do not use this. See discrepancies.
6 SYSCFG1 0x04 8 ms startup
7 CODESIZE 0x00
8 BOOTSIZE 0x01 512-byte boot section

Entry condition resolves to _extr. bootloader.class does not resolve, so stock burn-bootloader looks for a file named {bootloader.class}_ser0_extr.hex. The image that matches a 128 kB DA, USART0 default pins, and _extr is optiboot_128dx_ser0_extr.hex.

Burn fuse 5 as 0xC8 (RSTPINCFG = RESET, EESAVE still clear). 0xC0 leaves PF6 as GPIO and DTR will not enter Optiboot. EESAVE clear means the chip erase wipes internal EEPROM. The 24AA64 is not part of that erase.

FQBN='DxCore:megaavr:avrdaopti:chip=avr128da48,clock=24internal,millis=tcb2,bootloaderusart=ser0'
# Paths under the DxCore 1.6.2 package. On a default arduino-cli install that is
# ~/.arduino15/packages/DxCore/hardware/megaavr/1.6.2/
HEX=".../bootloaders/hex/optiboot_128dx_ser0_extr.hex"
PY=".../tools/prog.py"

python3 "$PY" -t uart -u "$PROG" -b 230400 -d avr128da48 \
  --fuses 0:0x00 1:0x00 2:0x00 5:0xC8 6:0x04 7:0x00 8:0x01 \
  -f "$HEX" -a write

arduino-cli upload -b "$FQBN" -p "$APP" firmware2/OpenBeacon2

$PROG is the SerialUPDI adapter. $APP is the CP2102N. Wiping the bootloader and recovering it is the same prog.py write over J13.

Bench 2 — panel and relays

  1. OLED shows OB2 F2 80/60m, ABC 000, EE ok once the 24AA64 answers, and key idle after the 50 ms gate (it can already say that by the time the display comes up). USB serial at 115200 prints one OB2 M1 line.
  2. Hold each button. Its letter in btn UDLRB12 appears, and the SYNC LED stays on for the hold. Released, the LED blinks.
  3. UP/DOWN steps F2, F3, F4, F5. Scope the gates: 000, 010, 100, 101 only. +5 V relay current should step 0 / 42 / 42 / 84 mA, never more than four coils. PA4 stays low.
  4. DSP1 on F2: PA4 rises, and about 20 ms later CLK0 is 3.5686 MHz and the bias leaves 0 (500 mV command). BACK or DSP2 zeros the bias, disables CLK0, then drops PA4. Repeat on F4 and confirm 14.0956 MHz, and that the relays moved only while the carrier was off.
  5. CC millivolts and TX_ISENSE are on the OLED. Under 100 mA the current line stays <100. There is no overcurrent trip in M1.

The 500 mV bias is a placeholder, not a calibrated level. CLK0 drive is 8 mA, carried from the old firmware; section 4.4 does not restate drive strength.

Discrepancies

Not silently changed:

  • The spec draft is not in the repo (documentation/ and docs/ have no copy), so these two stale lines are noted here instead of edited. Section 4.5 still says USART3 needs a PB1 pull-up. PB1 is BAND_C with R91, 22 kΩ to ground. A pull-up fights that and can bias Q9 on. This firmware drives PB1 low and does not enable the pull-up. RXEN stays off. Section 2.1 still says Q7 drives K2/K3/K5/K6. Section 2.2 assigns K3/K6 to BAND_C / Q9, and K2/K5 to BAND_B / Q7. The pin header follows section 2.2 and quotes the section 2.1 wording on the BAND_B row. docs/VERIFY.md has the same stale Q7 sentence and was left alone.
  • DxCore 1.6.2 avrdaopti writes SYSCFG0 0xC0 for both Reset-pin menu choices (DS40002183E 7.9.2.4: that is PF6 as GPIO). External reset needs 0xC8. The bench procedure burns 0xC8 on purpose. bootloader.class is unset, so arduino-cli burn-bootloader does not name a real hex file. The non-Optiboot DA menu does set the reset bit.
  • clock=24internal still does not set OSCHF autotune. Section 4.1's crystal-disciplined clock is not this sketch.
  • U8g2's second hardware-SPI class is a no-op on DxCore because SPI_INTERFACES_COUNT is 1 even though SPI1 exists. The sketch swaps the single SPI object onto SPI1 ALT1 before begin(). SPI0 (PA4–PA7) is never started. The display uses the page buffer, not the 1 KB full buffer.
  • 24AA64T-I/OT (U8, SOT-23-5) has no A0/A1/A2 on the symbol (SCL, VSS, SDA, VCC, WP). Address used is 0x50. The four bytes OB21 are a presence check, not the config schema.
  • MCP4725 code clamps 5000 mV to 4095. (5000 * 4096) / 5000 is 4096, which does not fit in 12 bits.
  • TWI is 100 kHz for bring-up. Section 4.4 does not set the bus speed.
  • CC "none" (both pins under 0.2 V) is reported as none and, per section 4.14, is the Default policy case. Power limiting is not in this milestone.
  • isense_k, the overcurrent trip, GPS, and the beacon engine are later milestones.
Open in Web Open in Cursor 

Drive the section 2.2 relay codes as GPIO, sample TX_ISENSE and the CC pins, and hold the PA off until the soft-start gates pass. The sketch adds the SH1106, buttons, SYNC LED, a fixed CLK0 carrier, the MCP4725, and a 24AA64 presence check. Relay PWM stays off; the timer map is the DS40002183E check.

Co-authored-by: Jason Milldrum <NT7S@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants