diff --git a/boards/seeed-wio-tracker-l1.json b/boards/seeed-wio-tracker-l1.json new file mode 100644 index 00000000..3602baab --- /dev/null +++ b/boards/seeed-wio-tracker-l1.json @@ -0,0 +1,61 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v7.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DARDUINO_SEEED_WIO_TRACKER_L1 -DNRF52840_XXAA -DSEEED_WIO_TRACKER_L1 ", + "f_cpu": "64000000L", + "hwids": [ + [ "0x2886", "0x1667" ], + [ "0x2886", "0x1668" ] + ], + "mcu": "nrf52840", + "variant": "Seeed_Wio_Tracker_L1", + "softdevice": { + "sd_flags": "-DS140", + "sd_name": "s140", + "sd_version": "7.3.0", + "sd_fwid": "0x0123" + }, + "bsp": { + "name": "adafruit" + }, + "bootloader": { + "settings_addr": "0xFF000" + }, + "usb_product": "Seeed Wio Tracker L1" + }, + "connectivity": [ + "bluetooth" + ], + "debug": { + "jlink_device": "nRF52840_xxAA", + "openocd_target": "nrf52.cfg", + "svd_path": "nrf52840.svd" + }, + "frameworks": [ + "arduino" + ], + "name": "Seeed Wio Tracker L1", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "protocol": "nrfutil", + "speed": 115200, + "protocols": [ + "jlink", + "nrfjprog", + "nrfutil", + "cmsis-dap", + "sam-ba", + "blackmagic" + ], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + }, + "url": "https://wiki.seeedstudio.com/wio_tracker_l1_node/", + "vendor": "Seeed Studio" +} \ No newline at end of file diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 6ddc19d6..c230cb8a 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -45,6 +45,7 @@ #define CMD_GET_CUSTOM_VARS 40 #define CMD_SET_CUSTOM_VAR 41 #define CMD_GET_ADVERT_PATH 42 +#define CMD_GET_TUNING_PARAMS 43 #define RESP_CODE_OK 0 #define RESP_CODE_ERR 1 @@ -69,6 +70,7 @@ #define RESP_CODE_SIGNATURE 20 #define RESP_CODE_CUSTOM_VARS 21 #define RESP_CODE_ADVERT_PATH 22 +#define RESP_CODE_TUNING_PARAMS 23 #define SEND_TIMEOUT_BASE_MILLIS 500 #define FLOOD_SEND_TIMEOUT_FACTOR 16.0f @@ -1016,6 +1018,13 @@ void MyMesh::handleCmdFrame(size_t len) { _prefs.airtime_factor = ((float)af) / 1000.0f; savePrefs(); writeOKFrame(); + } else if (cmd_frame[0] == CMD_GET_TUNING_PARAMS) { + uint32_t rx = _prefs.rx_delay_base * 1000, af = _prefs.airtime_factor * 1000; + int i = 0; + out_frame[i++] = RESP_CODE_TUNING_PARAMS; + memcpy(&out_frame[i], &rx, 4); i += 4; + memcpy(&out_frame[i], &af, 4); i += 4; + _serial->writeFrame(out_frame, i); } else if (cmd_frame[0] == CMD_SET_OTHER_PARAMS) { _prefs.manual_add_contacts = cmd_frame[1]; if (len >= 3) { diff --git a/examples/simple_sensor/SensorMesh.cpp b/examples/simple_sensor/SensorMesh.cpp index 48fd10fa..61444b2f 100644 --- a/examples/simple_sensor/SensorMesh.cpp +++ b/examples/simple_sensor/SensorMesh.cpp @@ -332,13 +332,14 @@ void SensorMesh::applyContactPermissions(const uint8_t* pubkey, uint16_t perms) dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); // trigger saveContacts() } -void SensorMesh::sendAlert(const char* text) { +void SensorMesh::sendAlert(AlertPriority pri, const char* text) { int text_len = strlen(text); + uint16_t pri_mask = (pri == HIGH_PRI_ALERT) ? PERM_RECV_ALERTS_HI : PERM_RECV_ALERTS_LO; // send text message to all contacts with RECV_ALERT permission for (int i = 0; i < num_contacts; i++) { auto c = &contacts[i]; - if ((c->permissions & PERM_RECV_ALERTS) == 0) continue; // contact does NOT want alerts + if ((c->permissions & pri_mask) == 0) continue; // contact does NOT want alert uint8_t data[MAX_PACKET_PAYLOAD]; uint32_t now = getRTCClock()->getCurrentTimeUnique(); // need different timestamp per packet @@ -360,12 +361,12 @@ void SensorMesh::sendAlert(const char* text) { } } -void SensorMesh::alertIf(bool condition, Trigger& t, const char* text) { +void SensorMesh::alertIf(bool condition, Trigger& t, AlertPriority pri, const char* text) { if (condition) { if (!t.triggered) { t.triggered = true; t.time = getRTCClock()->getCurrentTime(); - sendAlert(text); + sendAlert(pri, text); } } else { if (t.triggered) { @@ -422,7 +423,7 @@ uint8_t SensorMesh::handleLoginReq(const mesh::Identity& sender, const uint8_t* MESH_DEBUG_PRINTLN("Login success!"); client->last_timestamp = sender_timestamp; client->last_activity = getRTCClock()->getCurrentTime(); - client->permissions = PERM_IS_ADMIN | PERM_RECV_ALERTS; + client->permissions = PERM_IS_ADMIN | PERM_RECV_ALERTS_HI | PERM_RECV_ALERTS_LO; // initially opt-in to receive alerts (can opt out) memcpy(client->shared_secret, secret, PUB_KEY_SIZE); dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); diff --git a/examples/simple_sensor/SensorMesh.h b/examples/simple_sensor/SensorMesh.h index 00234355..e92c163f 100644 --- a/examples/simple_sensor/SensorMesh.h +++ b/examples/simple_sensor/SensorMesh.h @@ -26,7 +26,8 @@ #define PERM_IS_ADMIN 0x8000 #define PERM_GET_TELEMETRY 0x0001 #define PERM_GET_MIN_MAX_AVG 0x0002 -#define PERM_RECV_ALERTS 0x0100 +#define PERM_RECV_ALERTS_LO 0x0100 // low priority alerts +#define PERM_RECV_ALERTS_HI 0x0200 // high priority alerts struct ContactInfo { mesh::Identity id; @@ -104,8 +105,8 @@ protected: Trigger() { triggered = false; time = 0; } }; - - void alertIf(bool condition, Trigger& t, const char* text); + enum AlertPriority { LOW_PRI_ALERT, HIGH_PRI_ALERT }; + void alertIf(bool condition, Trigger& t, AlertPriority pri, const char* text); virtual void onSensorDataRead() = 0; // for app to implement virtual int querySeriesData(uint32_t start_secs_ago, uint32_t end_secs_ago, MinMaxAvg dest[], int max_num) = 0; // for app to implement @@ -145,6 +146,6 @@ private: ContactInfo* putContact(const mesh::Identity& id); void applyContactPermissions(const uint8_t* pubkey, uint16_t perms); - void sendAlert(const char* text); + void sendAlert(AlertPriority pri, const char* text); }; diff --git a/examples/simple_sensor/main.cpp b/examples/simple_sensor/main.cpp index 16e14d5b..792790d8 100644 --- a/examples/simple_sensor/main.cpp +++ b/examples/simple_sensor/main.cpp @@ -22,7 +22,7 @@ protected: float batt_voltage = getVoltage(TELEM_CHANNEL_SELF); battery_data.recordData(getRTCClock(), batt_voltage); // record battery - alertIf(batt_voltage < 3.4f, low_batt, "Battery low!"); + alertIf(batt_voltage < 3.4f, low_batt, HIGH_PRI_ALERT, "Battery low!"); } int querySeriesData(uint32_t start_secs_ago, uint32_t end_secs_ago, MinMaxAvg dest[], int max_num) override { diff --git a/src/helpers/ui/buzzer.cpp b/src/helpers/ui/buzzer.cpp index c8e5cfcc..ca469d17 100644 --- a/src/helpers/ui/buzzer.cpp +++ b/src/helpers/ui/buzzer.cpp @@ -46,6 +46,13 @@ void genericBuzzer::shutdown() { void genericBuzzer::quiet(bool buzzer_state) { _is_quiet = buzzer_state; +#ifdef PIN_BUZZER_EN + if (_is_quiet) { + digitalWrite(PIN_BUZZER_EN, LOW); + } else { + digitalWrite(PIN_BUZZER_EN, HIGH); + } +#endif } bool genericBuzzer::isQuiet() { diff --git a/src/helpers/nrf52/MinewsemiME25LS01Board.cpp b/variants/minewsemi_me25ls01/MinewsemiME25LS01Board.cpp similarity index 100% rename from src/helpers/nrf52/MinewsemiME25LS01Board.cpp rename to variants/minewsemi_me25ls01/MinewsemiME25LS01Board.cpp diff --git a/src/helpers/nrf52/MinewsemiME25LS01Board.h b/variants/minewsemi_me25ls01/MinewsemiME25LS01Board.h similarity index 100% rename from src/helpers/nrf52/MinewsemiME25LS01Board.h rename to variants/minewsemi_me25ls01/MinewsemiME25LS01Board.h diff --git a/variants/minewsemi_me25ls01/platformio.ini b/variants/minewsemi_me25ls01/platformio.ini index 302e695f..f7265af4 100644 --- a/variants/minewsemi_me25ls01/platformio.ini +++ b/variants/minewsemi_me25ls01/platformio.ini @@ -34,7 +34,6 @@ build_flags = ${nrf52840_me25ls01.build_flags} -D ENV_INCLUDE_INA219=1 build_src_filter = ${nrf52840_me25ls01.build_src_filter} + - + +<../variants/minewsemi_me25ls01> + debug_tool = jlink diff --git a/variants/minewsemi_me25ls01/target.h b/variants/minewsemi_me25ls01/target.h index aad55757..db832f91 100644 --- a/variants/minewsemi_me25ls01/target.h +++ b/variants/minewsemi_me25ls01/target.h @@ -3,7 +3,7 @@ #define RADIOLIB_STATIC_ONLY 1 #include #include -#include +#include #include #include #include diff --git a/src/helpers/nrf52/PromicroBoard.cpp b/variants/promicro/PromicroBoard.cpp similarity index 100% rename from src/helpers/nrf52/PromicroBoard.cpp rename to variants/promicro/PromicroBoard.cpp diff --git a/src/helpers/nrf52/PromicroBoard.h b/variants/promicro/PromicroBoard.h similarity index 100% rename from src/helpers/nrf52/PromicroBoard.h rename to variants/promicro/PromicroBoard.h diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index 246019c2..4e5edc22 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -23,7 +23,6 @@ build_flags = ${nrf52_base.build_flags} -D ENV_INCLUDE_INA3221=1 -D ENV_INCLUDE_INA219=1 build_src_filter = ${nrf52_base.build_src_filter} - + + +<../variants/promicro> lib_deps= ${nrf52_base.lib_deps} @@ -130,7 +129,6 @@ build_flags = ${nrf52_base.build_flags} -D SX126X_RX_BOOSTED_GAIN=1 build_src_filter = ${nrf52_base.build_src_filter} - + + +<../variants/promicro> lib_deps= ${nrf52_base.lib_deps} diff --git a/variants/promicro/target.h b/variants/promicro/target.h index c634d18a..7646d459 100644 --- a/variants/promicro/target.h +++ b/variants/promicro/target.h @@ -3,7 +3,7 @@ #define RADIOLIB_STATIC_ONLY 1 #include #include -#include +#include #include #include #include diff --git a/src/helpers/nrf52/RAK4631Board.cpp b/variants/rak4631/RAK4631Board.cpp similarity index 100% rename from src/helpers/nrf52/RAK4631Board.cpp rename to variants/rak4631/RAK4631Board.cpp diff --git a/src/helpers/nrf52/RAK4631Board.h b/variants/rak4631/RAK4631Board.h similarity index 100% rename from src/helpers/nrf52/RAK4631Board.h rename to variants/rak4631/RAK4631Board.h diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index 86879ed7..5fcdb3d0 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -15,7 +15,6 @@ build_flags = ${nrf52840_base.build_flags} -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 build_src_filter = ${nrf52840_base.build_src_filter} - + +<../variants/rak4631> lib_deps = ${nrf52840_base.lib_deps} diff --git a/variants/rak4631/target.h b/variants/rak4631/target.h index 3f26ab33..e1545581 100644 --- a/variants/rak4631/target.h +++ b/variants/rak4631/target.h @@ -3,7 +3,7 @@ #define RADIOLIB_STATIC_ONLY 1 #include #include -#include +#include #include #include #include diff --git a/variants/wio-e5-mini/platformio.ini b/variants/wio-e5-mini/platformio.ini index dfe4a090..93508d8e 100644 --- a/variants/wio-e5-mini/platformio.ini +++ b/variants/wio-e5-mini/platformio.ini @@ -25,6 +25,15 @@ build_flags = ${lora_e5_mini.build_flags} build_src_filter = ${lora_e5_mini.build_src_filter} +<../examples/simple_repeater/main.cpp> +[env:wio-e5-mini-sensor] +extends = lora_e5_mini +build_flags = ${lora_e5_mini.build_flags} + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"wio-e5-mini Sensor"' + -D ADMIN_PASSWORD='"password"' +build_src_filter = ${lora_e5_mini.build_src_filter} + +<../examples/simple_sensor> + [env:wio-e5-mini_companion_radio_usb] extends = lora_e5_mini build_flags = ${lora_e5_mini.build_flags} diff --git a/variants/wio-tracker-l1/WioTrackerL1Board.cpp b/variants/wio-tracker-l1/WioTrackerL1Board.cpp new file mode 100644 index 00000000..c5c9db65 --- /dev/null +++ b/variants/wio-tracker-l1/WioTrackerL1Board.cpp @@ -0,0 +1,96 @@ +#include +#include "WioTrackerL1Board.h" + +#include +#include + +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 WioTrackerL1Board::begin() { + // for future use, sub-classes SHOULD call this from their begin() + startup_reason = BD_STARTUP_NORMAL; + btn_prev_state = HIGH; + + pinMode(PIN_VBAT_READ, INPUT); // VBAT ADC input + // Set all button pins to INPUT_PULLUP + pinMode(PIN_BUTTON1, INPUT_PULLUP); + pinMode(PIN_BUTTON2, INPUT_PULLUP); + pinMode(PIN_BUTTON3, INPUT_PULLUP); + pinMode(PIN_BUTTON4, INPUT_PULLUP); + pinMode(PIN_BUTTON5, INPUT_PULLUP); + pinMode(PIN_BUTTON6, INPUT_PULLUP); + + + #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, LOW); + #endif + + delay(10); // give sx1262 some time to power up +} + +bool WioTrackerL1Board::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("WioTrackerL1 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 + + uint8_t mac_addr[6]; + memset(mac_addr, 0, sizeof(mac_addr)); + Bluefruit.getAddr(mac_addr); + sprintf(reply, "OK - mac: %02X:%02X:%02X:%02X:%02X:%02X", + mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); + + return true; +} diff --git a/variants/wio-tracker-l1/WioTrackerL1Board.h b/variants/wio-tracker-l1/WioTrackerL1Board.h new file mode 100644 index 00000000..03aef79c --- /dev/null +++ b/variants/wio-tracker-l1/WioTrackerL1Board.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +class WioTrackerL1Board : public mesh::MainBoard { +protected: + uint8_t startup_reason; + uint8_t btn_prev_state; + +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, HIGH); // turn TX LED on + } + void onAfterTransmit() override { + digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off + } +#endif + + uint16_t getBattMilliVolts() override { + int adcvalue = 0; + analogReadResolution(12); + analogReference(AR_INTERNAL); + delay(10); + adcvalue = analogRead(PIN_VBAT_READ); + return (adcvalue * ADC_MULTIPLIER * AREF_VOLTAGE) / 4.096; + } + + const char* getManufacturerName() const override { + return "Seeed Wio Tracker L1"; + } + + void reboot() override { + NVIC_SystemReset(); + } + + bool startOTAUpdate(const char* id, char reply[]) override; +}; diff --git a/variants/wio-tracker-l1/platformio.ini b/variants/wio-tracker-l1/platformio.ini new file mode 100644 index 00000000..380ff90f --- /dev/null +++ b/variants/wio-tracker-l1/platformio.ini @@ -0,0 +1,92 @@ +[WioTrackerL1] +extends = nrf52_base +board = seeed-wio-tracker-l1 +board_build.ldscript = boards/nrf52840_s140_v7.ld +build_flags = ${nrf52_base.build_flags} + -I lib/nrf52/s140_nrf52_7.3.0_API/include + -I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52 + -I variants/wio-tracker-l1 + -D WIO_TRACKER_L1 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=140 + -D SX126X_RX_BOOSTED_GAIN=1 + -D PIN_OLED_RESET=-1 + ; -D MESH_DEBUG=1 +build_src_filter = ${nrf52_base.build_src_filter} + + + +<../variants/wio-tracker-l1> + + + + +lib_deps= ${nrf52_base.lib_deps} + adafruit/Adafruit SH110X @ ^2.1.13 + adafruit/Adafruit GFX Library @ ^1.12.1 + stevemarple/MicroNMEA @ ^2.0.6 + +[env:WioTrackerL1_Repeater] +extends = WioTrackerL1 +build_src_filter = ${WioTrackerL1.build_src_filter} + +<../examples/simple_repeater> +build_flags = + ${WioTrackerL1.build_flags} + -D ADVERT_NAME='"WioTrackerL1 Repeater"' + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D DISPLAY_CLASS=SH1106Display +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = ${WioTrackerL1.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:WioTrackerL1_room_server] +extends = WioTrackerL1 +build_src_filter = ${WioTrackerL1.build_src_filter} + +<../examples/simple_room_server> +build_flags = ${WioTrackerL1.build_flags} + -D ADVERT_NAME='"WioTrackerL1 Room"' + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' + -D DISPLAY_CLASS=SH1106Display +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = ${WioTrackerL1.lib_deps} + adafruit/RTClib @ ^2.1.3 + +[env:WioTrackerL1_companion_radio_usb] +extends = WioTrackerL1 +build_flags = ${WioTrackerL1.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D DISPLAY_CLASS=SH1106Display +; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 +; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 +build_src_filter = ${WioTrackerL1.build_src_filter} + +<../examples/companion_radio> + + + + +lib_deps = ${WioTrackerL1.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + end2endzone/NonBlockingRTTTL@^1.3.0 + +[env:WioTrackerL1_companion_radio_ble] +extends = WioTrackerL1 +build_flags = ${WioTrackerL1.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D OFFLINE_QUEUE_SIZE=256 + -D DISPLAY_CLASS=SH1106Display +; -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 + -D PIN_BUZZER=12 +build_src_filter = ${WioTrackerL1.build_src_filter} + + + +<../examples/companion_radio> + + +lib_deps = ${WioTrackerL1.lib_deps} + adafruit/RTClib @ ^2.1.3 + densaugeo/base64 @ ~1.4.0 + end2endzone/NonBlockingRTTTL@^1.3.0 diff --git a/variants/wio-tracker-l1/target.cpp b/variants/wio-tracker-l1/target.cpp new file mode 100644 index 00000000..0809e19e --- /dev/null +++ b/variants/wio-tracker-l1/target.cpp @@ -0,0 +1,146 @@ +#include +#include "target.h" +#include +#include + +WioTrackerL1Board 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 fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); +MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1); +WioTrackerL1SensorManager sensors = WioTrackerL1SensorManager(nmea); + +#ifdef DISPLAY_CLASS + DISPLAY_CLASS display; +#endif + +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); +} + +void WioTrackerL1SensorManager::start_gps() +{ + if (!gps_active) + { + MESH_DEBUG_PRINTLN("starting GPS"); + digitalWrite(PIN_GPS_STANDBY, HIGH); + gps_active = true; + } +} + +void WioTrackerL1SensorManager::stop_gps() +{ + if (gps_active) + { + MESH_DEBUG_PRINTLN("stopping GPS"); + digitalWrite(PIN_GPS_STANDBY, LOW); + gps_active = false; + } +} + +bool WioTrackerL1SensorManager::begin() +{ + Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX); // be sure to tx into rx and rx into tx + Serial1.begin(GPS_BAUDRATE); + + pinMode(PIN_GPS_STANDBY, OUTPUT); + digitalWrite(PIN_GPS_STANDBY, HIGH); // Wake GPS from standby + delay(500); + + // We'll consider GPS detected if we see any data on Serial1 + if (Serial1.available() > 0) + { + MESH_DEBUG_PRINTLN("GPS detected"); + } + else + { + MESH_DEBUG_PRINTLN("No GPS detected"); + } + digitalWrite(PIN_GPS_STANDBY, LOW); // Put GPS back into standby mode + return true; +} + +bool WioTrackerL1SensorManager::querySensors(uint8_t requester_permissions, CayenneLPP &telemetry) +{ + if (requester_permissions & TELEM_PERM_LOCATION) + { // does requester have permission? + telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude); + } + return true; +} + +void WioTrackerL1SensorManager::loop() +{ + static long next_gps_update = 0; + _location->loop(); + if (millis() > next_gps_update && gps_active) // don't bother if gps position is not enabled + { + if (_location->isValid()) + { + node_lat = ((double)_location->getLatitude()) / 1000000.; + node_lon = ((double)_location->getLongitude()) / 1000000.; + node_altitude = ((double)_location->getAltitude()) / 1000.0; + MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); + } + next_gps_update = millis() + (1000 * 60); // after initial update, only check every minute TODO: should be configurable + } +} + +int WioTrackerL1SensorManager::getNumSettings() const { return 1; } // just one supported: "gps" (power switch) + +const char *WioTrackerL1SensorManager::getSettingName(int i) const +{ + return i == 0 ? "gps" : NULL; +} + +const char *WioTrackerL1SensorManager::getSettingValue(int i) const +{ + if (i == 0) + { + return gps_active ? "1" : "0"; + } + return NULL; +} + +bool WioTrackerL1SensorManager::setSettingValue(const char *name, const char *value) +{ + if (strcmp(name, "gps") == 0) + { + if (strcmp(value, "0") == 0) + { + stop_gps(); + } + else + { + start_gps(); + } + return true; + } + return false; // not supported +} + +mesh::LocalIdentity radio_new_identity() { + RadioNoiseListener rng(radio); + return mesh::LocalIdentity(&rng); // create new random identity +} diff --git a/variants/wio-tracker-l1/target.h b/variants/wio-tracker-l1/target.h new file mode 100644 index 00000000..0aac6c59 --- /dev/null +++ b/variants/wio-tracker-l1/target.h @@ -0,0 +1,47 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#include +#include +#ifdef DISPLAY_CLASS + #include +#endif +#include + +class WioTrackerL1SensorManager : public SensorManager +{ + bool gps_active = false; + LocationProvider *_location; + + void start_gps(); + void stop_gps(); + +public: + WioTrackerL1SensorManager(LocationProvider &location) : _location(&location) {} + bool begin() override; + bool querySensors(uint8_t requester_permissions, CayenneLPP &telemetry) override; + void loop() override; + int getNumSettings() const override; + const char *getSettingName(int i) const override; + const char *getSettingValue(int i) const override; + bool setSettingValue(const char *name, const char *value) override; +}; + + +extern WioTrackerL1Board board; +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock rtc_clock; +extern WioTrackerL1SensorManager sensors; +#ifdef DISPLAY_CLASS + extern DISPLAY_CLASS display; +#endif + +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(); diff --git a/variants/wio-tracker-l1/variant.cpp b/variants/wio-tracker-l1/variant.cpp new file mode 100644 index 00000000..3db5ec9a --- /dev/null +++ b/variants/wio-tracker-l1/variant.cpp @@ -0,0 +1,73 @@ +#include "variant.h" +#include "wiring_constants.h" +#include "wiring_digital.h" +#include "nrf.h" + +const uint32_t g_ADigitalPinMap[] = { + // D0 .. D10 - Peripheral control pins + 41, // D0 P1.09 GNSS_WAKEUP + 7, // D1 P0.07 LORA_DIO1 + 39, // D2 P1,07 LORA_RESET + 42, // D3 P1.10 LORA_BUSY + 46, // D4 P1.14 (A4/SDA) LORA_CS + 40, // D5 P1.08 (A5/SCL) LORA_SW + 27, // D6 P0.27 (UART_TX) GNSS_TX + 26, // D7 P0.26 (UART_RX) GNSS_RX + 30, // D8 P0.30 (SPI_SCK) LORA_SCK + 3, // D9 P0.3 (SPI_MISO) LORA_MISO + 28, // D10 P0.28 (SPI_MOSI) LORA_MOSI + + // D11-D12 - LED outputs + 33, // D11 P1.1 User LED + // Buzzzer + 32, // D12 P1.0 Buzzer + + // D13 - User input + 8, // D13 P0.08 User Button + + // D14-D15 - OLED + 6, // D14 P0.06 OLED SDA + 5, // D15 P0.05 OLED SCL + + // D16 - Battery voltage ADC input + 31, // D16 P0.31 VBAT_ADC + // GROVE + 43, // D17 P0.00 GROVE SDA + 44, // D18 P0.01 GROVE SCL + + // FLASH + 21, // D19 P0.21 (QSPI_SCK) + 25, // D20 P0.25 (QSPI_CSN) + 20, // D21 P0.20 (QSPI_SIO_0 DI) + 24, // D22 P0.24 (QSPI_SIO_1 DO) + 22, // D23 P0.22 (QSPI_SIO_2 WP) + 23, // D24 P0.23 (QSPI_SIO_3 HOLD) + + // JOYSTICK + 36, // D25 TB_UP + 12, // D26 TB_DOWN + 11, // D27 TB_LEFT + 35, // D28 TB_RIGHT + 37, // D29 TB_PRESS + + // VBAT ENABLE + 4, // D30 BAT_CTL +}; + +void initVariant() { + pinMode(PIN_QSPI_CS, OUTPUT); + digitalWrite(PIN_QSPI_CS, HIGH); + + // VBAT_ENABLE + pinMode(VBAT_ENABLE, OUTPUT); + digitalWrite(VBAT_ENABLE, HIGH); + + // set LED pin as output and set it low + pinMode(PIN_LED, OUTPUT); + digitalWrite(PIN_LED, LOW); + + // set buzzer pin as output and set it low + pinMode(12, OUTPUT); + digitalWrite(12, LOW); + pinMode(12, OUTPUT); +} diff --git a/variants/wio-tracker-l1/variant.h b/variants/wio-tracker-l1/variant.h new file mode 100644 index 00000000..7f51dcb8 --- /dev/null +++ b/variants/wio-tracker-l1/variant.h @@ -0,0 +1,102 @@ +#ifndef _SEEED_WIO_TRACKER_L1_H_ +#define _SEEED_WIO_TRACKER_L1_H_ + +/** Master clock frequency */ +#define VARIANT_MCK (64000000ul) + +#define USE_LFXO // Board uses 32khz crystal for LF + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "WVariant.h" + +#define PINS_COUNT (33) +#define NUM_DIGITAL_PINS (33) +#define NUM_ANALOG_INPUTS (8) +#define NUM_ANALOG_OUTPUTS (0) + +// LEDs +#define PIN_LED (11) +#define LED_BLUE (-1) // Disable annoying flashing caused by Bluefruit +#define LED_BUILTIN PIN_LED +#define P_LORA_TX_LED PIN_LED +#define LED_STATE_ON 1 + +// Buttons +#define PIN_BUTTON1 (13) // Menu / User Button +#define PIN_BUTTON2 (25) // Joystick Up +#define PIN_BUTTON3 (26) // Joystick Down +#define PIN_BUTTON4 (27) // Joystick Left +#define PIN_BUTTON5 (28) // Joystick Right +#define PIN_BUTTON6 (28) // Joystick Press +#define PIN_USER_BTN PIN_BUTTON1 +#define JOYSTICK_UP PIN_BUTTON2 +#define JOYSTICK_DOWN PIN_BUTTON3 +#define JOYSTICK_LEFT PIN_BUTTON4 +#define JOYSTICK_RIGHT PIN_BUTTON5 +#define JOYSTICK_PRESS PIN_BUTTON6 + +// Buzzer +// #define PIN_BUZZER (12) // Buzzer pin (defined per firmware type) + +#define VBAT_ENABLE (30) + +// Analog pins +#define PIN_VBAT_READ (16) +#define AREF_VOLTAGE (3.6F) +#define ADC_MULTIPLIER (2.0F) +#define ADC_RESOLUTION (12) + +// Serial interfaces +#define PIN_SERIAL1_RX (7) +#define PIN_SERIAL1_TX (6) + +// SPI Interfaces +#define SPI_INTERFACES_COUNT (1) + +#define PIN_SPI_MISO (9) +#define PIN_SPI_MOSI (10) +#define PIN_SPI_SCK (8) + +// Lora Pins +#define P_LORA_SCLK PIN_SPI_SCK +#define P_LORA_MISO PIN_SPI_MISO +#define P_LORA_MOSI PIN_SPI_MOSI +#define P_LORA_DIO_1 (1) +#define P_LORA_RESET (2) +#define P_LORA_BUSY (3) +#define P_LORA_NSS (4) +#define SX126X_RXEN (5) +#define SX126X_TXEN RADIOLIB_NC + +// Wire Interfaces +#define WIRE_INTERFACES_COUNT (2) + +#define PIN_WIRE_SDA (14) +#define PIN_WIRE_SCL (15) +#define PIN_WIRE1_SDA (17) +#define PIN_WIRE1_SCL (18) +#define I2C_NO_RESCAN +#define DISPLAY_ADDRESS 0x3D // SH1106 OLED I2C address + +// GPS L76KB +#define GPS_BAUDRATE 9600 +#define PIN_GPS_TX PIN_SERIAL1_RX +#define PIN_GPS_RX PIN_SERIAL1_TX +#define PIN_GPS_STANDBY (0) +#define PIN_GPS_EN (18) + +// QSPI Pins +#define PIN_QSPI_SCK (21) +#define PIN_QSPI_CS (22) +#define PIN_QSPI_IO0 (23) +#define PIN_QSPI_IO1 (24) +#define PIN_QSPI_IO2 (25) +#define PIN_QSPI_IO3 (26) + +#define EXTERNAL_FLASH_DEVICES P25Q16H +#define EXTERNAL_FLASH_USE_QSPI + +#endif \ No newline at end of file