Browse Source

Add initial MuziWorks Base Duo board support (nRF52840 + LR1121)

pull/2198/head
Vladimir Zaytsev 4 months ago
parent
commit
409a74933b
  1. 59
      boards/muziworks-duo.json
  2. 35
      src/helpers/radiolib/CustomLR1121.h
  3. 34
      src/helpers/radiolib/CustomLR1121Wrapper.h
  4. 28
      variants/muziworks_duo/MuziWorksDuoBoard.cpp
  5. 42
      variants/muziworks_duo/MuziWorksDuoBoard.h
  6. 113
      variants/muziworks_duo/platformio.ini
  7. 89
      variants/muziworks_duo/target.cpp
  8. 20
      variants/muziworks_duo/target.h
  9. 73
      variants/muziworks_duo/variant.cpp
  10. 123
      variants/muziworks_duo/variant.h

59
boards/muziworks-duo.json

@ -0,0 +1,59 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_MUZIWORKS_DUO -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"]
],
"usb_product": "MuziWorks-Duo-BOOT",
"mcu": "nrf52840",
"variant": "muziworks_duo",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52.cfg"
},
"frameworks": ["arduino"],
"name": "MuziWorks Base Duo",
"upload": {
"maximum_ram_size": 235520,
"maximum_size": 811008,
"speed": 115200,
"protocol": "nrfutil",
"protocols": [
"jlink",
"nrfjprog",
"nrfutil",
"stlink",
"cmsis-dap",
"blackmagic"
],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://www.muziworks.com",
"vendor": "MuziWorks"
}

35
src/helpers/radiolib/CustomLR1121.h

@ -0,0 +1,35 @@
#pragma once
#include <RadioLib.h>
#include "MeshCore.h"
class CustomLR1121 : public LR1121 {
bool _rx_boosted = false;
public:
CustomLR1121(Module *mod) : LR1121(mod) { }
size_t getPacketLength(bool update) override {
size_t len = LR1121::getPacketLength(update);
if (len == 0 && getIrqStatus() & RADIOLIB_LR11X0_IRQ_HEADER_ERR) {
MESH_DEBUG_PRINTLN("LR1121: got header err, calling standby()");
standby();
}
return len;
}
float getFreqMHz() const { return freqMHz; }
int16_t setRxBoostedGainMode(bool en) {
_rx_boosted = en;
return LR1121::setRxBoostedGainMode(en);
}
bool getRxBoostedGainMode() const { return _rx_boosted; }
bool isReceiving() {
uint16_t irq = getIrqStatus();
bool detected = ((irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || (irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED));
return detected;
}
};

34
src/helpers/radiolib/CustomLR1121Wrapper.h

@ -0,0 +1,34 @@
#pragma once
#include "CustomLR1121.h"
#include "RadioLibWrappers.h"
#include "LR11x0Reset.h"
class CustomLR1121Wrapper : public RadioLibWrapper {
public:
CustomLR1121Wrapper(CustomLR1121& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
void doResetAGC() override { lr11x0ResetAGC((LR11x0 *)_radio, ((CustomLR1121 *)_radio)->getFreqMHz()); }
bool isReceivingPacket() override {
return ((CustomLR1121 *)_radio)->isReceiving();
}
float getCurrentRSSI() override {
float rssi = -110;
((CustomLR1121 *)_radio)->getRssiInst(&rssi);
return rssi;
}
void onSendFinished() override {
RadioLibWrapper::onSendFinished();
_radio->setPreambleLength(16); // overcomes weird issues with small and big pkts
}
float getLastRSSI() const override { return ((CustomLR1121 *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomLR1121 *)_radio)->getSNR(); }
void setRxBoostedGainMode(bool en) override {
((CustomLR1121 *)_radio)->setRxBoostedGainMode(en);
}
bool getRxBoostedGainMode() const override {
return ((CustomLR1121 *)_radio)->getRxBoostedGainMode();
}
};

28
variants/muziworks_duo/MuziWorksDuoBoard.cpp

@ -0,0 +1,28 @@
#ifdef MUZIWORKS_DUO
#include "MuziWorksDuoBoard.h"
#include <Arduino.h>
#include <Wire.h>
void MuziWorksDuoBoard::begin() {
NRF52BoardDCDC::begin();
pinMode(PIN_VBAT_READ, INPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
// LEDs off (active LOW)
digitalWrite(LED_GREEN, !LED_STATE_ON);
digitalWrite(LED_BLUE, LED_STATE_ON);
#if defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL)
Wire.setPins(PIN_WIRE_SDA, PIN_WIRE_SCL);
#endif
Wire.begin();
delay(10);
}
#endif

42
variants/muziworks_duo/MuziWorksDuoBoard.h

@ -0,0 +1,42 @@
#pragma once
#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>
#ifdef MUZIWORKS_DUO
#define PIN_VBAT_READ BATTERY_PIN
#define BATTERY_SAMPLES 8
class MuziWorksDuoBoard : public NRF52BoardDCDC {
public:
MuziWorksDuoBoard() : NRF52Board("MuziWorksDuo_OTA") {}
void begin();
uint16_t getBattMilliVolts() override {
analogReadResolution(12);
uint32_t raw = 0;
for (int i = 0; i < BATTERY_SAMPLES; i++) {
raw += analogRead(PIN_VBAT_READ);
}
raw = raw / BATTERY_SAMPLES;
return (ADC_MULTIPLIER * raw);
}
const char* getManufacturerName() const override {
return "MuziWorks Duo";
}
#if defined(LED_GREEN)
void onBeforeTransmit() override {
digitalWrite(LED_GREEN, LED_STATE_ON);
}
void onAfterTransmit() override {
digitalWrite(LED_GREEN, !LED_STATE_ON);
}
#endif
};
#endif

113
variants/muziworks_duo/platformio.ini

@ -0,0 +1,113 @@
; ----------------- MuziWorks Base Duo (nRF52840 + LR1121) ---------------------
[muziworks_duo]
extends = nrf52_base
board = muziworks-duo
board_build.ldscript = boards/nrf52840_s140_v6.ld
build_flags = ${nrf52_base.build_flags}
${sensor_base.build_flags}
-I src/helpers/nrf52
-I lib/nrf52/s140_nrf52_6.1.1_API/include
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
-I variants/muziworks_duo
-D NRF52_PLATFORM
-D MUZIWORKS_DUO
-D ENV_INCLUDE_GPS=0
-D CONFIG_NFCT_PINS_AS_GPIOS=1
-D RADIO_CLASS=CustomLR1121
-D WRAPPER_CLASS=CustomLR1121Wrapper
-D LORA_TX_POWER=22
-D MAX_LORA_TX_POWER=22
-D RX_BOOSTED_GAIN=true
-D RF_SWITCH_TABLE
-D P_LORA_DIO_1=40
-D P_LORA_RESET=42
-D P_LORA_BUSY=43
-D P_LORA_NSS=44
-D P_LORA_SCLK=45
-D P_LORA_MOSI=46
-D P_LORA_MISO=47
-D LR11X0_DIO_AS_RF_SWITCH=true
-D LR11X0_DIO3_TCXO_VOLTAGE=3.0
build_src_filter = ${nrf52_base.build_src_filter}
+<helpers/*.cpp>
+<helpers/sensors>
+<../variants/muziworks_duo>
debug_tool = jlink
upload_protocol = nrfutil
lib_deps = ${nrf52_base.lib_deps}
${sensor_base.lib_deps}
[env:muziworks_duo_repeater]
extends = muziworks_duo
build_flags =
${muziworks_duo.build_flags}
-D ADVERT_NAME='"MuziDuo Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
build_src_filter = ${muziworks_duo.build_src_filter}
+<../examples/simple_repeater/*.cpp>
[env:muziworks_duo_room_server]
extends = muziworks_duo
build_flags =
${muziworks_duo.build_flags}
-D ADVERT_NAME='"MuziDuo Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
build_src_filter = ${muziworks_duo.build_src_filter}
+<../examples/simple_room_server/*.cpp>
[env:muziworks_duo_companion_radio_usb]
extends = muziworks_duo
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 708608
build_flags =
${muziworks_duo.build_flags}
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D OFFLINE_QUEUE_SIZE=256
build_src_filter = ${muziworks_duo.build_src_filter}
+<helpers/nrf52/*.cpp>
+<../examples/companion_radio/*.cpp>
lib_deps =
${muziworks_duo.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:muziworks_duo_terminal_chat]
extends = muziworks_duo
build_flags =
${muziworks_duo.build_flags}
-D ADVERT_NAME='"MuziDuo Chat"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
build_src_filter = ${muziworks_duo.build_src_filter}
+<../examples/simple_secure_chat/main.cpp>
lib_deps =
${muziworks_duo.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:muziworks_duo_companion_radio_ble]
extends = muziworks_duo
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 708608
build_flags =
${muziworks_duo.build_flags}
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D QSPIFLASH=1
-D OFFLINE_QUEUE_SIZE=256
build_src_filter = ${muziworks_duo.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio/*.cpp>
lib_deps =
${muziworks_duo.lib_deps}
densaugeo/base64 @ ~1.4.0

89
variants/muziworks_duo/target.cpp

@ -0,0 +1,89 @@
#include <Arduino.h>
#include "target.h"
#include <helpers/ArduinoHelpers.h>
MuziWorksDuoBoard board;
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
WRAPPER_CLASS radio_driver(radio, board);
VolatileRTCClock rtc_clock;
EnvironmentSensorManager sensors;
#ifndef LORA_CR
#define LORA_CR 5
#endif
#ifdef RF_SWITCH_TABLE
static const uint32_t rfswitch_dios[Module::RFSWITCH_MAX_PINS] = {
RADIOLIB_LR11X0_DIO5,
RADIOLIB_LR11X0_DIO6,
RADIOLIB_NC,
RADIOLIB_NC,
RADIOLIB_NC
};
static const Module::RfSwitchMode_t rfswitch_table[] = {
// mode DIO5 DIO6
{ LR11x0::MODE_STBY, {LOW, LOW }},
{ LR11x0::MODE_RX, {HIGH, LOW }},
{ LR11x0::MODE_TX, {LOW, HIGH}},
{ LR11x0::MODE_TX_HP, {LOW, HIGH}},
{ LR11x0::MODE_TX_HF, {LOW, LOW }},
{ LR11x0::MODE_GNSS, {LOW, LOW }},
{ LR11x0::MODE_WIFI, {LOW, LOW }},
END_OF_MODE_TABLE,
};
#endif
bool radio_init() {
#ifdef LR11X0_DIO3_TCXO_VOLTAGE
float tcxo = LR11X0_DIO3_TCXO_VOLTAGE;
#else
float tcxo = 3.0f;
#endif
SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI);
SPI.begin();
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
if (status != RADIOLIB_ERR_NONE) {
Serial.print("ERROR: radio init failed: ");
Serial.println(status);
return false;
}
radio.setCRC(2);
radio.explicitHeader();
#ifdef RF_SWITCH_TABLE
radio.setRfSwitchTable(rfswitch_dios, rfswitch_table);
#endif
#ifdef RX_BOOSTED_GAIN
radio.setRxBoostedGainMode(RX_BOOSTED_GAIN);
#endif
return true;
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(int8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng);
}

20
variants/muziworks_duo/target.h

@ -0,0 +1,20 @@
#pragma once
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include "MuziWorksDuoBoard.h"
#include <helpers/radiolib/CustomLR1121Wrapper.h>
#include <helpers/ArduinoHelpers.h>
#include <helpers/sensors/EnvironmentSensorManager.h>
extern MuziWorksDuoBoard board;
extern WRAPPER_CLASS radio_driver;
extern VolatileRTCClock rtc_clock;
extern EnvironmentSensorManager sensors;
bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();

73
variants/muziworks_duo/variant.cpp

@ -0,0 +1,73 @@
/*
* variant.cpp - MuziWorks Base Duo
* Pin mapping for nRF52840
*/
#include "variant.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
const uint32_t g_ADigitalPinMap[PINS_COUNT + 1] =
{
0, // P0.00
1, // P0.01
2, // P0.02
3, // P0.03
4, // P0.04
5, // P0.05
6, // P0.06
7, // P0.07
8, // P0.08
9, // P0.09
10, // P0.10
11, // P0.11
12, // P0.12
13, // P0.13
14, // P0.14
15, // P0.15
16, // P0.16
17, // P0.17
18, // P0.18
19, // P0.19
20, // P0.20
21, // P0.21
22, // P0.22
23, // P0.23
24, // P0.24, PIN_WIRE_SDA
25, // P0.25, PIN_WIRE_SCL
26, // P0.26
27, // P0.27
28, // P0.28
29, // P0.29
30, // P0.30
31, // P0.31, BATTERY_PIN (AIN7)
32, // P1.00
33, // P1.01
34, // P1.02
35, // P1.03, LED_GREEN
36, // P1.04, LED_BLUE
37, // P1.05
38, // P1.06
39, // P1.07
40, // P1.08, LORA_DIO_1 (LR1121 IRQ)
41, // P1.09
42, // P1.10, LORA_RESET (LR1121 NRESET)
43, // P1.11, LORA_BUSY (LR1121 BUSY)
44, // P1.12, PIN_SPI_NSS (LR1121 NSS)
45, // P1.13, PIN_SPI_SCK (LR1121 SCK)
46, // P1.14, PIN_SPI_MOSI (LR1121 MOSI)
47, // P1.15, PIN_SPI_MISO (LR1121 MISO)
255, // NRFX_SPIM_PIN_NOT_USED
};
void initVariant()
{
pinMode(BATTERY_PIN, INPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
// LEDs off (active LOW)
digitalWrite(LED_GREEN, !LED_STATE_ON);
digitalWrite(LED_BLUE, !LED_STATE_ON);
}

123
variants/muziworks_duo/variant.h

@ -0,0 +1,123 @@
/*
* variant.h - MuziWorks Base Duo
* nRF52840 + LR1121 (Sub-GHz LoRa)
* Elecrow nRFLR1121 module
*/
#pragma once
#include "WVariant.h"
////////////////////////////////////////////////////////////////////////////////
// Low frequency clock source
#define USE_LFXO // 32.768 kHz crystal oscillator
#define VARIANT_MCK (64000000ul)
////////////////////////////////////////////////////////////////////////////////
// Power
#define BATTERY_PIN (31) // P0.31 (AIN7)
#define BATTERY_IMMUTABLE
#define ADC_MULTIPLIER (1.537F)
#define ADC_RESOLUTION (12)
#define BATTERY_SENSE_RES (12)
////////////////////////////////////////////////////////////////////////////////
// Number of pins
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (8)
#define NUM_ANALOG_OUTPUTS (0)
////////////////////////////////////////////////////////////////////////////////
// UART pin definition
#define PIN_SERIAL1_RX (20) // P0.20 (GPS RX)
#define PIN_SERIAL1_TX (19) // P0.19 (GPS TX)
////////////////////////////////////////////////////////////////////////////////
// I2C pin definition
#define HAS_WIRE (1)
#define WIRE_INTERFACES_COUNT (1)
#define PIN_WIRE_SDA (24) // P0.24
#define PIN_WIRE_SCL (25) // P0.25
#define I2C_NO_RESCAN
////////////////////////////////////////////////////////////////////////////////
// SPI pin definition (internal to Elecrow nRFLR1121 module)
#define SPI_INTERFACES_COUNT (1)
#define PIN_SPI_MISO (47) // P1.15
#define PIN_SPI_MOSI (46) // P1.14
#define PIN_SPI_SCK (45) // P1.13
#define PIN_SPI_NSS (44) // P1.12
////////////////////////////////////////////////////////////////////////////////
// Builtin LEDs (active LOW)
#define LED_GREEN (35) // P1.03
#define LED_BLUE (36) // P1.04
#define LED_BUILTIN LED_GREEN
#define LED_PIN LED_GREEN
#define LED_STATE_ON LOW
////////////////////////////////////////////////////////////////////////////////
// Builtin buttons
#define PIN_BUTTON1 (-1)
#define BUTTON_PIN PIN_BUTTON1
////////////////////////////////////////////////////////////////////////////////
// LR1121 LoRa Radio (sub-GHz)
#define LORA_DIO_1 (40) // P1.08 - LR1121 IRQ (DIO1)
#define LORA_NSS (PIN_SPI_NSS) // P1.12
#define LORA_RESET (42) // P1.10 - LR1121 NRESET
#define LORA_BUSY (43) // P1.11 - LR1121 BUSY
#define LORA_SCLK (PIN_SPI_SCK) // P1.13
#define LORA_MISO (PIN_SPI_MISO) // P1.15
#define LORA_MOSI (PIN_SPI_MOSI) // P1.14
#define LORA_CS PIN_SPI_NSS // P1.12
#define LR11X0_DIO_AS_RF_SWITCH true
#define LR11X0_DIO3_TCXO_VOLTAGE 3.0
////////////////////////////////////////////////////////////////////////////////
// GPS/GNSS
#define HAS_GPS 0
#define PIN_GPS_TX (-1)
#define PIN_GPS_RX (-1)
#define GPS_EN (-1)
#define GPS_RESET (-1)
////////////////////////////////////////////////////////////////////////////////
// QSPI Flash (W25Q32JVSS - 8MB)
#define PIN_QSPI_SCK (3) // P0.03
#define PIN_QSPI_CS (26) // P0.26
#define PIN_QSPI_IO0 (30) // P0.30
#define PIN_QSPI_IO1 (29) // P0.29
#define PIN_QSPI_IO2 (28) // P0.28
#define PIN_QSPI_IO3 (2) // P0.02
#define EXTERNAL_FLASH_DEVICES W25Q64JV
#define EXTERNAL_FLASH_USE_QSPI
////////////////////////////////////////////////////////////////////////////////
// Additional peripheral pins (not enabled)
//
// I2C bus 1 (IMU): SDA P0.04, SCL P0.06
// Display (SH1107 OLED): I2C bus 0, power enable P0.23
// Trackball: UP P0.21, DOWN P0.17, LEFT P1.05, RIGHT P0.16, PRESS P0.10
// Buzzer: P0.22
// Buttons: Cancel P0.15, Mode1 P1.09, Mode2 P0.12
// GPS: RX P0.20, TX P0.19, EN P1.01
// Charge status: P1.02 (inverted)
Loading…
Cancel
Save