Explorar o código

Ikoka Nano Variant

Created as a fork of the ikoka stick variant.

- Updated for Ikoka Nano legacy pinout
- Removed display support
- Removed user button support
- Retains I2C sensor support

Tested with the ebytes E22 30W module, companion-ble and repeater firmware versions, with an I2C INA3221 power sensor.
Bill Plein hai 10 meses
pai
achega
b588e3f1e3

+ 94 - 0
variants/ikoka_nano_nrf/IkokaNanoNRFBoard.cpp

@@ -0,0 +1,94 @@
+#ifdef XIAO_NRF52
+
+#include <Arduino.h>
+#include "IkokaNanoNRFBoard.h"
+
+#include <bluefruit.h>
+#include <Wire.h>
+
+static BLEDfu bledfu;
+
+static void connect_callback(uint16_t conn_handle) {
+  (void)conn_handle;
+  MESH_DEBUG_PRINTLN("BLE client connected");
+}
+
+static void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
+  (void)conn_handle;
+  (void)reason;
+
+  MESH_DEBUG_PRINTLN("BLE client disconnected");
+}
+
+void IkokaNanoNRFBoard::begin() {
+  // for future use, sub-classes SHOULD call this from their begin()
+  startup_reason = BD_STARTUP_NORMAL;
+
+  pinMode(PIN_VBAT, INPUT);
+  pinMode(VBAT_ENABLE, OUTPUT);
+  digitalWrite(VBAT_ENABLE, HIGH);
+
+#ifdef PIN_USER_BTN
+  pinMode(PIN_USER_BTN, INPUT_PULLUP);
+#endif
+
+#if defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL)
+  Wire.setPins(PIN_WIRE_SDA, PIN_WIRE_SCL);
+#endif
+
+  Wire.begin();
+
+#ifdef P_LORA_TX_LED
+  pinMode(P_LORA_TX_LED, OUTPUT);
+  digitalWrite(P_LORA_TX_LED, HIGH);
+#endif
+
+//  pinMode(SX126X_POWER_EN, OUTPUT);
+//  digitalWrite(SX126X_POWER_EN, HIGH);
+  delay(10);   // give sx1262 some time to power up
+}
+
+bool IkokaNanoNRFBoard::startOTAUpdate(const char *id, char reply[]) {
+  // Config the peripheral connection with maximum bandwidth
+  // more SRAM required by SoftDevice
+  // Note: All config***() function must be called before begin()
+  Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
+  Bluefruit.configPrphConn(92, BLE_GAP_EVENT_LENGTH_MIN, 16, 16);
+
+  Bluefruit.begin(1, 0);
+  // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+  Bluefruit.setTxPower(4);
+  // Set the BLE device name
+  Bluefruit.setName("XIAO_NRF52_OTA");
+
+  Bluefruit.Periph.setConnectCallback(connect_callback);
+  Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
+
+  // To be consistent OTA DFU should be added first if it exists
+  bledfu.begin();
+
+  // Set up and start advertising
+  // Advertising packet
+  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+  Bluefruit.Advertising.addTxPower();
+  Bluefruit.Advertising.addName();
+
+  /* Start Advertising
+    - Enable auto advertising if disconnected
+    - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
+    - Timeout for fast mode is 30 seconds
+    - Start(timeout) with timeout = 0 will advertise forever (until connected)
+
+    For recommended advertising interval
+    https://developer.apple.com/library/content/qa/qa1931/_index.html
+  */
+  Bluefruit.Advertising.restartOnDisconnect(true);
+  Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+  Bluefruit.Advertising.setFastTimeout(30);   // number of seconds in fast mode
+  Bluefruit.Advertising.start(0);             // 0 = Don't stop advertising after n seconds
+
+  strcpy(reply, "OK - started");
+  return true;
+}
+
+#endif

+ 60 - 0
variants/ikoka_nano_nrf/IkokaNanoNRFBoard.h

@@ -0,0 +1,60 @@
+#pragma once
+
+#include <MeshCore.h>
+#include <Arduino.h>
+
+#ifdef XIAO_NRF52
+
+class IkokaNanoNRFBoard : public mesh::MainBoard {
+protected:
+  uint8_t startup_reason;
+
+public:
+  void begin();
+  uint8_t getStartupReason() const override { return startup_reason; }
+
+#if defined(P_LORA_TX_LED)
+  void onBeforeTransmit() override {
+    digitalWrite(P_LORA_TX_LED, LOW);   // turn TX LED on
+    #if defined(LED_BLUE)
+       // turn off that annoying blue LED before transmitting
+       digitalWrite(LED_BLUE, HIGH);
+    #endif
+  }
+  void onAfterTransmit() override {
+    digitalWrite(P_LORA_TX_LED, HIGH);   // turn TX LED off
+    #if defined(LED_BLUE)
+       // do it after transmitting too, just in case
+       digitalWrite(LED_BLUE, HIGH);
+    #endif
+  }
+#endif
+
+  uint16_t getBattMilliVolts() override {
+    // Please read befor going further ;)
+    // https://wiki.seeedstudio.com/XIAO_BLE#q3-what-are-the-considerations-when-using-xiao-nrf52840-sense-for-battery-charging
+
+    // We can't drive VBAT_ENABLE to HIGH as long 
+    // as we don't know wether we are charging or not ...
+    // this is a 3mA loss (4/1500)
+    digitalWrite(VBAT_ENABLE, LOW);
+    int adcvalue = 0;
+    analogReadResolution(12);
+    analogReference(AR_INTERNAL_3_0);  
+    delay(10);
+    adcvalue = analogRead(PIN_VBAT);
+    return (adcvalue * ADC_MULTIPLIER * AREF_VOLTAGE) / 4.096;
+  }
+
+  const char *getManufacturerName() const override {
+    return MANUFACTURER_STRING;
+  }
+
+  void reboot() override {
+    NVIC_SystemReset();
+  }
+
+  bool startOTAUpdate(const char *id, char reply[]) override;
+};
+
+#endif

+ 312 - 0
variants/ikoka_nano_nrf/platformio.ini

@@ -0,0 +1,312 @@
+[nrf52840_xiao]
+extends = nrf52_base
+platform_packages =
+  toolchain-gccarmnoneeabi@~1.100301.0
+  framework-arduinoadafruitnrf52
+board = seeed-xiao-afruitnrf52-nrf52840
+board_build.ldscript = boards/nrf52840_s140_v7.ld
+build_flags = ${nrf52_base.build_flags}
+  -D NRF52_PLATFORM -D XIAO_NRF52
+  -I lib/nrf52/s140_nrf52_7.3.0_API/include
+  -I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52
+lib_ignore =
+  BluetoothOTA
+  lvgl
+  lib5b4
+lib_deps =
+  ${nrf52_base.lib_deps}
+  rweather/Crypto @ ^0.4.0
+  adafruit/Adafruit INA3221 Library @ ^1.0.1
+  adafruit/Adafruit INA219 @ ^1.2.3
+  adafruit/Adafruit AHTX0 @ ^2.0.5
+  adafruit/Adafruit BME280 Library @ ^2.3.0
+  adafruit/Adafruit SSD1306 @ ^2.5.13
+
+[ikoka_nano_nrf_baseboard]
+extends = nrf52840_xiao
+;board_build.ldscript = boards/nrf52840_s140_v7.ld
+build_flags = ${nrf52840_xiao.build_flags}
+  -D P_LORA_TX_LED=11
+  -I variants/ikoka_nano_nrf
+  -I src/helpers/nrf52
+  -D DISPLAY_CLASS=NullDisplayDriver
+  -D RADIO_CLASS=CustomSX1262
+  -D WRAPPER_CLASS=CustomSX1262Wrapper
+  -D P_LORA_DIO_1=D1
+;  -D P_LORA_BUSY=D3
+  -D P_LORA_BUSY=D2 ; specific to ikoka nano variant.
+;  -D P_LORA_RESET=D2
+  -D P_LORA_RESET=D3 ; specific to ikoka nano variant.
+;  -D P_LORA_NSS=D4
+  -D P_LORA_NSS=D0 ; specific to ikoka nano variant.
+;  -D SX126X_RXEN=D5
+  -D SX126X_RXEN=D7
+  -D SX126X_TXEN=RADIOLIB_NC
+  -D SX126X_DIO2_AS_RF_SWITCH=1
+  -D SX126X_DIO3_TCXO_VOLTAGE=1.8
+  -D SX126X_CURRENT_LIMIT=140
+  -D SX126X_RX_BOOSTED_GAIN=1
+  -D PIN_WIRE_SCL=5 ; specific to ikoka nano variant.
+  -D PIN_WIRE_SDA=4 ; specific to ikoka nano variant.
+  -D ENV_INCLUDE_AHTX0=1
+  -D ENV_INCLUDE_BME280=1
+  -D ENV_INCLUDE_INA3221=1
+  -D ENV_INCLUDE_INA219=1
+debug_tool = jlink
+upload_protocol = nrfutil
+
+
+;;; abstracted hardware variants
+
+[ikoka_nano_nrf_e22_22dbm]
+extends = ikoka_nano_nrf_baseboard
+; No PA in this model, full 22dBm
+build_flags =
+  ${ikoka_nano_nrf_baseboard.build_flags}
+  -D MANUFACTURER_STRING='"Ikoka Nano-E22-22dBm (Xiao_nrf52)"'
+  -D LORA_TX_POWER=22
+build_src_filter = ${nrf52840_xiao.build_src_filter}
+  +<helpers/*.cpp>
+  +<helpers/sensors>
+  +<helpers/ui/NullDisplayDriver.cpp>
+  +<../variants/ikoka_nano_nrf>
+
+[ikoka_nano_nrf_e22_30dbm]
+extends = ikoka_nano_nrf_baseboard
+; limit txpower to 20dBm on E22-900M30S. Anything higher will
+; cause distortion in the PA output. 20dBm in -> 30dBm out
+build_flags =
+  ${ikoka_nano_nrf_baseboard.build_flags}
+  -D MANUFACTURER_STRING='"Ikoka Nano-E22-30dBm (Xiao_nrf52)"'
+  -D LORA_TX_POWER=20
+build_src_filter = ${nrf52840_xiao.build_src_filter}
+  +<helpers/*.cpp>
+  +<helpers/sensors>
+  +<helpers/ui/NullDisplayDriver.cpp>
+  +<../variants/ikoka_nano_nrf>
+
+[ikoka_nano_nrf_e22_33dbm]
+extends = ikoka_nano_nrf_baseboard
+; limit txpower to 9dBm on E22-900M33S to avoid hardware damage
+; to the rf amplifier frontend. 9dBm in -> 33dBm out
+build_flags =
+  ${ikoka_nano_nrf_baseboard.build_flags}
+  -D MANUFACTURER_STRING='"Ikoka Nano-E22-33dBm (Xiao_nrf52)"'
+  -D LORA_TX_POWER=9
+build_src_filter = ${nrf52840_xiao.build_src_filter}
+  +<helpers/*.cpp>
+  +<helpers/sensors>
+  +<helpers/ui/NullDisplayDriver.cpp>
+  +<../variants/ikoka_nano_nrf>
+
+;;; abstracted firmware roles
+
+[ikoka_nano_nrf_companion_radio_ble]
+extends = ikoka_nano_nrf_baseboard
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
+build_flags =
+  ${ikoka_nano_nrf_baseboard.build_flags}
+  -D MAX_CONTACTS=350
+  -D MAX_GROUP_CHANNELS=40
+  -D BLE_PIN_CODE=123456
+  -D OFFLINE_QUEUE_SIZE=256
+  -I examples/companion_radio/ui-new
+;  -D BLE_DEBUG_LOGGING=1
+;  -D MESH_PACKET_LOGGING=1
+;  -D MESH_DEBUG=1
+build_src_filter = ${ikoka_nano_nrf_baseboard.build_src_filter}
+  +<helpers/nrf52/SerialBLEInterface.cpp>
+  +<../examples/companion_radio/*.cpp>
+  +<../examples/companion_radio/ui-new/*.cpp>
+lib_deps =
+  ${ikoka_nano_nrf_baseboard.lib_deps}
+  densaugeo/base64 @ ~1.4.0
+
+[ikoka_nano_nrf_companion_radio_usb]
+extends = ikoka_nano_nrf_baseboard
+board_build.ldscript = boards/nrf52840_s140_v7_extrafs.ld
+board_upload.maximum_size = 708608
+build_flags =
+  ${ikoka_nano_nrf_baseboard.build_flags}
+  -D MAX_CONTACTS=350
+  -D MAX_GROUP_CHANNELS=40
+  -I examples/companion_radio/ui-new
+;  -D MESH_PACKET_LOGGING=1
+;  -D MESH_DEBUG=1
+build_src_filter = ${ikoka_nano_nrf_baseboard.build_src_filter}
+  +<helpers/nrf52/SerialBLEInterface.cpp>
+  +<../examples/companion_radio/*.cpp>
+  +<../examples/companion_radio/ui-new/*.cpp>
+lib_deps =
+  ${ikoka_nano_nrf_baseboard.lib_deps}
+  densaugeo/base64 @ ~1.4.0
+
+[ikoka_nano_nrf_repeater]
+extends = ikoka_nano_nrf_baseboard
+build_flags =
+  ${ikoka_nano_nrf_baseboard.build_flags}
+  -D ADVERT_NAME='"Ikoka Nano Repeater"'
+  -D ADVERT_LAT=0.0
+  -D ADVERT_LON=0.0
+  -D ADMIN_PASSWORD='"password"'
+  -D MAX_NEIGHBOURS=50
+;  -D MESH_PACKET_LOGGING=1
+;  -D MESH_DEBUG=1
+build_src_filter = ${ikoka_nano_nrf_baseboard.build_src_filter}
+  +<../examples/simple_repeater/*.cpp>
+
+[ikoka_nano_nrf_room_server]
+extends = ikoka_nano_nrf_baseboard
+build_flags =
+  ${ikoka_nano_nrf_baseboard.build_flags}
+  -D ADVERT_NAME='"Ikoka Nano Room"'
+  -D ADVERT_LAT=0.0
+  -D ADVERT_LON=0.0
+  -D ADMIN_PASSWORD='"password"'
+;  -D MESH_PACKET_LOGGING=1
+;  -D MESH_DEBUG=1
+build_src_filter = ${ikoka_nano_nrf_baseboard.build_src_filter}
+  +<../examples/simple_room_server/*.cpp>
+
+;;; hardware + firmware variants
+
+;;;    22dBm EBYTE E22-900M22 variants
+
+[env:ikoka_nano_nrf_22dbm_companion_radio_usb]
+extends =
+   ikoka_nano_nrf_e22_22dbm
+   ikoka_nano_nrf_companion_radio_usb
+build_flags =
+   ${ikoka_nano_nrf_companion_radio_usb.build_flags}
+   ${ikoka_nano_nrf_e22_22dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_companion_radio_usb.build_src_filter}
+   ${ikoka_nano_nrf_e22_22dbm.build_src_filter}
+
+[env:ikoka_nano_nrf_22dbm_companion_radio_ble]
+extends =
+   ikoka_nano_nrf_e22_22dbm
+   ikoka_nano_nrf_companion_radio_ble
+build_flags =
+   ${ikoka_nano_nrf_companion_radio_ble.build_flags}
+   ${ikoka_nano_nrf_e22_22dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_companion_radio_ble.build_src_filter}
+   ${ikoka_nano_nrf_e22_22dbm.build_src_filter}
+
+[env:ikoka_nano_nrf_22dbm_repeater]
+extends =
+   ikoka_nano_nrf_e22_22dbm
+   ikoka_nano_nrf_repeater
+build_flags =
+   ${ikoka_nano_nrf_repeater.build_flags}
+   ${ikoka_nano_nrf_e22_22dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_repeater.build_src_filter}
+   ${ikoka_nano_nrf_e22_22dbm.build_src_filter}
+
+[env:ikoka_nano_nrf_22dbm_room_server]
+extends =
+   ikoka_nano_nrf_e22_22dbm
+   ikoka_nano_nrf_room_server
+build_flags =
+   ${ikoka_nano_nrf_room_server.build_flags}
+   ${ikoka_nano_nrf_e22_22dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_room_server.build_src_filter}
+   ${ikoka_nano_nrf_e22_22dbm.build_src_filter}
+
+
+;;;    30dBm EBYTE E22-900M30 variants
+
+[env:ikoka_nano_nrf_30dbm_companion_radio_usb]
+extends =
+   ikoka_nano_nrf_e22_30dbm
+   ikoka_nano_nrf_companion_radio_usb
+build_flags =
+   ${ikoka_nano_nrf_companion_radio_usb.build_flags}
+   ${ikoka_nano_nrf_e22_30dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_companion_radio_usb.build_src_filter}
+   ${ikoka_nano_nrf_e22_30dbm.build_src_filter}
+
+[env:ikoka_nano_nrf_30dbm_companion_radio_ble]
+extends =
+   ikoka_nano_nrf_e22_30dbm
+   ikoka_nano_nrf_companion_radio_ble
+build_flags =
+   ${ikoka_nano_nrf_companion_radio_ble.build_flags}
+   ${ikoka_nano_nrf_e22_30dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_companion_radio_ble.build_src_filter}
+   ${ikoka_nano_nrf_e22_30dbm.build_src_filter}
+
+[env:ikoka_nano_nrf_30dbm_repeater]
+extends =
+   ikoka_nano_nrf_e22_30dbm
+   ikoka_nano_nrf_repeater
+build_flags =
+   ${ikoka_nano_nrf_repeater.build_flags}
+   ${ikoka_nano_nrf_e22_30dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_repeater.build_src_filter}
+   ${ikoka_nano_nrf_e22_30dbm.build_src_filter}
+
+[env:ikoka_nano_nrf_30dbm_room_server]
+extends =
+   ikoka_nano_nrf_e22_30dbm
+   ikoka_nano_nrf_room_server
+build_flags =
+   ${ikoka_nano_nrf_room_server.build_flags}
+   ${ikoka_nano_nrf_e22_30dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_room_server.build_src_filter}
+   ${ikoka_nano_nrf_e22_30dbm.build_src_filter}
+
+
+;;;    33dBm EBYTE E22-900M33 variants
+
+[env:ikoka_nano_nrf_33dbm_companion_radio_usb]
+extends =
+   ikoka_nano_nrf_e22_33dbm
+   ikoka_nano_nrf_companion_radio_usb
+build_flags =
+   ${ikoka_nano_nrf_companion_radio_usb.build_flags}
+   ${ikoka_nano_nrf_e22_33dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_companion_radio_usb.build_src_filter}
+   ${ikoka_nano_nrf_e22_33dbm.build_src_filter}
+
+[env:ikoka_nano_nrf_33dbm_companion_radio_ble]
+extends =
+   ikoka_nano_nrf_e22_33dbm
+   ikoka_nano_nrf_companion_radio_ble
+build_flags =
+   ${ikoka_nano_nrf_companion_radio_ble.build_flags}
+   ${ikoka_nano_nrf_e22_33dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_companion_radio_ble.build_src_filter}
+   ${ikoka_nano_nrf_e22_33dbm.build_src_filter}
+
+[env:ikoka_nano_nrf_33dbm_repeater]
+extends =
+   ikoka_nano_nrf_e22_33dbm
+   ikoka_nano_nrf_repeater
+build_flags =
+   ${ikoka_nano_nrf_repeater.build_flags}
+   ${ikoka_nano_nrf_e22_33dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_repeater.build_src_filter}
+   ${ikoka_nano_nrf_e22_33dbm.build_src_filter}
+
+[env:ikoka_nano_nrf_33dbm_room_server]
+extends =
+   ikoka_nano_nrf_e22_33dbm
+   ikoka_nano_nrf_room_server
+build_flags =
+   ${ikoka_nano_nrf_room_server.build_flags}
+   ${ikoka_nano_nrf_e22_33dbm.build_flags}
+build_src_filter =
+   ${ikoka_nano_nrf_room_server.build_src_filter}
+   ${ikoka_nano_nrf_e22_33dbm.build_src_filter}

+ 44 - 0
variants/ikoka_nano_nrf/target.cpp

@@ -0,0 +1,44 @@
+#include <Arduino.h>
+#include "target.h"
+#include <helpers/ArduinoHelpers.h>
+
+IkokaNanoNRFBoard board;
+
+#ifdef DISPLAY_CLASS
+  DISPLAY_CLASS display;
+  // MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
+#endif
+
+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 fallback_clock;
+AutoDiscoverRTCClock rtc_clock(fallback_clock);
+EnvironmentSensorManager sensors;
+
+bool radio_init() {
+    rtc_clock.begin(Wire);
+  
+    return radio.std_init(&SPI);
+}
+
+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(uint8_t dbm) {
+  radio.setOutputPower(dbm);
+}
+
+mesh::LocalIdentity radio_new_identity() {
+  RadioNoiseListener rng(radio);
+  return mesh::LocalIdentity(&rng);  // create new random identity
+}

+ 28 - 0
variants/ikoka_nano_nrf/target.h

@@ -0,0 +1,28 @@
+#pragma once
+
+#define RADIOLIB_STATIC_ONLY 1
+#include <RadioLib.h>
+#include <helpers/radiolib/RadioLibWrappers.h>
+#include <IkokaNanoNRFBoard.h>
+#include <helpers/radiolib/CustomSX1262Wrapper.h>
+#include <helpers/AutoDiscoverRTCClock.h>
+#include <helpers/ArduinoHelpers.h>
+#include <helpers/sensors/EnvironmentSensorManager.h>
+
+#ifdef DISPLAY_CLASS
+  #include <helpers/ui/NullDisplayDriver.h>
+  #include <helpers/ui/MomentaryButton.h>
+  extern DISPLAY_CLASS display;
+  // extern MomentaryButton user_btn;
+#endif
+
+extern IkokaNanoNRFBoard board;
+extern WRAPPER_CLASS radio_driver;
+extern AutoDiscoverRTCClock 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(uint8_t dbm);
+mesh::LocalIdentity radio_new_identity();

+ 86 - 0
variants/ikoka_nano_nrf/variant.cpp

@@ -0,0 +1,86 @@
+#include "variant.h"
+#include "wiring_constants.h"
+#include "wiring_digital.h"
+#include "nrf.h"
+
+const uint32_t g_ADigitalPinMap[] =
+{
+    // D0 .. D10
+     2, // D0  is P0.02 (A0)
+     3, // D1  is P0.03 (A1)
+    28, // D2  is P0.28 (A2)
+    29, // D3  is P0.29 (A3)
+     4, // D4  is P0.04 (A4,SDA)
+     5, // D5  is P0.05 (A5,SCL)
+    43, // D6  is P1.11 (TX)
+    44, // D7  is P1.12 (RX)
+    45, // D8  is P1.13 (SCK)
+    46, // D9  is P1.14 (MISO)
+    47, // D10 is P1.15 (MOSI)
+
+    // LEDs
+    26, // D11 is P0.26 (LED RED)
+     6, // D12 is P0.06 (LED BLUE)
+    30, // D13 is P0.30 (LED GREEN)
+    14, // D14 is P0.14 (READ_BAT)
+
+    // LSM6DS3TR
+    40, // D15 is P1.08 (6D_PWR)
+    27, // D16 is P0.27 (6D_I2C_SCL)
+     7, // D17 is P0.07 (6D_I2C_SDA)
+    11, // D18 is P0.11 (6D_INT1)
+
+    // MIC
+    42, // D19 is P1.10 (MIC_PWR)
+    32, // D20 is P1.00 (PDM_CLK)
+    16, // D21 is P0.16 (PDM_DATA)
+
+    // BQ25100
+    13, // D22 is P0.13 (HICHG)
+    17, // D23 is P0.17 (~CHG)
+
+    //
+    21, // D24 is P0.21 (QSPI_SCK)
+    25, // D25 is P0.25 (QSPI_CSN)
+    20, // D26 is P0.20 (QSPI_SIO_0 DI)
+    24, // D27 is P0.24 (QSPI_SIO_1 DO)
+    22, // D28 is P0.22 (QSPI_SIO_2 WP)
+    23, // D29 is P0.23 (QSPI_SIO_3 HOLD)
+
+    // NFC
+     9, // D30 is P0.09 (NFC1)
+    10, // D31 is P0.10 (NFC2)
+
+    // VBAT
+    31, // D32 is P0.31 (VBAT)
+};
+
+void initVariant()
+{
+    // Disable reading of the BAT voltage.
+    // https://wiki.seeedstudio.com/XIAO_BLE#q3-what-are-the-considerations-when-using-xiao-nrf52840-sense-for-battery-charging
+    pinMode(VBAT_ENABLE, OUTPUT);
+    //digitalWrite(VBAT_ENABLE, HIGH); 
+    // This was taken from Seeed github butis not coherent with the doc, 
+    // VBAT_ENABLE should be kept to LOW to protect P0.14, (1500/500)*(4.2-3.3)+3.3 = 3.9V > 3.6V
+    // This induces a 3mA current in the resistors :( but it's better than burning the nrf
+    digitalWrite(VBAT_ENABLE, LOW);
+
+    // Low charging current (50mA)
+    // https://wiki.seeedstudio.com/XIAO_BLE#battery-charging-current
+    //pinMode(PIN_CHARGING_CURRENT, INPUT);
+
+    // High charging current (100mA)
+    pinMode(PIN_CHARGING_CURRENT, OUTPUT);
+    digitalWrite(PIN_CHARGING_CURRENT, LOW);
+
+    pinMode(PIN_QSPI_CS, OUTPUT);
+    digitalWrite(PIN_QSPI_CS, HIGH);
+
+    pinMode(LED_RED, OUTPUT);
+    digitalWrite(LED_RED, HIGH);
+    pinMode(LED_GREEN, OUTPUT);
+    digitalWrite(LED_GREEN, HIGH);
+    pinMode(LED_BLUE, OUTPUT);
+    digitalWrite(LED_BLUE, HIGH);
+}

+ 149 - 0
variants/ikoka_nano_nrf/variant.h

@@ -0,0 +1,149 @@
+#ifndef _IKOKA_NANO_NRF_H_
+#define _IKOKA_NANO_NRF_H_
+
+/** Master clock frequency */
+#define VARIANT_MCK       (64000000ul)
+
+#define USE_LFXO      // Board uses 32khz crystal for LF
+//#define USE_LFRC    // Board uses RC for LF
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+#define PINS_COUNT              (33)
+#define NUM_DIGITAL_PINS        (33)
+#define NUM_ANALOG_INPUTS       (8)
+#define NUM_ANALOG_OUTPUTS      (0)
+
+// LEDs
+#define PIN_LED                 (LED_RED)
+#define LED_PWR                 (PINS_COUNT)
+#define PIN_NEOPIXEL            (PINS_COUNT)
+#define NEOPIXEL_NUM            (0)
+
+#define LED_BUILTIN             (PIN_LED)
+
+#define LED_RED                 (11)
+#define LED_GREEN               (13)
+#define LED_BLUE                (12)
+
+#define LED_STATE_ON            (0)     // State when LED is litted
+
+// Buttons
+// #define PIN_BUTTON1             (PINS_COUNT)
+
+// Digital PINs
+static const uint8_t D0  = 0 ;
+static const uint8_t D1  = 1 ;
+static const uint8_t D2  = 2 ;
+static const uint8_t D3  = 3 ;
+static const uint8_t D4  = 4 ;
+static const uint8_t D5  = 5 ;
+static const uint8_t D6  = 6 ;
+static const uint8_t D7  = 7 ;
+static const uint8_t D8  = 8 ;
+static const uint8_t D9  = 9 ;
+static const uint8_t D10 = 10;
+
+#define VBAT_ENABLE             (14)    // Output LOW to enable reading of the BAT voltage.
+                                        // https://wiki.seeedstudio.com/XIAO_BLE#q3-what-are-the-considerations-when-using-xiao-nrf52840-sense-for-battery-charging
+
+#define PIN_CHARGING_CURRENT    (22)    // Battery Charging current
+                                        // https://wiki.seeedstudio.com/XIAO_BLE#battery-charging-current
+
+// Analog pins
+#define PIN_A0                  (0)
+#define PIN_A1                  (1)
+#define PIN_A2                  (2)
+#define PIN_A3                  (3)
+#define PIN_A4                  (4)
+#define PIN_A5                  (5)
+#define PIN_VBAT                (32)    // Read the BAT voltage.
+                                        // https://wiki.seeedstudio.com/XIAO_BLE#q3-what-are-the-considerations-when-using-xiao-nrf52840-sense-for-battery-charging
+
+#define BAT_NOT_CHARGING        (23)    // LOW when charging
+
+#define AREF_VOLTAGE            (3.0)
+#define ADC_MULTIPLIER          (3.0F) // 1M, 512k divider bridge
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+
+#define ADC_RESOLUTION          (12)
+
+// Other pins
+#define PIN_NFC1                (30)
+#define PIN_NFC2                (31)
+
+// Serial interfaces
+#define PIN_SERIAL1_RX          (7)
+#define PIN_SERIAL1_TX          (6)
+
+// SPI Interfaces
+#define SPI_INTERFACES_COUNT    (2)
+
+#define PIN_SPI_MISO            (9)
+#define PIN_SPI_MOSI            (10)
+#define PIN_SPI_SCK             (8)
+
+#define PIN_SPI1_MISO           (25)
+#define PIN_SPI1_MOSI           (26)
+#define PIN_SPI1_SCK            (29)
+
+// Lora SPI is on SPI0
+#define  P_LORA_SCLK            PIN_SPI_SCK
+#define  P_LORA_MISO            PIN_SPI_MISO
+#define  P_LORA_MOSI            PIN_SPI_MOSI
+
+// Wire Interfaces
+#define WIRE_INTERFACES_COUNT   (1)
+
+// #define PIN_WIRE_SDA            (17) // 4 and 5 are used for the sx1262 !
+// #define PIN_WIRE_SCL            (16) // use WIRE1_SDA
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+//#define PIN_WIRE1_SDA           (17)
+//#define PIN_WIRE1_SCL           (16)
+#define PIN_LSM6DS3TR_C_POWER   (15)
+#define PIN_LSM6DS3TR_C_INT1    (18)
+
+// PDM Interfaces
+#define PIN_PDM_PWR	            (19)
+#define PIN_PDM_CLK	            (20)
+#define PIN_PDM_DIN	            (21)
+
+// QSPI Pins
+#define PIN_QSPI_SCK            (24)
+#define PIN_QSPI_CS             (25)
+#define PIN_QSPI_IO0            (26)
+#define PIN_QSPI_IO1            (27)
+#define PIN_QSPI_IO2            (28)
+#define PIN_QSPI_IO3            (29)
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES  (P25Q16H)
+#define EXTERNAL_FLASH_USE_QSPI
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#endif