Skip to content

Commit 34fdd94

Browse files
Vladimir Zaytsevclaude
andcommitted
Add MuziWorks Base Duo board support (nRF52840 + LR1121)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 31007d9 commit 34fdd94

10 files changed

Lines changed: 616 additions & 0 deletions

File tree

boards/muziworks-duo.json

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"build": {
3+
"arduino": {
4+
"ldscript": "nrf52840_s140_v6.ld"
5+
},
6+
"core": "nRF5",
7+
"cpu": "cortex-m4",
8+
"extra_flags": "-DARDUINO_MUZIWORKS_DUO -DNRF52840_XXAA",
9+
"f_cpu": "64000000L",
10+
"hwids": [
11+
["0x239A", "0x8029"],
12+
["0x239A", "0x0029"],
13+
["0x239A", "0x002A"],
14+
["0x239A", "0x802A"]
15+
],
16+
"usb_product": "MuziWorks-Duo-BOOT",
17+
"mcu": "nrf52840",
18+
"variant": "muziworks_duo",
19+
"bsp": {
20+
"name": "adafruit"
21+
},
22+
"softdevice": {
23+
"sd_flags": "-DS140",
24+
"sd_name": "s140",
25+
"sd_version": "6.1.1",
26+
"sd_fwid": "0x00B6"
27+
},
28+
"bootloader": {
29+
"settings_addr": "0xFF000"
30+
}
31+
},
32+
"connectivity": ["bluetooth"],
33+
"debug": {
34+
"jlink_device": "nRF52840_xxAA",
35+
"svd_path": "nrf52840.svd",
36+
"openocd_target": "nrf52.cfg"
37+
},
38+
"frameworks": ["arduino"],
39+
"name": "MuziWorks Base Duo",
40+
"upload": {
41+
"maximum_ram_size": 235520,
42+
"maximum_size": 811008,
43+
"speed": 115200,
44+
"protocol": "nrfutil",
45+
"protocols": [
46+
"jlink",
47+
"nrfjprog",
48+
"nrfutil",
49+
"stlink",
50+
"cmsis-dap",
51+
"blackmagic"
52+
],
53+
"use_1200bps_touch": true,
54+
"require_upload_port": true,
55+
"wait_for_upload_port": true
56+
},
57+
"url": "https://www.muziworks.com",
58+
"vendor": "MuziWorks"
59+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
3+
#include <RadioLib.h>
4+
#include "MeshCore.h"
5+
6+
class CustomLR1121 : public LR1121 {
7+
bool _rx_boosted = false;
8+
9+
public:
10+
CustomLR1121(Module *mod) : LR1121(mod) { }
11+
12+
size_t getPacketLength(bool update) override {
13+
size_t len = LR1121::getPacketLength(update);
14+
if (len == 0 && getIrqStatus() & RADIOLIB_LR11X0_IRQ_HEADER_ERR) {
15+
MESH_DEBUG_PRINTLN("LR1121: got header err, calling standby()");
16+
standby();
17+
}
18+
return len;
19+
}
20+
21+
float getFreqMHz() const { return freqMHz; }
22+
23+
int16_t setRxBoostedGainMode(bool en) {
24+
_rx_boosted = en;
25+
return LR1121::setRxBoostedGainMode(en);
26+
}
27+
28+
bool getRxBoostedGainMode() const { return _rx_boosted; }
29+
30+
bool isReceiving() {
31+
uint16_t irq = getIrqStatus();
32+
bool detected = ((irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || (irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED));
33+
return detected;
34+
}
35+
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
#include "CustomLR1121.h"
4+
#include "RadioLibWrappers.h"
5+
#include "LR11x0Reset.h"
6+
7+
class CustomLR1121Wrapper : public RadioLibWrapper {
8+
public:
9+
CustomLR1121Wrapper(CustomLR1121& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
10+
void doResetAGC() override { lr11x0ResetAGC((LR11x0 *)_radio, ((CustomLR1121 *)_radio)->getFreqMHz()); }
11+
bool isReceivingPacket() override {
12+
return ((CustomLR1121 *)_radio)->isReceiving();
13+
}
14+
float getCurrentRSSI() override {
15+
float rssi = -110;
16+
((CustomLR1121 *)_radio)->getRssiInst(&rssi);
17+
return rssi;
18+
}
19+
20+
void onSendFinished() override {
21+
RadioLibWrapper::onSendFinished();
22+
_radio->setPreambleLength(16); // overcomes weird issues with small and big pkts
23+
}
24+
25+
float getLastRSSI() const override { return ((CustomLR1121 *)_radio)->getRSSI(); }
26+
float getLastSNR() const override { return ((CustomLR1121 *)_radio)->getSNR(); }
27+
28+
void setRxBoostedGainMode(bool en) override {
29+
((CustomLR1121 *)_radio)->setRxBoostedGainMode(en);
30+
}
31+
bool getRxBoostedGainMode() const override {
32+
return ((CustomLR1121 *)_radio)->getRxBoostedGainMode();
33+
}
34+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifdef MUZIWORKS_DUO
2+
3+
#include "MuziWorksDuoBoard.h"
4+
5+
#include <Arduino.h>
6+
#include <Wire.h>
7+
8+
void MuziWorksDuoBoard::begin() {
9+
NRF52BoardDCDC::begin();
10+
11+
pinMode(PIN_VBAT_READ, INPUT);
12+
pinMode(LED_GREEN, OUTPUT);
13+
pinMode(LED_BLUE, OUTPUT);
14+
15+
// LEDs off (active LOW)
16+
digitalWrite(LED_GREEN, !LED_STATE_ON);
17+
digitalWrite(LED_BLUE, LED_STATE_ON);
18+
19+
#if defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL)
20+
Wire.setPins(PIN_WIRE_SDA, PIN_WIRE_SCL);
21+
#endif
22+
23+
Wire.begin();
24+
25+
delay(10);
26+
}
27+
28+
#endif
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
3+
#include <MeshCore.h>
4+
#include <Arduino.h>
5+
#include <helpers/NRF52Board.h>
6+
7+
#ifdef MUZIWORKS_DUO
8+
9+
#define PIN_VBAT_READ BATTERY_PIN
10+
#define BATTERY_SAMPLES 8
11+
12+
class MuziWorksDuoBoard : public NRF52BoardDCDC {
13+
public:
14+
MuziWorksDuoBoard() : NRF52Board("MuziWorksDuo_OTA") {}
15+
void begin();
16+
17+
uint16_t getBattMilliVolts() override {
18+
analogReadResolution(12);
19+
20+
uint32_t raw = 0;
21+
for (int i = 0; i < BATTERY_SAMPLES; i++) {
22+
raw += analogRead(PIN_VBAT_READ);
23+
}
24+
raw = raw / BATTERY_SAMPLES;
25+
return (ADC_MULTIPLIER * raw);
26+
}
27+
28+
const char* getManufacturerName() const override {
29+
return "MuziWorks Duo";
30+
}
31+
32+
#if defined(LED_GREEN)
33+
void onBeforeTransmit() override {
34+
digitalWrite(LED_GREEN, LED_STATE_ON);
35+
}
36+
void onAfterTransmit() override {
37+
digitalWrite(LED_GREEN, !LED_STATE_ON);
38+
}
39+
#endif
40+
};
41+
42+
#endif
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
; ----------------- MuziWorks Base Duo (nRF52840 + LR1121) ---------------------
2+
[muziworks_duo]
3+
extends = nrf52_base
4+
board = muziworks-duo
5+
board_build.ldscript = boards/nrf52840_s140_v6.ld
6+
build_flags = ${nrf52_base.build_flags}
7+
${sensor_base.build_flags}
8+
-I src/helpers/nrf52
9+
-I lib/nrf52/s140_nrf52_6.1.1_API/include
10+
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
11+
-I variants/muziworks_duo
12+
-D NRF52_PLATFORM
13+
-D MUZIWORKS_DUO
14+
-D ENV_INCLUDE_GPS=0
15+
-D CONFIG_NFCT_PINS_AS_GPIOS=1
16+
-D RADIO_CLASS=CustomLR1121
17+
-D WRAPPER_CLASS=CustomLR1121Wrapper
18+
-D LORA_TX_POWER=22
19+
-D MAX_LORA_TX_POWER=22
20+
-D RX_BOOSTED_GAIN=true
21+
-D RF_SWITCH_TABLE
22+
-D P_LORA_DIO_1=40
23+
-D P_LORA_RESET=42
24+
-D P_LORA_BUSY=43
25+
-D P_LORA_NSS=44
26+
-D P_LORA_SCLK=45
27+
-D P_LORA_MOSI=46
28+
-D P_LORA_MISO=47
29+
-D LR11X0_DIO_AS_RF_SWITCH=true
30+
-D LR11X0_DIO3_TCXO_VOLTAGE=3.0
31+
build_src_filter = ${nrf52_base.build_src_filter}
32+
+<helpers/*.cpp>
33+
+<helpers/sensors>
34+
+<../variants/muziworks_duo>
35+
debug_tool = jlink
36+
upload_protocol = nrfutil
37+
lib_deps = ${nrf52_base.lib_deps}
38+
${sensor_base.lib_deps}
39+
40+
[env:muziworks_duo_repeater]
41+
extends = muziworks_duo
42+
build_flags =
43+
${muziworks_duo.build_flags}
44+
-D ADVERT_NAME='"MuziDuo Repeater"'
45+
-D ADVERT_LAT=0.0
46+
-D ADVERT_LON=0.0
47+
-D ADMIN_PASSWORD='"password"'
48+
-D MAX_NEIGHBOURS=50
49+
build_src_filter = ${muziworks_duo.build_src_filter}
50+
+<../examples/simple_repeater/*.cpp>
51+
52+
[env:muziworks_duo_room_server]
53+
extends = muziworks_duo
54+
build_flags =
55+
${muziworks_duo.build_flags}
56+
-D ADVERT_NAME='"MuziDuo Room"'
57+
-D ADVERT_LAT=0.0
58+
-D ADVERT_LON=0.0
59+
-D ADMIN_PASSWORD='"password"'
60+
-D ROOM_PASSWORD='"hello"'
61+
build_src_filter = ${muziworks_duo.build_src_filter}
62+
+<../examples/simple_room_server/*.cpp>
63+
64+
[env:muziworks_duo_companion_radio_usb]
65+
extends = muziworks_duo
66+
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
67+
board_upload.maximum_size = 708608
68+
build_flags =
69+
${muziworks_duo.build_flags}
70+
-D MAX_CONTACTS=350
71+
-D MAX_GROUP_CHANNELS=40
72+
-D OFFLINE_QUEUE_SIZE=256
73+
build_src_filter = ${muziworks_duo.build_src_filter}
74+
+<helpers/nrf52/*.cpp>
75+
+<../examples/companion_radio/*.cpp>
76+
lib_deps =
77+
${muziworks_duo.lib_deps}
78+
densaugeo/base64 @ ~1.4.0
79+
80+
[env:muziworks_duo_terminal_chat]
81+
extends = muziworks_duo
82+
build_flags =
83+
${muziworks_duo.build_flags}
84+
-D ADVERT_NAME='"MuziDuo Chat"'
85+
-D ADVERT_LAT=0.0
86+
-D ADVERT_LON=0.0
87+
-D ADMIN_PASSWORD='"password"'
88+
-D ROOM_PASSWORD='"hello"'
89+
-D MAX_CONTACTS=100
90+
-D MAX_GROUP_CHANNELS=8
91+
build_src_filter = ${muziworks_duo.build_src_filter}
92+
+<../examples/simple_secure_chat/main.cpp>
93+
lib_deps =
94+
${muziworks_duo.lib_deps}
95+
densaugeo/base64 @ ~1.4.0
96+
97+
[env:muziworks_duo_companion_radio_ble]
98+
extends = muziworks_duo
99+
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
100+
board_upload.maximum_size = 708608
101+
build_flags =
102+
${muziworks_duo.build_flags}
103+
-D MAX_CONTACTS=350
104+
-D MAX_GROUP_CHANNELS=40
105+
-D BLE_PIN_CODE=123456
106+
-D QSPIFLASH=1
107+
-D OFFLINE_QUEUE_SIZE=256
108+
build_src_filter = ${muziworks_duo.build_src_filter}
109+
+<helpers/nrf52/SerialBLEInterface.cpp>
110+
+<../examples/companion_radio/*.cpp>
111+
lib_deps =
112+
${muziworks_duo.lib_deps}
113+
densaugeo/base64 @ ~1.4.0

0 commit comments

Comments
 (0)