Display refresh & Button IRQ

This commit is contained in:
Klaus K Wilting 2018-04-27 22:41:07 +02:00
parent cc003c43f0
commit b9db1bf1dc
2 changed files with 38 additions and 23 deletions

View File

@ -41,7 +41,6 @@ Refer to LICENSE.txt file in repository for more details.
configData_t cfg; // struct holds current device configuration configData_t cfg; // struct holds current device configuration
osjob_t sendjob, initjob; // LMIC jobs osjob_t sendjob, initjob; // LMIC jobs
uint64_t uptimecounter = 0; // timer global for uptime counter uint64_t uptimecounter = 0; // timer global for uptime counter
unsigned long previousDisplaymillis = millis(); // Display refresh for state machine
uint8_t DisplayState = 0; // globals 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 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 uint8_t channel = 0; // wifi channel rotation counter global for display
@ -53,11 +52,13 @@ uint16_t LEDBlinkDuration = 0; // How long the blink need to be
uint16_t LEDColor = COLOR_NONE; // state machine variable to set RGB LED color uint16_t LEDColor = COLOR_NONE; // state machine variable to set RGB LED color
bool joinstate = false; // LoRa network joined? global flag bool joinstate = false; // LoRa network joined? global flag
bool blinkdone = true; // flag for state machine for blinking LED once bool blinkdone = true; // flag for state machine for blinking LED once
hw_timer_t * timer = NULL; // configure hardware timer used for cyclic display refresh
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying shared variable DisplayIRQ
std::set<uint16_t> macs; // associative container holds total of unique MAC adress hashes (Wifi + BLE) std::set<uint16_t> 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 // this variables will be changed in the ISR, and read in main loop
static volatile bool ButtonTriggered = false; static volatile int ButtonPressed = 0, DisplayTimerIRQ = 0;
// local Tag for logging // local Tag for logging
static const char *TAG = "paxcnt"; static const char *TAG = "paxcnt";
@ -180,6 +181,12 @@ void lorawan_loop(void * pvParameters) {
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
HAS_DISPLAY u8x8(OLED_RST, OLED_SCL, OLED_SDA); 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 #endif
#ifdef HAS_ANTENNA_SWITCH #ifdef HAS_ANTENNA_SWITCH
@ -193,10 +200,11 @@ void lorawan_loop(void * pvParameters) {
#endif #endif
#ifdef HAS_BUTTON #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 // IRAM_ATTR necessary here, see https://github.com/espressif/arduino-esp32/issues/855
void IRAM_ATTR isr_button_pressed(void) { void IRAM_ATTR ButtonIRQ() {
ButtonTriggered = true; } ButtonPressed++;
}
#endif #endif
/* end hardware specific parts -------------------------------------------------------- */ /* end hardware specific parts -------------------------------------------------------- */
@ -332,26 +340,27 @@ uint64_t uptime() {
} }
void updateDisplay() { void updateDisplay() {
// timed display refresh according to refresh cycle setting // refresh display according to refresh cycle setting
if (DisplayTimerIRQ) {
if (millis() - previousDisplaymillis >= DISPLAYREFRESH_MS) { portENTER_CRITICAL(&timerMux);
DisplayTimerIRQ--;
portEXIT_CRITICAL(&timerMux);
refreshDisplay(); refreshDisplay();
previousDisplaymillis += DISPLAYREFRESH_MS;
} // set display on/off according to current device configuration
// set display on/off according to current device configuration if (DisplayState != cfg.screenon) {
if (DisplayState != cfg.screenon) { DisplayState = cfg.screenon;
DisplayState = cfg.screenon; u8x8.setPowerSave(!cfg.screenon);
u8x8.setPowerSave(!cfg.screenon); }
} }
} // updateDisplay() } // updateDisplay()
#endif // HAS_DISPLAY #endif // HAS_DISPLAY
#ifdef HAS_BUTTON #ifdef HAS_BUTTON
void readButton() { void readButton() {
if (ButtonTriggered) { if (ButtonPressed) {
ButtonTriggered = false; ButtonPressed--;
ESP_LOGI(TAG, "Button pressed, resetting device to factory defaults"); ESP_LOGI(TAG, "Button pressed, resetting device to factory defaults");
eraseConfig(); eraseConfig();
esp_restart(); esp_restart();
@ -496,12 +505,12 @@ void setup() {
strcat(features, "PU"); strcat(features, "PU");
// install button interrupt (pullup mode) // install button interrupt (pullup mode)
pinMode(HAS_BUTTON, INPUT_PULLUP); pinMode(HAS_BUTTON, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), isr_button_pressed, RISING); attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING);
#else #else
strcat(features, "PD"); strcat(features, "PD");
// install button interrupt (pulldown mode) // install button interrupt (pulldown mode)
pinMode(HAS_BUTTON, INPUT_PULLDOWN); pinMode(HAS_BUTTON, INPUT_PULLDOWN);
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), isr_button_pressed, FALLING); attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING);
#endif #endif
#endif #endif
@ -528,9 +537,15 @@ void setup() {
u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit); u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit);
sprintf(display_lora, "Join wait"); sprintf(display_lora, "Join wait");
// setup Display IRQ, thanks to https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
timer = timerBegin(0, 80, true); // prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up
timerAttachInterrupt(timer, &DisplayIRQ, true); // interrupt handler DisplayIRQ, triggered by edge
timerAlarmWrite(timer, DISPLAYREFRESH_MS * 1000, true); // reload interrupt after each trigger of display refresh cycle
timerAlarmEnable(timer); // enable display interrupt
#endif #endif
// Display features compiled for // show compiled features
ESP_LOGI(TAG, "Features %s", features); ESP_LOGI(TAG, "Features %s", features);
// output LoRaWAN keys to console // output LoRaWAN keys to console

View File

@ -45,7 +45,7 @@
#define RGBLUMINOSITY 30 // 30% #define RGBLUMINOSITY 30 // 30%
// OLED Display refresh cycle (in Milliseconds) // 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 // LMIC settings
// define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored // define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored