diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index 6ae6ac0a8..64fcc91b7 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -722,6 +722,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc _prefs.advert_loc_policy = ADVERT_LOC_PREFS; _prefs.adc_multiplier = 0.0f; // 0.0f means use default board multiplier + _prefs.idle_interval = 0; } void MyMesh::begin(FILESYSTEM *fs) { diff --git a/examples/simple_repeater/MyMesh.h b/examples/simple_repeater/MyMesh.h index ed9f0c5fc..987851b5a 100644 --- a/examples/simple_repeater/MyMesh.h +++ b/examples/simple_repeater/MyMesh.h @@ -171,6 +171,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { const char* getBuildDate() override { return FIRMWARE_BUILD_DATE; } const char* getRole() override { return FIRMWARE_ROLE; } const char* getNodeName() { return _prefs.node_name; } + const uint32_t getIdleInterval() { return _prefs.idle_interval; } NodePrefs* getNodePrefs() { return &_prefs; } diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 7387e77e7..dc87a322f 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -19,6 +19,12 @@ void halt() { static char command[160]; +constexpr unsigned long ACTIVE_TIME_MS_INUSE = 3 * 60 * 1000; // 3 minutes +constexpr unsigned long ACTIVE_TIME_MS_IDLE = 5 * 1000; // 5 seconds + +unsigned long active_timestamp; +unsigned long active_time_ms = ACTIVE_TIME_MS_INUSE; + void setup() { Serial.begin(115200); delay(1000); @@ -82,6 +88,7 @@ void setup() { // send out initial Advertisement to the mesh the_mesh.sendSelfAdvertisement(16000); + active_timestamp = millis(); } void loop() { @@ -103,6 +110,8 @@ void loop() { Serial.print('\n'); command[len - 1] = 0; // replace newline with C string null terminator char reply[160]; + active_timestamp = millis(); + active_time_ms = ACTIVE_TIME_MS_INUSE; the_mesh.handleCommand(0, command, reply); // NOTE: there is no sender_timestamp via serial! if (reply[0]) { Serial.print(" -> "); Serial.println(reply); @@ -117,4 +126,11 @@ void loop() { ui_task.loop(); #endif rtc_clock.tick(); + + if (the_mesh.getIdleInterval() && ((millis() - active_timestamp) > active_time_ms) && + !the_mesh.hasOutboundPackets()) { + radio_driver.blockTaskUntilRXEvent(the_mesh.getIdleInterval() * 1000); + active_timestamp = millis(); + active_time_ms = ACTIVE_TIME_MS_IDLE; + } } diff --git a/src/Dispatcher.h b/src/Dispatcher.h index 25a41d82c..013528c91 100644 --- a/src/Dispatcher.h +++ b/src/Dispatcher.h @@ -167,6 +167,7 @@ class Dispatcher { Packet* obtainNewPacket(); void releasePacket(Packet* packet); void sendPacket(Packet* packet, uint8_t priority, uint32_t delay_millis=0); + bool hasOutboundPackets() { return _mgr->getOutboundCount(0xFFFFFFFF); } unsigned long getTotalAirTime() const { return total_air_time; } // in milliseconds unsigned long getReceiveAirTime() const {return rx_air_time; } diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index a3de990aa..35278232a 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -70,8 +70,9 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { file.read((uint8_t *)&_prefs->gps_interval, sizeof(_prefs->gps_interval)); // 157 file.read((uint8_t *)&_prefs->advert_loc_policy, sizeof (_prefs->advert_loc_policy)); // 161 file.read((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162 - file.read((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166 - // 170 + file.read((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166 + file.read((uint8_t *)&_prefs->idle_interval, sizeof(_prefs->idle_interval)); // 170 + // 174 // sanitise bad pref values _prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f); @@ -151,7 +152,8 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) { file.write((uint8_t *)&_prefs->advert_loc_policy, sizeof(_prefs->advert_loc_policy)); // 161 file.write((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162 file.write((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166 - // 170 + file.write((uint8_t *)&_prefs->idle_interval, sizeof(_prefs->idle_interval)); // 170 + // 174 file.close(); } @@ -301,6 +303,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch sprintf(reply, "> %d", (uint32_t) _prefs->tx_power_dbm); } else if (memcmp(config, "freq", 4) == 0) { sprintf(reply, "> %s", StrHelper::ftoa(_prefs->freq)); + } else if (memcmp(config, "idle.interval", 13) == 0) { + sprintf(reply, "> %d", ((uint32_t)_prefs->idle_interval)); } else if (memcmp(config, "public.key", 10) == 0) { strcpy(reply, "> "); mesh::Utils::toHex(&reply[2], _callbacks->getSelfId().pub_key, PUB_KEY_SIZE); @@ -484,6 +488,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch _prefs->freq = atof(&config[5]); savePrefs(); strcpy(reply, "OK - reboot to apply"); + } else if (memcmp(config, "idle.interval ", 14) == 0) { + _prefs->idle_interval = atoi(&config[14]); + savePrefs(); + strcpy(reply, "OK"); #ifdef WITH_BRIDGE } else if (memcmp(config, "bridge.enabled ", 15) == 0) { _prefs->bridge_enabled = memcmp(&config[15], "on", 2) == 0; diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index 068783ab1..2848baf9f 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -48,6 +48,7 @@ struct NodePrefs { // persisted to file uint8_t advert_loc_policy; uint32_t discovery_mod_timestamp; float adc_multiplier; + uint32_t idle_interval; // in seconds }; class CommonCLICallbacks { diff --git a/src/helpers/radiolib/RadioLibWrappers.cpp b/src/helpers/radiolib/RadioLibWrappers.cpp index 9014743a3..9e852d266 100644 --- a/src/helpers/radiolib/RadioLibWrappers.cpp +++ b/src/helpers/radiolib/RadioLibWrappers.cpp @@ -12,6 +12,7 @@ #define SAMPLING_THRESHOLD 14 static volatile uint8_t state = STATE_IDLE; +static SemaphoreHandle_t rx_wait_sem; // this function is called when a complete packet // is transmitted by the module @@ -22,6 +23,8 @@ static void setFlag(void) { // we sent a packet, set the flag state |= STATE_INT_READY; + + if (state & STATE_RX) xSemaphoreGive(rx_wait_sem); } void RadioLibWrapper::begin() { @@ -38,6 +41,10 @@ void RadioLibWrapper::begin() { // start average out some samples _num_floor_samples = 0; _floor_sample_sum = 0; + + rx_wait_sem = xSemaphoreCreateBinary(); + xSemaphoreGive(rx_wait_sem); + xSemaphoreTake(rx_wait_sem, portMAX_DELAY); } void RadioLibWrapper::idle() { @@ -45,6 +52,10 @@ void RadioLibWrapper::idle() { state = STATE_IDLE; // need another startReceive() } +int RadioLibWrapper::blockTaskUntilRXEvent(unsigned int timeout = 5000) { + return xSemaphoreTake(rx_wait_sem, pdMS_TO_TICKS(timeout)); +} + void RadioLibWrapper::triggerNoiseFloorCalibrate(int threshold) { _threshold = threshold; if (_num_floor_samples >= NUM_NOISE_FLOOR_SAMPLES) { // ignore trigger if currently sampling diff --git a/src/helpers/radiolib/RadioLibWrappers.h b/src/helpers/radiolib/RadioLibWrappers.h index 3c26d3727..6e907ba4b 100644 --- a/src/helpers/radiolib/RadioLibWrappers.h +++ b/src/helpers/radiolib/RadioLibWrappers.h @@ -36,6 +36,8 @@ class RadioLibWrapper : public mesh::Radio { return isChannelActive(); } + int blockTaskUntilRXEvent(unsigned int timeout); + virtual float getCurrentRSSI() =0; int getNoiseFloor() const override { return _noise_floor; } diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 2692ec9c8..698132382 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -606,6 +606,7 @@ void EnvironmentSensorManager::rakGPSInit(){ MESH_DEBUG_PRINTLN("No GPS found"); gps_active = false; gps_detected = false; + Serial1.end(); return; } @@ -644,8 +645,7 @@ bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin){ _location = &RAK12500_provider; return true; - } - else if(Serial1){ + } else if (Serial1.available()) { MESH_DEBUG_PRINTLN("Serial GPS init correctly and is turned on"); if(PIN_GPS_EN){ gpsResetPin = PIN_GPS_EN; @@ -655,6 +655,8 @@ bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin){ gps_detected = true; return true; } + + pinMode(ioPin, INPUT); MESH_DEBUG_PRINTLN("GPS did not init with this IO pin... try the next"); return false; } diff --git a/variants/rak4631/RAK4631Board.h b/variants/rak4631/RAK4631Board.h index a181256b0..343f4ebff 100644 --- a/variants/rak4631/RAK4631Board.h +++ b/variants/rak4631/RAK4631Board.h @@ -7,7 +7,7 @@ // LoRa radio module pins for RAK4631 #define P_LORA_DIO_1 47 #define P_LORA_NSS 42 -#define P_LORA_RESET RADIOLIB_NC // 38 +#define P_LORA_RESET 38 #define P_LORA_BUSY 46 #define P_LORA_SCLK 43 #define P_LORA_MISO 45