Repository navigation
Conversation
…DVERT_PATH_TABLE_SIZE, COMPANION_PACKET_POOL_SIZE)
…default unchanged) Routes that do not fit are not stored (OUT_PATH_UNKNOWN) and the contact is reached by flood. Protocol frames keep 64 path bytes. With the default size the call-site helpers compile to the previous code.
…r 128 KB parts Keeps only the first row of the precomputed base table and computes a*B by Horner (4 doublings per radix-16 digit) with the same recoding and constant-time select. RFC 8032 vectors pass with both tables.
… stalled frame Without it, a frame longer than MAX_FRAME_SIZE is executed truncated, and a frame cut short by the sender swallows the start of the next one. Worth enabling by default; kept behind a flag here so other boards build unchanged.
…t of flash Radio settings still go through the binary commands (CMD_SET_RADIO_PARAMS and friends).
…crypto stack) - CubeCellRadio: mesh::Radio on the Heltec SX1262 driver; DIO1 runs callbacks in interrupt context, so main-context radio calls detach DIO1 (RadioLock) and the RX buffer is copied in a critical section - FlashRecord/FlashRecordStore: 160-byte identity + prefs record, A/B over two SFLASH user rows, CRC-32 - BigStack + IDENTITY_CRYPTO_ON_BIG_STACK: Ed25519 runs on a heap-allocated stack (the main stack is fixed at 2 KB); Sbrk lets the heap grow up to the stack region - TxGate: the node never transmits until a private key has been imported - SmallStrtod: decimal-only strtod/strtof/atof (newlib's pulls in ~7 KB) - pure helpers with host tests: NMEA parser (integer only), GPS power policy, status lines, 5x7 font, debounced button, radio airtime/score
… with OLED status and GPS Legacy board: ASR6502 (Cortex-M0+), 128 KB flash, 16 KB RAM, fixed 2 KB stack. Companion over USB/UART only (no BLE, no WiFi). The node does not generate its own identity: import a private key from the app. - 8-line SSD1306 status screen on the raw PSoC I2C block (Wire's buffers do not fit in RAM), auto-off after 30 s, USER key wakes it - Air530Z GPS: powered when a fix is wanted, off after the fix, $PCAS03 keeps only GGA+RMC, sets the clock from RMC; 'gps' / 'gps_interval' through the custom-var commands - contacts in RAM (12), identity and prefs in SFLASH
…fered A main loop busy for more than 100 ms (e.g. Ed25519 on a small MCU) must not drop a frame whose remaining bytes are already waiting in the UART buffer.
… v2); no hard-coded upload port Version 2 of the SFLASH record (192 bytes) adds airtime/rx/tx delay factors, multi-acks, manual add, telemetry modes, advert location policy, auto-add, path hash mode, tz offset, CAD/AGC/interference and rx gain. Version 1 records still load (the new settings then keep their defaults).
Contacts the app adds or edits (CMD_ADD_UPDATE_CONTACT) are pinned in the free SFLASH user row; removing a contact unpins it, a fourth contact stays RAM-only, factory reset clears the pins. Contacts learnt from adverts or imports stay RAM-only. The MyMesh hooks are behind CONTACT_PIN_STORE (default off).
…cord magic
Function names follow the project's camelCase convention, new files are formatted with .clang-format,
project-internal references are removed from comments and tests. The flash record is now written with
the "ASR1" magic; records from early test builds ("KTM1") still load.
…02S in the PR build check - build.sh copies the .cyacd (CubeCellFlash / bootloader image) and .hex of ASR650X_PLATFORM envs to out/ - run-unit-tests runs native_noop_config and native_ed25519_small as well - pr-build-check builds Heltec_CubeCell_AB02S_companion_radio_usb (128 KB part: catches size regressions)
…them GET_CONTACTS only sends contacts with lastmod > since (0 for a full listing); pinned contacts were restored with lastmod 0, so they were in the table but never reported to the app.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #2017. Related: #1632 (crypto de-duplication would free more flash on this part).
Most of the implementation was done by an AI coding agent (Claude) working from my ideas and direction; it was
tested on real hardware as described below.
What this is
A companion firmware for the Heltec CubeCell GPS-6502 (HTCC-AB02S). This is a legacy board with very small
resources: ASR6502 (Cortex-M0+), 128 KB flash, 16 KB RAM, a fixed 2 KB main stack, SX1262, Air530Z GPS and a
0.96" SSD1306 OLED.
app with a placeholder identity derived from the chip ID and never transmits.
removing a contact frees its place), stored direct routes up to 16 bytes (longer routes are
not stored and that contact is reached by flood), offline queue of 3 messages, 1 group channel, no text CLI.
Settings kept across reboots: identity, name, radio parameters and TX power, GPS on/off and interval, and the
companion settings (multi-acks, manual add, telemetry modes, advert location policy, auto-add, path hash mode,
time zone, airtime and delay factors, CAD/AGC/interference, RX gain) and the 3 pinned contacts. Not kept: the
manually set location, the default scope, channels, the other contacts.
frequency/SF). It turns off after 30 s; the USER button wakes it.
gpsandgps_intervalare exposed through the custom-variable commands.New env:
Heltec_CubeCell_AB02S_companion_radio_usb(platformheltecautomation/heltec-cubecell@1.1.0).Changes to shared code: all opt-in, other boards build unchanged
MAX_ANON_CONTACTS,MAX_PACKET_HASHES,ADVERT_PATH_TABLE_SIZE,COMPANION_PACKET_POOL_SIZECONTACT_OUT_PATH_SIZEMAX_PATH_SIZERX_DELAY_FAST_POWpow()(< 1 % error)DISABLE_CLI_RESCUEDISABLE_COMPANION_CLICONFIG_SERIALIZER_NOOPED25519_SMALL_BASE_TABLEIDENTITY_CRYPTO_ON_BIG_STACKCONTACT_PIN_STORESERIAL_FRAME_STRICTMAX_FRAME_SIZEinstead of executing them truncated; abandon a partial frame after 100 ms with nothing bufferedSERIAL_FRAME_STRICTfixes two problems that every USB companion has today: an oversize frame is executed afterbeing cut short, and a frame cut short by the sender swallows the start of the next one. It might be worth making it
the default; I kept it behind a flag so this PR does not change other boards.
New code lives in
src/helpers/asr650x/(compiled only by this env) andvariants/heltec_cubecell_ab02s/.examples/companion_radio/gets a flash-rowDataStorefor boards without a filesystem (FlashDataStore.*, selectedin
DataStore.h) and amain.cppbranch forASR650X_PLATFORM.Evidence
RAK_4631_companion_radio_usb,Heltec_v3_companion_radio_usbandPicoW_companion_radio_usbreport identical RAM and flash sizes before and after this branch (every change toshared code is behind a flag, and new files compile only for this env).
pio test -e native88/88, plusnative_noop_config3/3,native_ed25519_small3/3 (RFC 8032vectors with both tables),
native_kiss_modem8/8.Static RAM is 9 408 B (
.data+.bss+.ramvectors). Measured on the board: main stack peak 1 360 B (of2 048), crypto stack peak 1 760 B, heap peak 3 992 B, so about 870 B of RAM stays free.
transmit before a key is imported, framing resync, signatures verified on a PC, adverts imported and rejected;
15/15 GPS/OLED checks (power control, NMEA filtered to GGA+RMC, settings persist, OLED acknowledges on I2C); route
storage: a 20-byte route is not stored and a 4-byte route is kept; companion settings set over the protocol survive
a reboot.
adverts both ways; a direct message AB02S -> nRF acknowledged over the air (round trip 912 ms); a message
nRF -> AB02S received; a contact added in the app was still listed after an AB02S reboot.
Build and flashing
build.shcopies the.cyacdand.hexofASR650X_PLATFORMenvs toout/(the release workflows buildevery
*_companion_radio_usbenv). Flash with Heltec's CubeCellFlash (.cyacd) orpio run -e Heltec_CubeCell_AB02S_companion_radio_usb -t upload --upload-port <port>.run-unit-testsalso runs the two new native envs;pr-build-checkbuilds the AB02S env, so a change thatmakes it outgrow 128 KB shows up in CI.
Notes for review
Radio.*), not RadioLib: RadioLib does not fit next to themesh code in 128 KB. Its callbacks run in interrupt context; main-context radio calls detach the DIO1 interrupt
while they talk to the chip.
variants/heltec_cubecell_ab02s/c_include_order.pyworks around a header-name clash on case-insensitive filesystems (the framework's C
aes.hvs rweather/Crypto'sAES.h); it only affects C sources of this env.src/helpers/asr650x/SmallStrtod.cppreplaces newlib'sstrtod/strtof/atofon this env only (decimal numbersonly; newlib's version pulls in ~7 KB).
Wirekeeps two 128-byte buffers per instance, which this RAMbudget cannot spare.