diff --git a/README.md b/README.md index 0fa85e7a..500457b2 100644 --- a/README.md +++ b/README.md @@ -156,10 +156,10 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. 1 = reset MAC counter to zero 2 = reset device to factory settings -0x0A set Wifi scan cycle and payload transmit cycle +0x0A set payload send cycle - 0 ... 255 duration of a wifi scan cycle in seconds/2, after this payload is sent - e.g. 120 -> 1 cycle runs for 240 seconds [default] + 0 ... 255 payload send cycle in seconds/2 + e.g. 120 -> payload is transmitted each 240 seconds [default] 0x0B set Wifi channel switch interval timer @@ -193,7 +193,7 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. 0x80 get device configuration -device answers with it's current configuration. The configuration is a C structure declared in file [globals.h](src/globals.h#L24-L41) with the following definition: +device answers with it's current configuration. The configuration is a C structure declared in file [globals.h](src/globals.h#L27-L44) with the following definition: byte 1: Lora SF (7..12) byte 2: Lora TXpower (2..15) @@ -202,7 +202,7 @@ device answers with it's current configuration. The configuration is a C structu byte 5: Display status (1=on, 0=off) byte 6: Counter mode (0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed) bytes 7-8: RSSI limiter threshold value (negative) - byte 9: Wifi scan cycle duration in seconds/2 (0..255) + byte 9: Payload send cycle in seconds/2 (0..255) byte 10: Wifi channel switch interval in seconds/100 (0..255) byte 11: BLE scan cycle duration in seconds (0..255) byte 12: BLE scan mode (1=on, 0=0ff) diff --git a/src/antenna.cpp b/src/antenna.cpp index 8bf94a2c..bcbf1703 100644 --- a/src/antenna.cpp +++ b/src/antenna.cpp @@ -21,7 +21,7 @@ void antenna_init(void) { gpio_config(&gpioconf); } -void antenna_select (const int8_t _ant) { +void antenna_select (const uint8_t _ant) { if (HAS_ANTENNA_SWITCH < 32) { if (_ant == ANTENNA_EXT) { GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << HAS_ANTENNA_SWITCH); diff --git a/src/blecsan.cpp b/src/blecsan.cpp index 8dd4bb15..4c2bb9af 100644 --- a/src/blecsan.cpp +++ b/src/blecsan.cpp @@ -100,7 +100,7 @@ static void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_pa { case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: { // restart scan - status = esp_ble_gap_start_scanning(BLESCANTIME); + status = esp_ble_gap_start_scanning(cfg.blescantime); if (status != ESP_OK) { ESP_LOGE(TAG, "esp_ble_gap_start_scanning: rc=%d", status); @@ -112,7 +112,7 @@ static void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_pa { if ( p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) // Inquiry complete, scan is done { // restart scan - status = esp_ble_gap_start_scanning (BLESCANTIME); + status = esp_ble_gap_start_scanning (cfg.blescantime); if (status != ESP_OK) { ESP_LOGE(TAG, "esp_ble_gap_start_scanning: rc=%d", status); @@ -286,8 +286,7 @@ void bt_loop(void * pvParameters) while(1) { - vTaskDelay(10/portTICK_PERIOD_MS); - yield(); + vTaskDelay(10/portTICK_PERIOD_MS); // reset watchdog } end: diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 628e4cd3..74c26206 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -13,7 +13,7 @@ esp_err_t err; // defined in antenna.cpp #ifdef HAS_ANTENNA_SWITCH - void antenna_select(const int8_t _ant); + void antenna_select(const uint8_t _ant); #endif // populate cfg vars with factory settings @@ -25,7 +25,7 @@ void defaultConfig() { cfg.screenon = 1; // 0=disbaled, 1=enabled cfg.countermode = 0; // 0=cyclic, 1=cumulative, 2=cyclic confirmed cfg.rssilimit = 0; // threshold for rssilimiter, negative value! - cfg.wifiscancycle = SEND_SECS; // wifi scan cycle [seconds/2] + cfg.sendcycle = SEND_SECS; // payload send cycle [seconds/2] cfg.wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100] cfg.blescantime = BLESCANTIME; // BLE scan cycle duration [seconds] cfg.blescan = 1; // 0=disabled, 1=enabled @@ -99,8 +99,8 @@ void saveConfig() { if( nvs_get_i8(my_handle, "countermode", &flash8) != ESP_OK || flash8 != cfg.countermode ) nvs_set_i8(my_handle, "countermode", cfg.countermode); - if( nvs_get_i8(my_handle, "wifiscancycle", &flash8) != ESP_OK || flash8 != cfg.wifiscancycle ) - nvs_set_i8(my_handle, "wifiscancycle", cfg.wifiscancycle); + if( nvs_get_i8(my_handle, "sendcycle", &flash8) != ESP_OK || flash8 != cfg.sendcycle ) + nvs_set_i8(my_handle, "sendcycle", cfg.sendcycle); if( nvs_get_i8(my_handle, "wifichancycle", &flash8) != ESP_OK || flash8 != cfg.wifichancycle ) nvs_set_i8(my_handle, "wifichancycle", cfg.wifichancycle); @@ -220,11 +220,11 @@ void loadConfig() { saveConfig(); } - if( nvs_get_i8(my_handle, "wifiscancycle", &flash8) == ESP_OK ) { - cfg.wifiscancycle = flash8; - ESP_LOGI(TAG, "wifiscancycle = %d", flash8); + if( nvs_get_i8(my_handle, "sendcycle", &flash8) == ESP_OK ) { + cfg.sendcycle = flash8; + ESP_LOGI(TAG, "sendcycle = %d", flash8); } else { - ESP_LOGI(TAG, "WIFI scan cycle set to default %d", cfg.wifiscancycle); + ESP_LOGI(TAG, "Payload send cycle set to default %d", cfg.sendcycle); saveConfig(); } diff --git a/src/globals.h b/src/globals.h index 7035c7d2..2578596d 100644 --- a/src/globals.h +++ b/src/globals.h @@ -26,33 +26,33 @@ // Struct holding devices's runtime configuration typedef struct { - int8_t lorasf; // 7-12, lora spreadfactor - int8_t txpower; // 2-15, lora tx power - int8_t adrmode; // 0=disabled, 1=enabled - int8_t screensaver; // 0=disabled, 1=enabled - int8_t screenon; // 0=disabled, 1=enabled - int8_t countermode; // 0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed + uint8_t lorasf; // 7-12, lora spreadfactor + uint8_t txpower; // 2-15, lora tx power + uint8_t adrmode; // 0=disabled, 1=enabled + uint8_t screensaver; // 0=disabled, 1=enabled + uint8_t screenon; // 0=disabled, 1=enabled + uint8_t countermode; // 0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed int16_t rssilimit; // threshold for rssilimiter, negative value! - int8_t wifiscancycle; // wifi scan cycle [seconds/2] - int8_t wifichancycle; // wifi channel switch cycle [seconds/100] - int8_t blescantime; // BLE scan cycle duration [seconds] - int8_t blescan; // 0=disabled, 1=enabled - int8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4) - int8_t vendorfilter; // 0=disabled, 1=enabled - int8_t rgblum; // RGB Led luminosity (0..100%) + uint8_t sendcycle; // payload send cycle [seconds/2] + uint8_t wifichancycle; // wifi channel switch cycle [seconds/100] + uint8_t blescantime; // BLE scan cycle duration [seconds] + uint8_t blescan; // 0=disabled, 1=enabled + uint8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4) + uint8_t vendorfilter; // 0=disabled, 1=enabled + uint8_t rgblum; // RGB Led luminosity (0..100%) char version[10]; // Firmware version } configData_t; extern configData_t cfg; extern uint8_t mydata[]; extern uint64_t uptimecounter; -extern unsigned long currentMillis ; extern osjob_t sendjob; extern char display_lora[], display_lmic[]; extern int countermode, screensaver, adrmode, lorasf, txpower, rlim; extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters extern bool joinstate; -extern std::set macs; +extern std::set macs; +extern hw_timer_t * channelSwitch; // hardware timer used for wifi channel switching #ifdef HAS_DISPLAY extern HAS_DISPLAY u8x8; diff --git a/src/hal/heltec.h b/src/hal/heltec.h index eb9aa31c..ed2e63db 100644 --- a/src/hal/heltec.h +++ b/src/hal/heltec.h @@ -17,7 +17,7 @@ #define RST 14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input #define DIO0 26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done #define DIO1 33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 32 // ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) +#define DIO2 LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) // Hardware pin definitions for Heltec LoRa-32 Board with OLED SSD1306 I2C Display #define OLED_RST 16 // ESP32 GPIO16 (Pin16) -- SD1306 RST diff --git a/src/hal/lolin32_lora.h b/src/hal/lolin32_lora.h index a1bdbe09..ca5929af 100644 --- a/src/hal/lolin32_lora.h +++ b/src/hal/lolin32_lora.h @@ -25,8 +25,8 @@ #define RST 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input #define DIO0 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done #define DIO1 26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 4 // ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) -#define DIO5 35 // ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) +#define DIO2 LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) +#define DIO5 LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) // Hardware pin definitions for LoRaNode32 Board with OLED I2C Display #define OLED_RST U8X8_PIN_NONE // Not reset pin diff --git a/src/hal/lolin32lite_lora.h b/src/hal/lolin32lite_lora.h index fe2adac8..51cd6f10 100644 --- a/src/hal/lolin32lite_lora.h +++ b/src/hal/lolin32lite_lora.h @@ -24,8 +24,8 @@ #define RST 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input #define DIO0 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done #define DIO1 26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 4 // ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) -#define DIO5 35 // ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) +#define DIO2 LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) +#define DIO5 LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) // Hardware pin definitions for LoRaNode32 Board with OLED I2C Display #define OLED_RST U8X8_PIN_NONE // Not reset pin diff --git a/src/hal/lopy.h b/src/hal/lopy.h index fffb2294..3e34dc8f 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -12,7 +12,7 @@ #define RST 18 #define DIO0 23 // LoRa IRQ #define DIO1 23 // workaround -#define DIO2 23 // workaround +#define DIO2 LMIC_UNUSED_PIN // 23 workaround // select WIFI antenna (internal = onboard / external = u.fl socket) #define HAS_ANTENNA_SWITCH 16 // pin for switching wifi antenna diff --git a/src/hal/lopy4.h b/src/hal/lopy4.h index 4ff9ac72..223e26b5 100644 --- a/src/hal/lopy4.h +++ b/src/hal/lopy4.h @@ -12,7 +12,7 @@ #define RST LMIC_UNUSED_PIN #define DIO0 23 // LoRa IRQ #define DIO1 23 // workaround -#define DIO2 23 // workaround +#define DIO2 LMIC_UNUSED_PIN // 23 workaround // select WIFI antenna (internal = onboard / external = u.fl socket) #define HAS_ANTENNA_SWITCH 21 // pin for switching wifi antenna diff --git a/src/hal/ttgov1.h b/src/hal/ttgov1.h index ab6b4f2c..c8e1a12d 100644 --- a/src/hal/ttgov1.h +++ b/src/hal/ttgov1.h @@ -18,7 +18,7 @@ #define RST 14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input #define DIO0 26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done #define DIO1 33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout -#define DIO2 32 // ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) +#define DIO2 LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) // Hardware pin definitions for TTGOv1 Board with OLED SSD1306 I2C Display #define OLED_RST 16 // ESP32 GPIO16 (Pin16) -- SD1306 Reset diff --git a/src/hal/ttgov2.h b/src/hal/ttgov2.h index 537990af..ebdfe87d 100644 --- a/src/hal/ttgov2.h +++ b/src/hal/ttgov2.h @@ -19,7 +19,7 @@ #define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN #define DIO0 26 // ESP32 GPIO26 wired on PCB to HPD13A #define DIO1 33 // HPDIO1 on pcb, needs to be wired external to GPIO33 -#define DIO2 32 // HPDIO2 on pcb, needs to be wired external to GPIO32 (not necessary for LoRa, only FSK) +#define DIO2 LMIC_UNUSED_PIN // 32 HPDIO2 on pcb, needs to be wired external to GPIO32 (not necessary for LoRa, only FSK) // Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display #define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN diff --git a/src/lorawan.cpp b/src/lorawan.cpp index b4f09726..a5e3e90a 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -14,8 +14,8 @@ static const char *TAG = "lorawan"; // functions defined in rcommand.cpp -void rcommand(int cmd, int arg); -void switch_lora(int sf, int tx); +void rcommand(uint8_t cmd, uint8_t arg); +void switch_lora(uint8_t sf, uint8_t tx); // DevEUI generator using devices's MAC address void gen_lora_deveui(uint8_t *pdeveui) { @@ -140,7 +140,7 @@ void do_send(osjob_t* j){ } // Schedule next transmission - os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(SEND_SECS * 2), do_send); + os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(cfg.sendcycle * 2), do_send); } // do_send() diff --git a/src/main.cpp b/src/main.cpp index 8aff95ee..5f360faa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,8 +41,6 @@ Refer to LICENSE.txt file in repository for more details. configData_t cfg; // struct holds current device configuration osjob_t sendjob, initjob; // LMIC jobs uint64_t uptimecounter = 0; // timer global for uptime counter -unsigned long currentMillis = millis(); // timer global for state machine -unsigned long previousDisplaymillis = currentMillis; // Display refresh for state machine uint8_t DisplayState = 0; // globals for state machine uint16_t macs_total = 0, macs_wifi = 0, macs_ble = 0; // MAC counters globals for display uint8_t channel = 0; // wifi channel rotation counter global for display @@ -54,11 +52,15 @@ uint16_t LEDBlinkDuration = 0; // How long the blink need to be uint16_t LEDColor = COLOR_NONE; // state machine variable to set RGB LED color bool joinstate = false; // LoRa network joined? global flag bool blinkdone = true; // flag for state machine for blinking LED once +hw_timer_t * displaytimer = NULL; // configure hardware timer used for cyclic display refresh +hw_timer_t * channelSwitch = NULL; // configure hardware timer used for wifi channel switching + +portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying shared variable DisplayIRQ std::set macs; // associative container holds total of unique MAC adress hashes (Wifi + BLE) -// this variable will be changed in the ISR, and read in main loop -static volatile bool ButtonTriggered = false; +// this variables will be changed in the ISR, and read in main loop +static volatile int ButtonPressed = 0, DisplayTimerIRQ = 0, ChannelTimerIRQ = 0; // local Tag for logging static const char *TAG = "paxcnt"; @@ -165,11 +167,9 @@ void lorawan_loop(void * pvParameters) { LMIC_reset(); // Reset the MAC state. Session and pending data transfers will be discarded. }; vTaskDelay(1000/portTICK_PERIOD_MS); - yield(); } */ - vTaskDelay(10/portTICK_PERIOD_MS); - yield(); + vTaskDelay(10/portTICK_PERIOD_MS); // reset watchdog } } @@ -181,12 +181,18 @@ void lorawan_loop(void * pvParameters) { #ifdef HAS_DISPLAY HAS_DISPLAY u8x8(OLED_RST, OLED_SCL, OLED_SDA); + // Display Refresh IRQ + void IRAM_ATTR DisplayIRQ() { + portENTER_CRITICAL_ISR(&timerMux); + DisplayTimerIRQ++; + portEXIT_CRITICAL_ISR(&timerMux); + } #endif #ifdef HAS_ANTENNA_SWITCH // defined in antenna.cpp void antenna_init(); - void antenna_select(const int8_t _ant); + void antenna_select(const uint8_t _ant); #endif #ifndef BLECOUNTER @@ -194,12 +200,19 @@ void lorawan_loop(void * pvParameters) { #endif #ifdef HAS_BUTTON - // Button Handling, board dependent -> perhaps to be moved to hal/<$board.h> + // Button IRQ // IRAM_ATTR necessary here, see https://github.com/espressif/arduino-esp32/issues/855 - void IRAM_ATTR isr_button_pressed(void) { - ButtonTriggered = true; } + void IRAM_ATTR ButtonIRQ() { + ButtonPressed++; + } #endif +void IRAM_ATTR ChannelSwitchIRQ() { + portENTER_CRITICAL(&timerMux); + ChannelTimerIRQ++; + portEXIT_CRITICAL(&timerMux); +} + /* end hardware specific parts -------------------------------------------------------- */ @@ -212,12 +225,16 @@ void sniffer_loop(void * pvParameters) { while (1) { - for (channel = 1; channel <= WIFI_CHANNEL_MAX; channel++) { - // rotates variable channel 1..WIFI_CHANNEL_MAX + if (ChannelTimerIRQ) { + portENTER_CRITICAL(&timerMux); + ChannelTimerIRQ--; + portEXIT_CRITICAL(&timerMux); + // rotates variable channel 1..WIFI_CHANNEL_MAX + channel = (channel % WIFI_CHANNEL_MAX) + 1; wifi_sniffer_set_channel(channel); ESP_LOGD(TAG, "Wifi set channel %d", channel); - vTaskDelay(cfg.wifichancycle*10 / portTICK_PERIOD_MS); - yield(); + + vTaskDelay(10/portTICK_PERIOD_MS); // reset watchdog } } // end of infinite wifi channel rotation loop @@ -313,16 +330,20 @@ uint64_t uptime() { u8x8.printf("%-16s", "BLTH:off"); #endif - // update free memory display (line 4) - u8x8.setCursor(10,4); - u8x8.printf("%4dKB", ESP.getFreeHeap() / 1024); + // update LoRa SF display (line 3) + u8x8.setCursor(11,3); + u8x8.printf("SF:%c%c", lora_datarate[LMIC.datarate * 2], lora_datarate[LMIC.datarate * 2 + 1]); - // update RSSI limiter status & wifi channel display (line 5) - u8x8.setCursor(0,5); - u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); - u8x8.setCursor(11,5); + // update wifi channel display (line 4) + u8x8.setCursor(11,4); u8x8.printf("ch:%02d", channel); + // update RSSI limiter status & free memory display (line 5) + u8x8.setCursor(0,5); + u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); + u8x8.setCursor(10,5); + u8x8.printf("%4dKB", ESP.getFreeHeap() / 1024); + // update LoRa status display (line 6) u8x8.setCursor(0,6); u8x8.printf("%-16s", display_lora); @@ -333,26 +354,27 @@ uint64_t uptime() { } void updateDisplay() { - // timed display refresh according to refresh cycle setting - - if (currentMillis - previousDisplaymillis >= DISPLAYREFRESH_MS) { + // refresh display according to refresh cycle setting + if (DisplayTimerIRQ) { + portENTER_CRITICAL(&timerMux); + DisplayTimerIRQ--; + portEXIT_CRITICAL(&timerMux); + refreshDisplay(); - previousDisplaymillis += DISPLAYREFRESH_MS; - } - // set display on/off according to current device configuration - if (DisplayState != cfg.screenon) { - DisplayState = cfg.screenon; - u8x8.setPowerSave(!cfg.screenon); + + // set display on/off according to current device configuration + if (DisplayState != cfg.screenon) { + DisplayState = cfg.screenon; + u8x8.setPowerSave(!cfg.screenon); + } } } // updateDisplay() - - #endif // HAS_DISPLAY #ifdef HAS_BUTTON void readButton() { - if (ButtonTriggered) { - ButtonTriggered = false; + if (ButtonPressed) { + ButtonPressed--; ESP_LOGI(TAG, "Button pressed, resetting device to factory defaults"); eraseConfig(); esp_restart(); @@ -497,12 +519,12 @@ void setup() { strcat(features, "PU"); // install button interrupt (pullup mode) pinMode(HAS_BUTTON, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), isr_button_pressed, RISING); + attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING); #else strcat(features, "PD"); // install button interrupt (pulldown mode) pinMode(HAS_BUTTON, INPUT_PULLDOWN); - attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), isr_button_pressed, FALLING); + attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING); #endif #endif @@ -529,9 +551,21 @@ void setup() { u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit); sprintf(display_lora, "Join wait"); + + // setup Display IRQ, thanks to https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/ + displaytimer = timerBegin(0, 80, true); // prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up + timerAttachInterrupt(displaytimer, &DisplayIRQ, true); // interrupt handler DisplayIRQ, triggered by edge + timerAlarmWrite(displaytimer, DISPLAYREFRESH_MS * 1000, true); // reload interrupt after each trigger of display refresh cycle + timerAlarmEnable(displaytimer); // enable display interrupt #endif -// Display features compiled for +// setup channel rotation IRQ, thanks to https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/ +channelSwitch = timerBegin(1, 80, true); // prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 1, count up +timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true); // interrupt handler, triggered by edge +timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true); // reload interrupt after each trigger of channel switch cycle +timerAlarmEnable(channelSwitch); // enable channel switching interrupt + +// show compiled features ESP_LOGI(TAG, "Features %s", features); // output LoRaWAN keys to console @@ -579,7 +613,6 @@ void loop() { // simple state machine for controlling display, LED, button, etc. uptimecounter = uptime() / 1000; // counts uptime in seconds (64bit) - currentMillis = millis(); // timebase for state machine in milliseconds (32bit) #if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED) led_loop(); @@ -600,6 +633,8 @@ void loop() { reset_salt(); // get new salt for salting hashes } + vTaskDelay(10/portTICK_PERIOD_MS); // reset watchdog + } /* end Aruino LOOP ------------------------------------------------------------ */ diff --git a/src/main.h b/src/main.h index 8b0d5b60..5ad9b39b 100644 --- a/src/main.h +++ b/src/main.h @@ -1,6 +1,6 @@ // program version - note: increment version after modifications to configData_t struct!! -#define PROGVERSION "1.3.3" // use max 10 chars here! +#define PROGVERSION "1.3.4" // use max 10 chars here! #define PROGNAME "PAXCNT" //--- Declarations --- @@ -10,6 +10,12 @@ enum led_states { LED_ON }; +#if defined(CFG_eu868) + const char lora_datarate[] = {"1211100908077BFSNA"}; +#elif defined(CFG_us915) + const char lora_datarate[] = {"100908078CNA121110090807"}; +#endif + //--- Prototypes --- // defined in main.cpp diff --git a/src/paxcounter.conf b/src/paxcounter.conf index ec8c455a..cc953b6b 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -34,7 +34,7 @@ // LoRa payload send cycle --> take care of duty cycle of LoRaWAN network! <-- #define SEND_SECS 120 // [seconds/2] -> 240 sec. -#define MEM_LOW 2048 // [Bytes] memory threshold triggering send cycle +#define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle // Default LoRa Spreadfactor #define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs @@ -45,7 +45,7 @@ #define RGBLUMINOSITY 30 // 30% // OLED Display refresh cycle (in Milliseconds) -#define DISPLAYREFRESH_MS 40 // e.g. 40ms -> 1000/40 = 25 frames per second +#define DISPLAYREFRESH_MS 40 // e.g. 40ms -> 1000/40 = 25 frames per second // LMIC settings // define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 90894149..95ccee33 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -14,18 +14,18 @@ static const char *TAG = "rcommand"; // table of remote commands and assigned functions typedef struct { - const int nam; - void (*func)(int); + const uint8_t nam; + void (*func)(uint8_t); const bool store; } cmd_t; // function defined in antenna.cpp #ifdef HAS_ANTENNA_SWITCH - void antenna_select(const int8_t _ant); + void antenna_select(const uint8_t _ant); #endif // help function to assign LoRa datarates to numeric spreadfactor values -void switch_lora (int sf, int tx) { +void switch_lora (uint8_t sf, uint8_t tx) { if ( tx > 20 ) return; cfg.txpower = tx; switch (sf) { @@ -50,7 +50,7 @@ void switch_lora (int sf, int tx) { } // set of functions that can be triggered by remote commands -void set_reset(int val) { +void set_reset(uint8_t val) { switch (val) { case 0: // restart device ESP_LOGI(TAG, "Remote command: restart device"); @@ -72,27 +72,29 @@ void set_reset(int val) { } }; -void set_rssi(int val) { +void set_rssi(uint8_t val) { cfg.rssilimit = val * -1; ESP_LOGI(TAG, "Remote command: set RSSI limit to %d", cfg.rssilimit); }; -void set_wifiscancycle(int val) { - cfg.wifiscancycle = val; - ESP_LOGI(TAG, "Remote command: set Wifi scan cycle duration to %d seconds", cfg.wifiscancycle*2); +void set_sendcycle(uint8_t val) { + cfg.sendcycle = val; + ESP_LOGI(TAG, "Remote command: set payload send cycle to %d seconds", cfg.sendcycle*2); }; -void set_wifichancycle(int val) { +void set_wifichancycle(uint8_t val) { cfg.wifichancycle = val; - ESP_LOGI(TAG, "Remote command: set Wifi channel switch interval to %d seconds", cfg.wifichancycle/100); + // modify wifi channel rotation IRQ + timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true); // reload interrupt after each trigger of channel switch cycle + ESP_LOGI(TAG, "Remote command: set Wifi channel switch interval to %.1f seconds", cfg.wifichancycle/float(100)); }; -void set_blescantime(int val) { +void set_blescantime(uint8_t val) { cfg.blescantime = val; ESP_LOGI(TAG, "Remote command: set BLE scan time to %d seconds", cfg.blescantime); }; -void set_countmode(int val) { +void set_countmode(uint8_t val) { switch (val) { case 0: // cyclic unconfirmed cfg.countermode = 0; @@ -109,7 +111,7 @@ void set_countmode(int val) { } }; -void set_screensaver(int val) { +void set_screensaver(uint8_t val) { ESP_LOGI(TAG, "Remote command: set screen saver to %s ", val ? "on" : "off"); switch (val) { case 1: cfg.screensaver = val; break; @@ -117,7 +119,7 @@ void set_screensaver(int val) { } }; -void set_display(int val) { +void set_display(uint8_t val) { ESP_LOGI(TAG, "Remote command: set screen to %s", val ? "on" : "off"); switch (val) { case 1: cfg.screenon = val; break; @@ -125,12 +127,12 @@ void set_display(int val) { } }; -void set_lorasf(int val) { +void set_lorasf(uint8_t val) { ESP_LOGI(TAG, "Remote command: set LoRa SF to %d", val); switch_lora(val, cfg.txpower); }; -void set_loraadr(int val) { +void set_loraadr(uint8_t val) { ESP_LOGI(TAG, "Remote command: set LoRa ADR mode to %s", val ? "on" : "off"); switch (val) { case 1: cfg.adrmode = val; break; @@ -139,7 +141,7 @@ void set_loraadr(int val) { LMIC_setAdrMode(cfg.adrmode); }; -void set_blescan(int val) { +void set_blescan(uint8_t val) { ESP_LOGI(TAG, "Remote command: set BLE scan mode to %s", val ? "on" : "off"); switch (val) { case 0: @@ -152,7 +154,7 @@ void set_blescan(int val) { } }; -void set_wifiant(int val) { +void set_wifiant(uint8_t val) { ESP_LOGI(TAG, "Remote command: set Wifi antenna to %s", val ? "external" : "internal"); switch (val) { case 1: cfg.wifiant = val; break; @@ -163,7 +165,7 @@ void set_wifiant(int val) { #endif }; -void set_vendorfilter(int val) { +void set_vendorfilter(uint8_t val) { ESP_LOGI(TAG, "Remote command: set vendorfilter mode to %s", val ? "on" : "off"); switch (val) { case 1: cfg.vendorfilter = val; break; @@ -171,22 +173,22 @@ void set_vendorfilter(int val) { } }; -void set_rgblum(int val) { +void set_rgblum(uint8_t val) { // Avoid wrong parameters cfg.rgblum = (val>=0 && val<=100) ? (uint8_t) val : RGBLUMINOSITY; ESP_LOGI(TAG, "Remote command: set RGB Led luminosity %d", cfg.rgblum); }; -void set_lorapower(int val) { +void set_lorapower(uint8_t val) { ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %d", val); switch_lora(cfg.lorasf, val); }; -void set_noop (int val) { +void set_noop (uint8_t val) { ESP_LOGI(TAG, "Remote command: noop - doing nothing"); }; -void get_config (int val) { +void get_config (uint8_t val) { ESP_LOGI(TAG, "Remote command: get configuration"); int size = sizeof(configData_t); // declare send buffer (char byte array) @@ -198,7 +200,7 @@ void get_config (int val) { ESP_LOGI(TAG, "%d bytes queued in send queue", size-1); }; -void get_uptime (int val) { +void get_uptime (uint8_t val) { ESP_LOGI(TAG, "Remote command: get uptime"); int size = sizeof(uptimecounter); unsigned char *sendData = new unsigned char[size]; @@ -208,7 +210,7 @@ void get_uptime (int val) { ESP_LOGI(TAG, "%d bytes queued in send queue", size-1); }; -void get_cputemp (int val) { +void get_cputemp (uint8_t val) { ESP_LOGI(TAG, "Remote command: get cpu temperature"); float temp = temperatureRead(); int size = sizeof(temp); @@ -232,7 +234,7 @@ cmd_t table[] = { {0x07, set_loraadr, true}, {0x08, set_screensaver, true}, {0x09, set_reset, false}, - {0x0a, set_wifiscancycle, true}, + {0x0a, set_sendcycle, true}, {0x0b, set_wifichancycle, true}, {0x0c, set_blescantime, true}, {0x0d, set_vendorfilter, false}, @@ -245,7 +247,7 @@ cmd_t table[] = { }; // check and execute remote command -void rcommand(int cmd, int arg) { +void rcommand(uint8_t cmd, uint8_t arg) { int i = sizeof(table) / sizeof(table[0]); // number of commands in command table bool store_flag = false; while(i--) {