Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changepacks/changepack_log_NrfutilCiFix.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"changes": {},
"note": "fix(ci): install pinned adafruit-nrfutil through the existing cached requirements in validation and publishing, verify CLI availability before Seeeduino nRF52 compilation, and trigger publishing on dependency changes.",
"date": "2026-09-11T06:26:20.000Z"
}
3 changes: 2 additions & 1 deletion .github/firmware-toolchain.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"schemaVersion": 1,
"arduinoCli": "1.5.1",
"platforms": {
"arduino:avr": "1.8.8"
"arduino:avr": "1.8.8",
"Seeeduino:nrf52": "1.1.13"
}
}
5 changes: 5 additions & 0 deletions .github/workflows/publish-firmware.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
- "boards/*.png"
- "schemas/**"
- "scripts/firmware.py"
- "requirements-dev.txt"
- "sources/boards/**"
workflow_dispatch:

Expand Down Expand Up @@ -49,10 +50,14 @@ jobs:
- name: Install validation dependencies
run: python -m pip install --requirement requirements-dev.txt

- name: Verify nRF52 packaging tool
run: adafruit-nrfutil version

- name: Install locked Arduino platform
run: |
arduino-cli core update-index
arduino-cli core install arduino:avr@1.8.8
arduino-cli core install Seeeduino:nrf52@1.1.13 --additional-urls https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json

- name: Test publisher
run: python -m unittest -v tests.test_firmware
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ jobs:
- name: Install validation dependencies
run: python -m pip install --requirement requirements-dev.txt

- name: Verify nRF52 packaging tool
run: adafruit-nrfutil version

- name: Install locked Arduino platform
run: |
arduino-cli core update-index
arduino-cli core install arduino:avr@1.8.8
arduino-cli core install Seeeduino:nrf52@1.1.13 --additional-urls https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json

- name: Run unit tests
run: python -m unittest -v tests.test_firmware
Expand Down
98 changes: 98 additions & 0 deletions boards/seeed-xiao-nrf52840-sense.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Hanbeon Bluetooth switch firmware for Seeed XIAO nRF52840 Sense.
//
// Reports one P record per stable press and one R record per stable release
// over both USB CDC and Nordic UART Service. A USB bridge can send HELLO,
// FLASH, OFF, or BOOT; the latter enters the serial DFU bootloader.

const byte buttonPin = 2;
const byte ledPin = 9;
const unsigned long debounceMs = 30;
const unsigned long flashMs = 120;

int lastRawReading = HIGH;
int stableState = HIGH;
unsigned long lastChangeMs = 0;
unsigned long flashUntilMs = 0;
String command;
bool commandHadCarriageReturn = false;

#ifdef USE_TINYUSB
#include <Adafruit_TinyUSB.h>
#include <Adafruit_TinyUSB_API.h>
#endif

#include <bluefruit.h>

BLEUart bleuart;

void sendLine(const char* line) {
Serial.print(line);
if (bleuart.notifyEnabled()) bleuart.print(line);
}

void enterBootloader() {
sendLine("BOOT_ENTER\n");
Serial.flush();
delay(100);
#ifdef USE_TINYUSB
TinyUSB_Port_EnterDFU();
#endif
}

void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
Serial.begin(115200);

Bluefruit.autoConnLed(false);
Bluefruit.begin();
Bluefruit.setName("HanBeon XIAO");
bleuart.begin();
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addService(bleuart);
Bluefruit.Advertising.start();
}

void loop() {
readBridgeCommands(Serial);
readBridgeCommands(bleuart);

const int rawReading = digitalRead(buttonPin);
if (rawReading != lastRawReading) {
lastChangeMs = millis();
lastRawReading = rawReading;
}
if (millis() - lastChangeMs >= debounceMs && rawReading != stableState) {
stableState = rawReading;
sendLine(stableState == LOW ? "P\n" : "R\n");
}

const bool buttonPressed = stableState == LOW;
const bool flashing = millis() < flashUntilMs;
digitalWrite(ledPin, buttonPressed || flashing ? HIGH : LOW);
}

void readBridgeCommands(Stream& stream) {
while (stream.available() > 0) {
const char next = static_cast<char>(stream.read());
if (next == '\n') {
if (command == "HELLO" && !commandHadCarriageReturn) {
sendLine("HANBEON_UNO_V1\n");
} else if (command == "FLASH") {
flashUntilMs = millis() + flashMs;
} else if (command == "OFF") {
flashUntilMs = 0;
} else if (command == "BOOT") {
enterBootloader();
}
command = "";
commandHadCarriageReturn = false;
} else if (next == '\r') {
commandHadCarriageReturn = true;
} else {
command += next;
}
}
}
2 changes: 2 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
jsonschema==4.26.0
# Linux DFU packaging tool required by Seeeduino:nrf52's compile recipe.
adafruit-nrfutil==0.5.3.post16
34 changes: 34 additions & 0 deletions sources/boards/seeed-xiao-nrf52840-sense.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"schemaVersion": 1,
"id": "seeed.xiao-nrf52840-sense",
"name": "Seeed XIAO nRF52840 Sense",
"sketch": {
"path": "boards/seeed-xiao-nrf52840-sense.ino",
"fqbn": "Seeeduino:nrf52:xiaonRF52840Sense"
},
"detect": {
"usb": [
{
"vid": "2886",
"pid": "8045",
"confidence": "exact",
"manufacturerAliases": ["Seeed Studio"],
"productAliases": ["XIAO nRF52840 Sense"]
},
{
"vid": "2886",
"pid": "0045",
"confidence": "exact",
"manufacturerAliases": ["Seeed Studio"],
"productAliases": ["XIAO nRF52840 Sense"]
}
]
},
"wiring": [
{
"from": "D2",
"to": "순간 누름 스위치 NO 단자",
"note": "스위치 COM 단자는 GND에 연결"
}
]
}
Loading