From 5b8cef880c40e31d97fb36e2f5039ec7d837334e Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 11 Aug 2019 21:12:27 +0200 Subject: [PATCH 001/105] v1.7.91 --- platformio.ini | 2 +- src/timekeeper.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index a4499620..4df4cb24 100644 --- a/platformio.ini +++ b/platformio.ini @@ -40,7 +40,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.841 +release_version = 1.7.91 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 diff --git a/src/timekeeper.cpp b/src/timekeeper.cpp index 4d01f7d9..4afe5641 100644 --- a/src/timekeeper.cpp +++ b/src/timekeeper.cpp @@ -54,6 +54,8 @@ void calibrateTime(void) { } #endif +goto finish; + finish: setMyTime(t, t_msec, timeSource); // set time From b926d908b22da2380c8d6aaca34766b5dc7b2ea7 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Tue, 13 Aug 2019 22:40:33 +0200 Subject: [PATCH 002/105] timekeeper/timesync: fixed dependencies --- include/timekeeper.h | 1 + include/timesync.h | 1 - src/timekeeper.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++- src/timesync.cpp | 46 ------------------------------------------ 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/include/timekeeper.h b/include/timekeeper.h index 6239f082..20199ac1 100644 --- a/include/timekeeper.h +++ b/include/timekeeper.h @@ -27,6 +27,7 @@ void timeSync(void); uint8_t timepulse_init(void); time_t timeIsValid(time_t const t); void calibrateTime(void); +void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource); time_t compiledUTC(void); TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPins); diff --git a/include/timesync.h b/include/timesync.h index 498952c1..7a0013ec 100644 --- a/include/timesync.h +++ b/include/timesync.h @@ -15,6 +15,5 @@ void send_timesync_req(void); int recv_timesync_ans(uint8_t seq_no, uint8_t buf[], uint8_t buf_len); void process_timesync_req(void *taskparameter); void store_time_sync_req(uint32_t t_millisec); -void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t timesource); #endif \ No newline at end of file diff --git a/src/timekeeper.cpp b/src/timekeeper.cpp index 4afe5641..16236de0 100644 --- a/src/timekeeper.cpp +++ b/src/timekeeper.cpp @@ -58,10 +58,56 @@ goto finish; finish: - setMyTime(t, t_msec, timeSource); // set time + setMyTime((uint32_t)t, t_msec, timeSource); // set time } // calibrateTime() +// adjust system time, calibrate RTC and RTC_INT pps +void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec, + timesource_t mytimesource) { + + // increment t_sec only if t_msec > 1000 + time_t time_to_set = (time_t)(t_sec + t_msec / 1000); + + // do we have a valid time? + if (timeIsValid(time_to_set)) { + + // if we have msec fraction, then wait until top of second with + // millisecond precision + if (t_msec % 1000) { + time_to_set++; + vTaskDelay(pdMS_TO_TICKS(1000 - t_msec % 1000)); + } + + ESP_LOGD(TAG, "[%0.3f] UTC epoch time: %d.%03d sec", millis() / 1000.0, + time_to_set, t_msec % 1000); + +// if we have got an external timesource, set RTC time and shift RTC_INT pulse +// to top of second +#ifdef HAS_RTC + if ((mytimesource == _gps) || (mytimesource == _lora)) + set_rtctime(time_to_set); +#endif + +// if we have a software pps timer, shift it to top of second +#if (!defined GPS_INT && !defined RTC_INT) + timerWrite(ppsIRQ, 0); // reset pps timer + CLOCKIRQ(); // fire clock pps, this advances time 1 sec +#endif + + setTime(time_to_set); // set the time on top of second + + timeSource = mytimesource; // set global variable + timesyncer.attach(TIME_SYNC_INTERVAL * 60, timeSync); + ESP_LOGI(TAG, "[%0.3f] Timesync finished, time was set | source: %c", + millis() / 1000.0, timeSetSymbols[timeSource]); + } else { + timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, timeSync); + ESP_LOGI(TAG, "[%0.3f] Timesync failed, invalid time fetched | source: %c", + millis() / 1000.0, timeSetSymbols[timeSource]); + } +} + // helper function to setup a pulse per second for time synchronisation uint8_t timepulse_init() { diff --git a/src/timesync.cpp b/src/timesync.cpp index ef50041d..b1814538 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -207,52 +207,6 @@ int recv_timesync_ans(uint8_t seq_no, uint8_t buf[], uint8_t buf_len) { } } -// adjust system time, calibrate RTC and RTC_INT pps -void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec, - timesource_t mytimesource) { - - // increment t_sec only if t_msec > 1000 - time_t time_to_set = (time_t)(t_sec + t_msec / 1000); - - // do we have a valid time? - if (timeIsValid(time_to_set)) { - - // if we have msec fraction, then wait until top of second with - // millisecond precision - if (t_msec % 1000) { - time_to_set++; - vTaskDelay(pdMS_TO_TICKS(1000 - t_msec % 1000)); - } - - ESP_LOGD(TAG, "[%0.3f] UTC epoch time: %d.%03d sec", millis() / 1000.0, - time_to_set, t_msec % 1000); - -// if we have got an external timesource, set RTC time and shift RTC_INT pulse -// to top of second -#ifdef HAS_RTC - if ((mytimesource == _gps) || (mytimesource == _lora)) - set_rtctime(time_to_set); -#endif - -// if we have a software pps timer, shift it to top of second -#if (!defined GPS_INT && !defined RTC_INT) - timerWrite(ppsIRQ, 0); // reset pps timer - CLOCKIRQ(); // fire clock pps, this advances time 1 sec -#endif - - setTime(time_to_set); // set the time on top of second - - timeSource = mytimesource; // set global variable - timesyncer.attach(TIME_SYNC_INTERVAL * 60, timeSync); - ESP_LOGI(TAG, "[%0.3f] Timesync finished, time was set | source: %c", - millis() / 1000.0, timeSetSymbols[timeSource]); - } else { - timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, timeSync); - ESP_LOGI(TAG, "[%0.3f] Timesync failed, invalid time fetched | source: %c", - millis() / 1000.0, timeSetSymbols[timeSource]); - } -} - // create task for timeserver handshake processing, called from main.cpp void timesync_init() { xTaskCreatePinnedToCore(process_timesync_req, // task function From 8717d5e3a738798714345d5aa6166eba06406cb0 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Tue, 13 Aug 2019 22:47:19 +0200 Subject: [PATCH 003/105] changed lmic clock error procentage --- src/lmic_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic_config.h b/src/lmic_config.h index 9e90a439..f4ddf4ab 100644 --- a/src/lmic_config.h +++ b/src/lmic_config.h @@ -35,7 +35,7 @@ // so consuming more power. You may sharpen (reduce) this value if you are // limited on battery. // ATTN: VALUES > 7 WILL CAUSE RECEPTION AND JOIN PROBLEMS WITH HIGH SF RATES -#define CLOCK_ERROR_PROCENTAGE 5 +#define CLOCK_ERROR_PROCENTAGE 7 // Set this to 1 to enable some basic debug output (using printf) about // RF settings used during transmission and reception. Set to 2 to From c566b302d576828978521aa3090a0d43067ab92a Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 14 Aug 2019 21:52:12 +0200 Subject: [PATCH 004/105] add tinyPICO board --- platformio.ini | 3 ++- src/hal/eboxtube.h | 2 +- src/hal/fipy.h | 2 +- src/hal/generic.h | 2 +- src/hal/lolin32litelora.h | 2 +- src/hal/lolin32lora.h | 2 +- src/hal/lopy.h | 2 +- src/hal/lopy4.h | 4 ++-- src/hal/octopus32.h | 2 +- src/hal/tinypico.h | 24 ++++++++++++++++++++++++ src/led.cpp | 2 +- src/main.cpp | 10 +++++++++- src/paxcounter.conf | 2 +- 13 files changed, 46 insertions(+), 13 deletions(-) create mode 100644 src/hal/tinypico.h diff --git a/platformio.ini b/platformio.ini index 4df4cb24..b35fa91e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,6 +28,7 @@ halfile = generic.h ;halfile = wemos32oled.h ;halfile = wemos32matrix.h ;halfile = octopus32.h +;halfile = tinypico.h [platformio] ; upload firmware to board with usb cable @@ -40,7 +41,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.91 +release_version = 1.7.92 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 diff --git a/src/hal/eboxtube.h b/src/hal/eboxtube.h index 9278f0a6..34abe865 100644 --- a/src/hal/eboxtube.h +++ b/src/hal/eboxtube.h @@ -14,7 +14,7 @@ #define CFG_sx1276_radio 1 #define HAS_LED (22) // Green LED on board -#define HAS_RGB_LED (2) // WS2812B RGB LED on board +#define HAS_RGB_LED SmartLed rgb_led(LED_WS2812, 1, GPIO_NUM_2) // WS2812B RGB LED on board #define HAS_BUTTON (0) // button "FLASH" on board #define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature diff --git a/src/hal/fipy.h b/src/hal/fipy.h index c59dff59..f904d716 100644 --- a/src/hal/fipy.h +++ b/src/hal/fipy.h @@ -13,7 +13,7 @@ #define CFG_sx1272_radio 1 #define HAS_LED NOT_A_PIN // FiPy has no on board LED, so we use RGB LED -#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 +#define HAS_RGB_LED SmartLed rgb_led(LED_WS2812, 1, GPIO_NUM_0) // WS2812B RGB LED on GPIO0 #define BOARD_HAS_PSRAM // use extra 4MB extern RAM // Pins for LORA chip SPI interface, reset line and interrupt lines diff --git a/src/hal/generic.h b/src/hal/generic.h index 1579221f..c606e5ba 100644 --- a/src/hal/generic.h +++ b/src/hal/generic.h @@ -51,7 +51,7 @@ #define HAS_LED (21) // on board LED #define HAS_BUTTON (39) // on board button -#define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 +#define HAS_RGB_LED SmartLed rgb_led(LED_WS2812, 1, GPIO_NUM_0) // WS2812B RGB LED on GPIO0 // GPS settings #define HAS_GPS 1 // use on board GPS diff --git a/src/hal/lolin32litelora.h b/src/hal/lolin32litelora.h index 79f9bb6b..11f3f156 100644 --- a/src/hal/lolin32litelora.h +++ b/src/hal/lolin32litelora.h @@ -17,7 +17,7 @@ //#define DISPLAY_FLIP 1 // uncomment this for rotated display #define HAS_LED 22 // ESP32 GPIO12 (pin22) On Board LED #define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW -#define HAS_RGB_LED 13 // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED +#define HAS_RGB_LED SmartLed rgb_led(LED_WS2812, 1, GPIO_NUM_13) // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED #define HAS_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield #define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown diff --git a/src/hal/lolin32lora.h b/src/hal/lolin32lora.h index a6fa2f37..a79b0d84 100644 --- a/src/hal/lolin32lora.h +++ b/src/hal/lolin32lora.h @@ -18,7 +18,7 @@ #define HAS_LED NOT_A_PIN // Led os on same pin as Lora SS pin, to avoid problems, we don't use it #define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW // Anyway shield is on over the LoLin32 board, so we won't be able to see this LED -#define HAS_RGB_LED 13 // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED +#define HAS_RGB_LED SmartLed rgb_led(LED_WS2812, 1, GPIO_NUM_13) // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED #define HAS_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield #define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown diff --git a/src/hal/lopy.h b/src/hal/lopy.h index 4bf50781..733eb603 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -12,7 +12,7 @@ #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1272_radio 1 #define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED -#define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 +#define HAS_RGB_LED SmartLed rgb_led(LED_WS2812, 1, GPIO_NUM_0) // WS2812B RGB LED on GPIO0 (P2) // Note: Pins for LORA chip SPI interface come from board file pins_arduino.h diff --git a/src/hal/lopy4.h b/src/hal/lopy4.h index 321244e4..e0736229 100644 --- a/src/hal/lopy4.h +++ b/src/hal/lopy4.h @@ -20,8 +20,8 @@ //#define SPI_CS GPIO_NUM_36 #define CFG_sx1276_radio 1 -//#define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED -#define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 (P2) +#define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED +#define HAS_RGB_LED SmartLed rgb_led(LED_WS2812, 1, GPIO_NUM_0) // WS2812B RGB LED on GPIO0 (P2) #define BOARD_HAS_PSRAM // use extra 4MB extern RAM // Note: Pins for LORA chip SPI interface come from board file pins_arduino.h diff --git a/src/hal/octopus32.h b/src/hal/octopus32.h index c2bf3735..d245a8c2 100644 --- a/src/hal/octopus32.h +++ b/src/hal/octopus32.h @@ -23,7 +23,7 @@ #define HAS_LED 13 // ESP32 GPIO12 (pin22) On Board LED //#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW -//#define HAS_RGB_LED 13 // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED +//#define HAS_RGB_LED SmartLed rgb_led(LED_WS2812, 1, GPIO_NUM_13) // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED //#define HAS_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield //#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown diff --git a/src/hal/tinypico.h b/src/hal/tinypico.h new file mode 100644 index 00000000..415f793d --- /dev/null +++ b/src/hal/tinypico.h @@ -0,0 +1,24 @@ +// clang-format off +// upload_speed 921600 +// board esp32dev + + +#ifndef _TINYPICO_H +#define _TINYPICO_H + +#include + +// Hardware related definitions for crowdsupply tinypico board + +#define HAS_LED NOT_A_PIN // Green LED on board +#define HAS_RGB_LED Apa102 rgb_led(1, GPIO_NUM_12, GPIO_NUM_2) // APA102 RGB LED on board + +//#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature +#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 +#define BAT_VOLTAGE_DIVIDER 2.7625f // voltage divider 160k/442k on board +#define BOARD_HAS_PSRAM // use extra 4MB external RAM +#define LED_POWER_SW (13) // switches LED power +#define LED_POWER_ON 0 // switch on transistor for LED power +#define LED_POWER_OFF 1 + +#endif \ No newline at end of file diff --git a/src/led.cpp b/src/led.cpp index 624fb7d9..d7925b4e 100644 --- a/src/led.cpp +++ b/src/led.cpp @@ -14,7 +14,7 @@ unsigned long LEDBlinkStarted = 0; // When (in millis() led blink started) #ifdef HAS_RGB_LED // RGB Led instance -SmartLed rgb_led(LED_WS2812, 1, HAS_RGB_LED); +HAS_RGB_LED; float rgb_CalcColor(float p, float q, float t) { if (t < 0.0f) diff --git a/src/main.cpp b/src/main.cpp index c6dae99e..976ad625 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -195,17 +195,25 @@ void setup() { #if (HAS_LED != NOT_A_PIN) pinMode(HAS_LED, OUTPUT); strcat_P(features, " LED"); + +#ifdef LED_POWER_SW + pinMode(LED_POWER_SW, OUTPUT); + digitalWrite(LED_POWER_SW, LED_POWER_ON); +#endif + #ifdef HAS_TWO_LED pinMode(HAS_TWO_LED, OUTPUT); strcat_P(features, " LED1"); #endif + // use LED for power display if we have additional RGB LED, else for status #ifdef HAS_RGB_LED switch_LED(LED_ON); strcat_P(features, " RGB"); rgb_set_color(COLOR_PINK); #endif -#endif + +#endif // HAS_LED #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED) // start led loop diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 30dcedc0..7382d8d8 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -72,7 +72,7 @@ #define TIME_SYNC_INTERVAL_RETRY 10 // retry time sync after lost sync each .. minutes [default = 10], 0 means off #define TIME_SYNC_COMPILEDATE 0 // set to 1 to use compile date to initialize RTC after power outage [default = 0] #define TIME_SYNC_LORAWAN 0 // set to 1 to use LORA network as time source, 0 means off [default = 0] -#define TIME_SYNC_LORASERVER 1 // set to 1 to use LORA timeserver as time source, 0 means off [default = 0] +#define TIME_SYNC_LORASERVER 0 // set to 1 to use LORA timeserver as time source, 0 means off [default = 0] // settings for syncing time with timeserver applications #define TIME_SYNC_SAMPLES 1 // number of time requests for averaging From 49a6714dbc90df29c39bab6513214d62b9dd45ae Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 14 Aug 2019 21:54:12 +0200 Subject: [PATCH 005/105] readme.md updated --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a9f2ebed..d8956b0a 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ LoLin32lite + [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-L - Pyom: WiPy - WeMos: LoLin32, LoLin32 Lite, WeMos D32, [Wemos32 Oled](https://www.instructables.com/id/ESP32-With-Integrated-OLED-WEMOSLolin-Getting-Star/) +- Crowdsupply: [TinyPICO](https://www.crowdsupply.com/unexpected-maker/tinypico) - Generic ESP32 Depending on board hardware following features are supported: From 267d04488b1f2209a4129ff9550f683850444033 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Thu, 15 Aug 2019 12:02:03 +0200 Subject: [PATCH 006/105] added tinypicomatrix.h --- src/hal/tinypicomatrix.h | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/hal/tinypicomatrix.h diff --git a/src/hal/tinypicomatrix.h b/src/hal/tinypicomatrix.h new file mode 100644 index 00000000..c24c8059 --- /dev/null +++ b/src/hal/tinypicomatrix.h @@ -0,0 +1,46 @@ +// clang-format off +// upload_speed 921600 +// board esp32dev + + +#ifndef _TINYPICO_H +#define _TINYPICO_H + +#include + +// Hardware related definitions for crowdsupply tinypico board +// for operating a 96x16 shift register LED matrix display + +#define HAS_LED NOT_A_PIN // Green LED on board +#define HAS_RGB_LED Apa102 rgb_led(1, GPIO_NUM_12, GPIO_NUM_2) // APA102 RGB LED on board + +//#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature +#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 +#define BAT_VOLTAGE_DIVIDER 2.7625f // voltage divider 160k/442k on board +#define BOARD_HAS_PSRAM // use extra 4MB external RAM +#define LED_POWER_SW (13) // switches LED power +#define LED_POWER_ON 0 // switch on transistor for LED power +#define LED_POWER_OFF 1 + +// LED Matrix display settings +#define HAS_MATRIX_DISPLAY 1 // Uncomment to enable LED matrix display output +#define LED_MATRIX_WIDTH 64 // Width in pixels (LEDs) of your display +#define LED_MATRIX_HEIGHT 16 // Height in pixels (LEDs ) of your display + +// Explanation of pin signals see https://learn.adafruit.com/32x16-32x32-rgb-led-matrix/new-wiring +#define MATRIX_DISPLAY_SCAN_US 500 // Matrix display scan rate in microseconds (1ms is about 'acceptable') +#define LED_MATRIX_LATCHPIN 32 // LAT (or STB = Strobe) +#define LED_MATRIX_CLOCKPIN 33 // CLK +#define LED_MATRIX_EN_74138 21 // EN (or OE) +#define LED_MATRIX_LA_74138 23 // LA (or A) +#define LED_MATRIX_LB_74138 19 // LB (or B) +#define LED_MATRIX_LC_74138 18 // LC (or C) +#define LED_MATRIX_LD_74138 5 // LD (or D) +#define LED_MATRIX_DATA_R1 22 // R1 (or R0) + +// CLK: The clock signal moves the data bits from pin R1 ("red") in the shift registers +// LAT: The latch signal enables LEDs according to the shift register's contents +// Line Selects: LA, LB, LC, LD select which rows of the display are currently lit (0 .. 15) +// OE: Output enable switches the LEDs on/off while transitioning from one row to the next + +#endif \ No newline at end of file From d332a17b2872a771479f3d2b7d8ebd5c909206a7 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 17 Aug 2019 18:30:45 +0200 Subject: [PATCH 007/105] added ledmatrix footfall line diagram --- src/ledmatrixdisplay.cpp | 50 ++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/ledmatrixdisplay.cpp b/src/ledmatrixdisplay.cpp index 3cfe31f2..14e0008c 100644 --- a/src/ledmatrixdisplay.cpp +++ b/src/ledmatrixdisplay.cpp @@ -2,7 +2,8 @@ #include "globals.h" -#define NUMCHARS 5 +#define NUMROWS 16 +#define NUMCOLS 96 #define MATRIX_DISPLAY_PAGES (2) // number of display pages // local Tag for logging @@ -17,7 +18,7 @@ LEDMatrix matrix(LED_MATRIX_LA_74138, LED_MATRIX_LB_74138, LED_MATRIX_LC_74138, LED_MATRIX_LATCHPIN, LED_MATRIX_CLOCKPIN); // Display Buffer 128 = 64 * 16 / 8 -uint8_t displaybuf[LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT / NUMCHARS]; +uint8_t displaybuf[LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT / 8]; // --- SELECT YOUR FONT HERE --- const FONT_INFO *ActiveFontInfo = &digital7_18ptFontInfo; @@ -34,11 +35,11 @@ void init_matrix_display(bool reverse) { if (reverse) matrix.reverse(); matrix.clear(); - DrawNumber(String("0")); + matrix.drawPoint(0, NUMROWS - 1, 1); } // init_display void refreshTheMatrixDisplay(bool nextPage) { - static uint8_t DisplayPage = 0; + static uint8_t DisplayPage = 0, col = 0, row = 0; char buff[16]; // if Matrixdisplay is switched off we don't refresh it to relax cpu @@ -54,19 +55,48 @@ void refreshTheMatrixDisplay(bool nextPage) { DisplayPage = (DisplayPage >= MATRIX_DISPLAY_PAGES - 1) ? 0 : (DisplayPage + 1); matrix.clear(); + col = 0; } switch (DisplayPage % MATRIX_DISPLAY_PAGES) { - // page 0: pax - // page 1: time + // page 0: number of current pax OR footfall line diagram + // page 1: time of day case 0: - if (ulLastNumMacs != macs.size()) { - ulLastNumMacs = macs.size(); - matrix.clear(); - DrawNumber(String(ulLastNumMacs)); + if (cfg.countermode == 1) + + { // cumulative counter mode -> display total number of pax + if (ulLastNumMacs != macs.size()) { + ulLastNumMacs = macs.size(); + matrix.clear(); + DrawNumber(String(ulLastNumMacs)); + } + } + + else { // cyclic counter mode -> plot a line diagram + + if (ulLastNumMacs != macs.size()) { + + // next count cycle? + if (macs.size() == 0) { + col++; + // display full? + if (col >= NUMCOLS) { + col = 0; + matrix.clear(); + } + } else { + // clear previous dot + matrix.drawPoint(col, row, 0); + } + + // set current dot + ulLastNumMacs = macs.size(); + row = NUMROWS - 1 - (ulLastNumMacs / 2) % NUMROWS; + matrix.drawPoint(col, row, 1); + } } break; From 15b53596509e06a97e4d0c4f6af814aff920dd6e Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 17 Aug 2019 18:31:45 +0200 Subject: [PATCH 008/105] platformio.ini: added tinypicomatrix --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index b35fa91e..2afbf626 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,6 +29,7 @@ halfile = generic.h ;halfile = wemos32matrix.h ;halfile = octopus32.h ;halfile = tinypico.h +;halfile = tinypicomatrix.h [platformio] ; upload firmware to board with usb cable From 77352b832e0fd8cfa4254d045e04baf3dd60ba1b Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 17 Aug 2019 18:45:00 +0200 Subject: [PATCH 009/105] ledmatrix scale factor --- src/ledmatrixdisplay.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ledmatrixdisplay.cpp b/src/ledmatrixdisplay.cpp index 14e0008c..5c8fef39 100644 --- a/src/ledmatrixdisplay.cpp +++ b/src/ledmatrixdisplay.cpp @@ -5,6 +5,7 @@ #define NUMROWS 16 #define NUMCOLS 96 #define MATRIX_DISPLAY_PAGES (2) // number of display pages +#define LINE_DIAGRAM_DIVIDER (2) // scales pax numbers to led rows // local Tag for logging static const char TAG[] = __FILE__; @@ -94,7 +95,7 @@ void refreshTheMatrixDisplay(bool nextPage) { // set current dot ulLastNumMacs = macs.size(); - row = NUMROWS - 1 - (ulLastNumMacs / 2) % NUMROWS; + row = NUMROWS - 1 - ((ulLastNumMacs / LINE_DIAGRAM_DIVIDER) % NUMROWS); matrix.drawPoint(col, row, 1); } } From a4419ab6f08e830492eca28d2efdab9e0e4d49ed Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 16:47:28 +0200 Subject: [PATCH 010/105] LED matrix scroll function added --- include/ledmatrixdisplay.h | 1 + src/ledmatrixdisplay.cpp | 39 +++++++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/include/ledmatrixdisplay.h b/include/ledmatrixdisplay.h index 9adfcd11..5c3dca0d 100644 --- a/include/ledmatrixdisplay.h +++ b/include/ledmatrixdisplay.h @@ -13,5 +13,6 @@ void refreshTheMatrixDisplay(bool nextPage = false); void DrawNumber(String strNum, uint8_t iDotPos = 0); uint8_t GetCharFromFont(char cChar); uint8_t GetCharWidth(char cChar); +void ShiftLeft(uint8_t *arr, uint32_t len); #endif \ No newline at end of file diff --git a/src/ledmatrixdisplay.cpp b/src/ledmatrixdisplay.cpp index 5c8fef39..b9af6ec5 100644 --- a/src/ledmatrixdisplay.cpp +++ b/src/ledmatrixdisplay.cpp @@ -14,13 +14,14 @@ uint8_t MatrixDisplayIsOn = 0; static unsigned long ulLastNumMacs = 0; static time_t ulLastTime = myTZ.toLocal(now()); +// Display Buffer 128 = 64 * 16 / 8 +static const uint32_t DisplaySize = LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT / 8; +uint8_t displaybuf[DisplaySize] = {0}; + LEDMatrix matrix(LED_MATRIX_LA_74138, LED_MATRIX_LB_74138, LED_MATRIX_LC_74138, LED_MATRIX_LD_74138, LED_MATRIX_EN_74138, LED_MATRIX_DATA_R1, LED_MATRIX_LATCHPIN, LED_MATRIX_CLOCKPIN); -// Display Buffer 128 = 64 * 16 / 8 -uint8_t displaybuf[LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT / 8]; - // --- SELECT YOUR FONT HERE --- const FONT_INFO *ActiveFontInfo = &digital7_18ptFontInfo; // const FONT_INFO *ActiveFontInfo = &arialNarrow_17ptFontInfo; @@ -41,6 +42,7 @@ void init_matrix_display(bool reverse) { void refreshTheMatrixDisplay(bool nextPage) { static uint8_t DisplayPage = 0, col = 0, row = 0; + uint8_t level; char buff[16]; // if Matrixdisplay is switched off we don't refresh it to relax cpu @@ -82,20 +84,20 @@ void refreshTheMatrixDisplay(bool nextPage) { // next count cycle? if (macs.size() == 0) { - col++; - // display full? - if (col >= NUMCOLS) { - col = 0; - matrix.clear(); - } - } else { - // clear previous dot - matrix.drawPoint(col, row, 0); - } - // set current dot + // matrix full? then scroll left 1 dot, else increment column + if (col < NUMCOLS - 1) + col++; + else + ShiftLeft(displaybuf, DisplaySize); + + } else + matrix.drawPoint(col, row, 0); // clear current dot + + // scale and set new dot ulLastNumMacs = macs.size(); - row = NUMROWS - 1 - ((ulLastNumMacs / LINE_DIAGRAM_DIVIDER) % NUMROWS); + level = ulLastNumMacs / LINE_DIAGRAM_DIVIDER; + row = level <= NUMROWS ? NUMROWS - 1 - level % NUMROWS : 0; matrix.drawPoint(col, row, 1); } } @@ -195,4 +197,11 @@ uint8_t GetCharWidth(char cChar) { return CharDescriptor.width; } +void ShiftLeft(uint8_t *arr, uint32_t len) { + uint32_t i; + for (i = 0; i < len - 1; ++i) { + arr[i] = (arr[i] << 1) | ((arr[i + 1] >> 31) & 1); + } + arr[len - 1] = arr[len - 1] << 1; +} #endif // HAS_MATRIX_DISPLAY \ No newline at end of file From 381286331f628621f60a41f0dfe6860922f18c2e Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 16:55:43 +0200 Subject: [PATCH 011/105] LED matrix on/off added --- src/ledmatrixdisplay.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ledmatrixdisplay.cpp b/src/ledmatrixdisplay.cpp index b9af6ec5..6c22fd23 100644 --- a/src/ledmatrixdisplay.cpp +++ b/src/ledmatrixdisplay.cpp @@ -34,6 +34,12 @@ const FONT_CHAR_INFO *ActiveFontCharInfo = ActiveFontInfo->Descriptors; void init_matrix_display(bool reverse) { ESP_LOGI(TAG, "Initializing LED Matrix display"); matrix.begin(displaybuf, LED_MATRIX_WIDTH, LED_MATRIX_HEIGHT); + + if (MatrixDisplayIsOn) + matrix.on(); + else + matrix.off(); + if (reverse) matrix.reverse(); matrix.clear(); @@ -52,6 +58,10 @@ void refreshTheMatrixDisplay(bool nextPage) { // set display on/off according to current device configuration if (MatrixDisplayIsOn != cfg.screenon) { MatrixDisplayIsOn = cfg.screenon; + if (MatrixDisplayIsOn) + matrix.on(); + else + matrix.off(); } if (nextPage) { From 1d8969f645361e60c5ef250358be6ee7b1edadb3 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 16:58:29 +0200 Subject: [PATCH 012/105] ledmatrixdisplay.cpp code sanitizations --- src/ledmatrixdisplay.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/ledmatrixdisplay.cpp b/src/ledmatrixdisplay.cpp index 6c22fd23..a92f4cf9 100644 --- a/src/ledmatrixdisplay.cpp +++ b/src/ledmatrixdisplay.cpp @@ -10,14 +10,11 @@ // local Tag for logging static const char TAG[] = __FILE__; -uint8_t MatrixDisplayIsOn = 0; +static const uint32_t DisplaySize = LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT / 8; +uint8_t MatrixDisplayIsOn = 0, displaybuf[DisplaySize] = {0}; static unsigned long ulLastNumMacs = 0; static time_t ulLastTime = myTZ.toLocal(now()); -// Display Buffer 128 = 64 * 16 / 8 -static const uint32_t DisplaySize = LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT / 8; -uint8_t displaybuf[DisplaySize] = {0}; - LEDMatrix matrix(LED_MATRIX_LA_74138, LED_MATRIX_LB_74138, LED_MATRIX_LC_74138, LED_MATRIX_LD_74138, LED_MATRIX_EN_74138, LED_MATRIX_DATA_R1, LED_MATRIX_LATCHPIN, LED_MATRIX_CLOCKPIN); @@ -214,4 +211,5 @@ void ShiftLeft(uint8_t *arr, uint32_t len) { } arr[len - 1] = arr[len - 1] << 1; } + #endif // HAS_MATRIX_DISPLAY \ No newline at end of file From ba08662323e8615f573b3dadfbdae5e888b3a98b Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 17:04:02 +0200 Subject: [PATCH 013/105] update LED matrix size --- README.md | 2 +- src/ledmatrixdisplay.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d8956b0a..c4993e5b 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Depending on board hardware following features are supported: - Real Time Clock (Maxim DS3231 I2C) - IF482 (serial) and DCF77 (gpio) time telegram generator - Switch external power / battery -- 64x16 pixel LED Matrix display (similar to [this model](https://www.instructables.com/id/64x16-RED-LED-Marquee/), can be ordered on [Aliexpress](https://www.aliexpress.com/item/P3-75-dot-matrix-led-module-3-75mm-high-clear-top1-for-text-display-304-60mm/32616683948.html)) +- LED Matrix display (similar to [this 64x16 model](https://www.instructables.com/id/64x16-RED-LED-Marquee/), can be ordered on [Aliexpress](https://www.aliexpress.com/item/P3-75-dot-matrix-led-module-3-75mm-high-clear-top1-for-text-display-304-60mm/32616683948.html)) Target platform must be selected in [platformio.ini](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/platformio.ini).
Hardware dependent settings (pinout etc.) are stored in board files in /hal directory. If you want to use a ESP32 board which is not yet supported, use hal file generic.h and tailor pin mappings to your needs. Pull requests for new boards welcome.
diff --git a/src/ledmatrixdisplay.cpp b/src/ledmatrixdisplay.cpp index a92f4cf9..c517fdf7 100644 --- a/src/ledmatrixdisplay.cpp +++ b/src/ledmatrixdisplay.cpp @@ -3,7 +3,7 @@ #include "globals.h" #define NUMROWS 16 -#define NUMCOLS 96 +#define NUMCOLS 64 #define MATRIX_DISPLAY_PAGES (2) // number of display pages #define LINE_DIAGRAM_DIVIDER (2) // scales pax numbers to led rows From c0692c38798ccaf72177ed3292b713def075147b Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 17:44:42 +0200 Subject: [PATCH 014/105] gps initial time sync added --- src/gpsread.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gpsread.cpp b/src/gpsread.cpp index 262daf0a..bcefd2a2 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -90,13 +90,12 @@ time_t fetch_gpsTime(uint16_t *msec) { // poll NMEA $GPZDA sentence #ifdef GPS_SERIAL GPS_Serial.print(ZDA_Request); + // wait for gps NMEA answer + vTaskDelay(tx_Ticks(NMEA_FRAME_SIZE, GPS_SERIAL)); #elif defined GPS_I2C Wire.print(ZDA_Request); #endif - // wait for gps NMEA answer - //vTaskDelay(tx_Ticks(NMEA_FRAME_SIZE, GPS_SERIAL)); - // did we get a current time? if (gpstime.isUpdated() && gpstime.isValid()) { @@ -104,7 +103,8 @@ time_t fetch_gpsTime(uint16_t *msec) { String rawtime = gpstime.value(); uint32_t time_bcd = rawtime.toFloat() * 100; - uint32_t delay_ms = gpstime.age() + nmea_txDelay_ms + NMEA_COMPENSATION_FACTOR; + uint32_t delay_ms = + gpstime.age() + nmea_txDelay_ms + NMEA_COMPENSATION_FACTOR; uint8_t year = CalendarYrToTm(gps.date.year()); // year offset from 1970 in microTime.h From 1de9a0bcd2b4e127a8ea15508b6c25277cd545d8 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 17:45:16 +0200 Subject: [PATCH 015/105] remove arduino loop task --- src/main.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 976ad625..087bf867 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -427,12 +427,10 @@ void setup() { #warning you did not specify a time source, time will not be synched #endif -/* // initialize gps time #if (HAS_GPS) fetch_gpsTime(); #endif -*/ #if (defined HAS_IF482 || defined HAS_DCF77) ESP_LOGI(TAG, "Starting Clock Controller..."); @@ -452,15 +450,8 @@ void setup() { // show compiled features ESP_LOGI(TAG, "Features:%s", features); + vTaskDelete(NULL); + } // setup() -void loop() { - - while (1) { -#if (HAS_LORA) - os_runloop_once(); // execute lmic scheduled jobs and events -#else - delay(2); // yield to CPU -#endif - } -} +void loop() { vTaskDelete(NULL); } From 0a970f3dcf095061e160ca9086efc85f29bbb6e1 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 17:46:10 +0200 Subject: [PATCH 016/105] v1.7.93 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 2afbf626..33c863ce 100644 --- a/platformio.ini +++ b/platformio.ini @@ -42,7 +42,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.92 +release_version = 1.7.93 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 From a381f3124486290b85f05a82323ee13d009b56d8 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 22:13:42 +0200 Subject: [PATCH 017/105] timekeeper.cpp: setmytime return if no timesrc --- src/timekeeper.cpp | 6 +++++- src/timesync.cpp | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/timekeeper.cpp b/src/timekeeper.cpp index 16236de0..85f62864 100644 --- a/src/timekeeper.cpp +++ b/src/timekeeper.cpp @@ -54,7 +54,7 @@ void calibrateTime(void) { } #endif -goto finish; + goto finish; finish: @@ -66,6 +66,10 @@ finish: void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) { + // called with invalid timesource? + if (mytimesource == _unsynced) + return; + // increment t_sec only if t_msec > 1000 time_t time_to_set = (time_t)(t_sec + t_msec / 1000); diff --git a/src/timesync.cpp b/src/timesync.cpp index b1814538..b44a955a 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -178,7 +178,7 @@ int recv_timesync_ans(uint8_t seq_no, uint8_t buf[], uint8_t buf_len) { // the 5th byte contains the fractional seconds in 2^-8 second steps // (= 1/250th sec), we convert this to ms uint16_t timestamp_msec = 4 * buf[4]; - // pointers to 4 bytes 4 bytes containing UTC seconds since unix epoch, msb + // pointers to 4 bytes containing UTC seconds since unix epoch, msb uint32_t timestamp_sec, *timestamp_ptr; // convert buffer to uint32_t, octet order is big endian From c865c8996c23d374f2106ea8d2d9404fe6986aa2 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 22:14:00 +0200 Subject: [PATCH 018/105] main.cpp: update comments --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 087bf867..eb9398aa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,7 +36,6 @@ timesync_req 1 3 processes realtime time sync requests lmictask 1 2 MCCI LMiC LORAWAN stack irqhandler 1 1 display, timesync, gps, etc. triggered by timers gpsloop 1 1 reads data from GPS via serial or i2c -looptask 1 1 arduino loop (unused) IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator Low priority numbers denote low priority tasks. From 526fc2900c07e6c1e57ee8b299cabd6849d4d008 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 22:14:25 +0200 Subject: [PATCH 019/105] ledmaxtrix: update hal files --- src/hal/tinypicomatrix.h | 4 ++-- src/hal/wemos32matrix.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hal/tinypicomatrix.h b/src/hal/tinypicomatrix.h index c24c8059..73597446 100644 --- a/src/hal/tinypicomatrix.h +++ b/src/hal/tinypicomatrix.h @@ -24,8 +24,8 @@ // LED Matrix display settings #define HAS_MATRIX_DISPLAY 1 // Uncomment to enable LED matrix display output -#define LED_MATRIX_WIDTH 64 // Width in pixels (LEDs) of your display -#define LED_MATRIX_HEIGHT 16 // Height in pixels (LEDs ) of your display +#define LED_MATRIX_WIDTH (32*2) // Width (cols) in pixels (LEDs) of your display, must be 32X +#define LED_MATRIX_HEIGHT (16*1) // Height (rows) in pixels (LEDs) of your display, must be 16X // Explanation of pin signals see https://learn.adafruit.com/32x16-32x32-rgb-led-matrix/new-wiring #define MATRIX_DISPLAY_SCAN_US 500 // Matrix display scan rate in microseconds (1ms is about 'acceptable') diff --git a/src/hal/wemos32matrix.h b/src/hal/wemos32matrix.h index 66935f00..b69ac074 100644 --- a/src/hal/wemos32matrix.h +++ b/src/hal/wemos32matrix.h @@ -11,8 +11,8 @@ // LED Matrix display settings #define HAS_MATRIX_DISPLAY 1 // Uncomment to enable LED matrix display output -#define LED_MATRIX_WIDTH 64 // Width in pixels (LEDs) of your display -#define LED_MATRIX_HEIGHT 16 // Height in pixels (LEDs ) of your display +#define LED_MATRIX_WIDTH (32*2) // Width (cols) in pixels (LEDs) of your display, must be 32X +#define LED_MATRIX_HEIGHT (16*1) // Height (rows) in pixels (LEDs) of your display, must be 16X // Pin numbers work fine for Wemos Lolin32 board (all used pins are on 1 side of the board) // Explanation of pin signals see https://learn.adafruit.com/32x16-32x32-rgb-led-matrix/new-wiring From 012bf545c4fe8362d095316a8e57018e233e195d Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 18 Aug 2019 22:16:35 +0200 Subject: [PATCH 020/105] ledmatrix: bugfix scrolling --- include/ledmatrixdisplay.h | 2 +- src/ledmatrixdisplay.cpp | 31 ++++++++++++++++++------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/include/ledmatrixdisplay.h b/include/ledmatrixdisplay.h index 5c3dca0d..d5878f71 100644 --- a/include/ledmatrixdisplay.h +++ b/include/ledmatrixdisplay.h @@ -13,6 +13,6 @@ void refreshTheMatrixDisplay(bool nextPage = false); void DrawNumber(String strNum, uint8_t iDotPos = 0); uint8_t GetCharFromFont(char cChar); uint8_t GetCharWidth(char cChar); -void ShiftLeft(uint8_t *arr, uint32_t len); +void ScrollLeft(uint8_t *buf, uint16_t cols, uint16_t rows); #endif \ No newline at end of file diff --git a/src/ledmatrixdisplay.cpp b/src/ledmatrixdisplay.cpp index c517fdf7..ffdad8c0 100644 --- a/src/ledmatrixdisplay.cpp +++ b/src/ledmatrixdisplay.cpp @@ -2,16 +2,14 @@ #include "globals.h" -#define NUMROWS 16 -#define NUMCOLS 64 #define MATRIX_DISPLAY_PAGES (2) // number of display pages #define LINE_DIAGRAM_DIVIDER (2) // scales pax numbers to led rows // local Tag for logging static const char TAG[] = __FILE__; -static const uint32_t DisplaySize = LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT / 8; -uint8_t MatrixDisplayIsOn = 0, displaybuf[DisplaySize] = {0}; +uint8_t MatrixDisplayIsOn = 0; +static uint8_t displaybuf[LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT / 8] = {0}; static unsigned long ulLastNumMacs = 0; static time_t ulLastTime = myTZ.toLocal(now()); @@ -40,7 +38,7 @@ void init_matrix_display(bool reverse) { if (reverse) matrix.reverse(); matrix.clear(); - matrix.drawPoint(0, NUMROWS - 1, 1); + matrix.drawPoint(0, LED_MATRIX_HEIGHT - 1, 1); } // init_display void refreshTheMatrixDisplay(bool nextPage) { @@ -93,10 +91,10 @@ void refreshTheMatrixDisplay(bool nextPage) { if (macs.size() == 0) { // matrix full? then scroll left 1 dot, else increment column - if (col < NUMCOLS - 1) + if (col < (LED_MATRIX_WIDTH - 1)) col++; else - ShiftLeft(displaybuf, DisplaySize); + ScrollLeft(displaybuf, LED_MATRIX_WIDTH, LED_MATRIX_HEIGHT); } else matrix.drawPoint(col, row, 0); // clear current dot @@ -104,7 +102,9 @@ void refreshTheMatrixDisplay(bool nextPage) { // scale and set new dot ulLastNumMacs = macs.size(); level = ulLastNumMacs / LINE_DIAGRAM_DIVIDER; - row = level <= NUMROWS ? NUMROWS - 1 - level % NUMROWS : 0; + row = level <= LED_MATRIX_HEIGHT + ? LED_MATRIX_HEIGHT - 1 - level % LED_MATRIX_HEIGHT + : 0; matrix.drawPoint(col, row, 1); } } @@ -204,12 +204,17 @@ uint8_t GetCharWidth(char cChar) { return CharDescriptor.width; } -void ShiftLeft(uint8_t *arr, uint32_t len) { - uint32_t i; - for (i = 0; i < len - 1; ++i) { - arr[i] = (arr[i] << 1) | ((arr[i + 1] >> 31) & 1); +void ScrollLeft(uint8_t *buf, uint16_t cols, uint16_t rows) { + uint32_t i, k, idx; + + for (k = 0; k < rows; k++) { + // scroll a line with x bytes one dot to the left + for (i = 0; i < cols / 8 - 1; ++i) { + idx = i + k * cols / 8; + buf[idx] = (buf[idx] << 1) | ((buf[idx + 1] >> 7) & 1); + } + buf[idx + 1] <<= 1; } - arr[len - 1] = arr[len - 1] << 1; } #endif // HAS_MATRIX_DISPLAY \ No newline at end of file From 43cf6b7fe5968de683f127bf01f96bf8a443e609 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 19 Aug 2019 21:48:11 +0200 Subject: [PATCH 021/105] ledmatrix.cpp small code sanitization --- include/ledmatrixdisplay.h | 2 +- src/ledmatrixdisplay.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/ledmatrixdisplay.h b/include/ledmatrixdisplay.h index d5878f71..b7ec5a3b 100644 --- a/include/ledmatrixdisplay.h +++ b/include/ledmatrixdisplay.h @@ -13,6 +13,6 @@ void refreshTheMatrixDisplay(bool nextPage = false); void DrawNumber(String strNum, uint8_t iDotPos = 0); uint8_t GetCharFromFont(char cChar); uint8_t GetCharWidth(char cChar); -void ScrollLeft(uint8_t *buf, uint16_t cols, uint16_t rows); +void ScrollLeft(uint8_t *buf, const uint16_t cols, const uint16_t rows); #endif \ No newline at end of file diff --git a/src/ledmatrixdisplay.cpp b/src/ledmatrixdisplay.cpp index ffdad8c0..881f57fe 100644 --- a/src/ledmatrixdisplay.cpp +++ b/src/ledmatrixdisplay.cpp @@ -204,13 +204,14 @@ uint8_t GetCharWidth(char cChar) { return CharDescriptor.width; } -void ScrollLeft(uint8_t *buf, uint16_t cols, uint16_t rows) { +void ScrollLeft(uint8_t *buf, const uint16_t cols, const uint16_t rows) { uint32_t i, k, idx; + const uint32_t x = cols / 8; for (k = 0; k < rows; k++) { // scroll a line with x bytes one dot to the left - for (i = 0; i < cols / 8 - 1; ++i) { - idx = i + k * cols / 8; + for (i = 0; i < x - 1; ++i) { + idx = i + k * x; buf[idx] = (buf[idx] << 1) | ((buf[idx + 1] >> 7) & 1); } buf[idx + 1] <<= 1; From bbca15a76e2a11e1dcf093421abf72fc66cae555 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 25 Aug 2019 17:18:29 +0200 Subject: [PATCH 022/105] rcommand.cpp: set payload mask & set BME data --- README.md | 11 ++++++++++- src/bmesensor.cpp | 4 +++- src/rcommand.cpp | 17 ++++++++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c4993e5b..cbdaab95 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ If you're using a device with OLED display, or if you add such one to the I2C bu You can add up to 3 user defined sensors. Insert sensor's payload scheme in [*sensor.cpp*](src/sensor.cpp). Bosch BME280 / BME680 environment sensors are supported. Enable flag *lib_deps_sensors* for your board in [*platformio.ini*](src/platformio.ini) and configure BME in board's hal file before build. If you need Bosch's proprietary BSEC libraray (e.g. to get indoor air quality value from BME680) further enable *build_flags_sensors*, which comes on the price of reduced RAM and increased build size. RTC DS3231, generic serial NMEA GPS, I2C LoPy GPS are supported, and to be configured in board's hal file. See [*generic.h*](src/hal/generic.h) for all options and for proper configuration of BME280/BME680. -Output of user sensor data can be switched by user remote control command 0x13 sent to Port 2. +Output of user sensor data can be switched by user remote control command 0x14 sent to Port 2. Output of sensor and peripheral data is internally switched by a bitmask register. Default mask (0xFF) can be tailored by editing *cfg.payloadmask* initialization value in [*configmanager.cpp*](src/configmanager.cpp) following this scheme: @@ -383,6 +383,15 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. byte 1 = user sensor number (1..3) byte 2 = sensor mode (0 = disabled / 1 = enabled [default]) +0x14 set payload mask + + byte 1 = sensor data payload mask (0..255, meaning of bits see above) + +0x15 set BME data on/off + + 0 = BME data off + 1 = BME data on, sends BME data on port 7 [default] + 0x80 get device configuration Device answers with it's current configuration on Port 3. diff --git a/src/bmesensor.cpp b/src/bmesensor.cpp index 78298798..c6b77fc4 100644 --- a/src/bmesensor.cpp +++ b/src/bmesensor.cpp @@ -143,7 +143,9 @@ int checkIaqSensorStatus(void) { // store current BME sensor data in struct void bme_storedata(bmeStatus_t *bme_store) { - if (I2C_MUTEX_LOCK()) { // block i2c bus access + + if ((cfg.payloadmask && MEMS_DATA) & + (I2C_MUTEX_LOCK())) { // block i2c bus access #ifdef HAS_BME680 if (iaqSensor.run()) { // if new data is available diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 415283a9..be00f21e 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -131,6 +131,20 @@ void set_gps(uint8_t val[]) { } } +void set_bme(uint8_t val[]) { + ESP_LOGI(TAG, "Remote command: set BME mode to %s", val[0] ? "on" : "off"); + if (val[0]) { + cfg.payloadmask |= (uint8_t)MEMS_DATA; // set bit in mask + } else { + cfg.payloadmask &= ~(uint8_t)MEMS_DATA; // clear bit in mask + } +} + +void set_payloadmask(uint8_t val[]) { + ESP_LOGI(TAG, "Remote command: set payload mask to %X", val[0]); + cfg.payloadmask = val[0]; +} + void set_sensor(uint8_t val[]) { #if (HAS_SENSORS) switch (val[0]) { // check if valid sensor number 1...4 @@ -307,7 +321,8 @@ cmd_t table[] = { {0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true}, {0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true}, {0x11, set_monitor, 1, true}, {0x12, set_beacon, 7, false}, - {0x13, set_sensor, 2, true}, {0x80, get_config, 0, false}, + {0x13, set_sensor, 2, true}, {0x14, set_payloadmask, 1, true}, + {0x15, set_bme, 1, true}, {0x80, get_config, 0, false}, {0x81, get_status, 0, false}, {0x84, get_gps, 0, false}, {0x85, get_bme, 0, false}, {0x86, get_time, 0, false}, {0x87, set_time, 0, false}, {0x99, set_flush, 0, false}}; From 829ab0ea0551ead6abf64f37c3c051499bc9b193 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 28 Aug 2019 10:48:39 +0200 Subject: [PATCH 023/105] bugfix message queuing to LMIC while LMIC is busy --- include/globals.h | 7 ++++--- include/lorawan.h | 2 +- include/spislave.h | 2 +- src/lorawan.cpp | 29 +++++++++++++---------------- src/senddata.cpp | 8 +++++--- src/spislave.cpp | 4 +++- 6 files changed, 27 insertions(+), 25 deletions(-) diff --git a/include/globals.h b/include/globals.h index e8e8bb48..a112e481 100644 --- a/include/globals.h +++ b/include/globals.h @@ -45,6 +45,9 @@ #define I2C_MUTEX_LOCK() (xSemaphoreTake(I2Caccess, pdMS_TO_TICKS(10)) == pdTRUE) #define I2C_MUTEX_UNLOCK() (xSemaphoreGive(I2Caccess)) +enum sendprio_t { prio_low, prio_normal, prio_high }; +enum timesource_t { _gps, _rtc, _lora, _unsynced }; + // Struct holding devices's runtime configuration typedef struct { uint8_t lorasf; // 7-12, lora spreadfactor @@ -73,6 +76,7 @@ typedef struct { typedef struct { uint8_t MessageSize; uint8_t MessagePort; + sendprio_t MessagePrio; uint8_t Message[PAYLOAD_BUFFER_SIZE]; } MessageBuffer_t; @@ -95,9 +99,6 @@ typedef struct { float gas; // raw gas sensor signal } bmeStatus_t; -enum sendprio_t { prio_low, prio_normal, prio_high }; -enum timesource_t { _gps, _rtc, _lora, _unsynced }; - extern std::set, Mallocator> macs; extern std::array::iterator it; extern std::array beacons; diff --git a/include/lorawan.h b/include/lorawan.h index b3331751..5762297c 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -35,7 +35,7 @@ void os_getDevEui(u1_t *buf); void showLoraKeys(void); void switch_lora(uint8_t sf, uint8_t tx); void lora_send(osjob_t *job); -void lora_enqueuedata(MessageBuffer_t *message, sendprio_t prio); +void lora_enqueuedata(MessageBuffer_t *message); void lora_queuereset(void); #if (TIME_SYNC_LORAWAN) void user_request_network_time_callback(void *pVoidUserUTCTime, diff --git a/include/spislave.h b/include/spislave.h index 44c58455..0d85a09e 100644 --- a/include/spislave.h +++ b/include/spislave.h @@ -28,7 +28,7 @@ licenses. Refer to LICENSE.txt file in repository for more details. esp_err_t spi_init(); -void spi_enqueuedata(MessageBuffer_t *message, sendprio_t prio); +void spi_enqueuedata(MessageBuffer_t *message); void spi_queuereset(); #endif // _SPISLAVE_H diff --git a/src/lorawan.cpp b/src/lorawan.cpp index e82ac1f5..3974c7f4 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -391,21 +391,16 @@ void switch_lora(uint8_t sf, uint8_t tx) { void lora_send(osjob_t *job) { MessageBuffer_t SendBuffer; - // Check if there is a pending TX/RX job running, if yes don't eat data - // since it cannot be sent right now - if ((LMIC.opmode & (OP_JOINING | OP_REJOIN | OP_TXDATA | OP_POLL)) != 0) { - // waiting for LoRa getting ready - } else { - if (xQueueReceive(LoraSendQueue, &SendBuffer, (TickType_t)0) == pdTRUE) { - // SendBuffer now filled with next payload from queue - if (!LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, - SendBuffer.MessageSize, (cfg.countermode & 0x02))) { - ESP_LOGI(TAG, "%d byte(s) sent to LoRa", SendBuffer.MessageSize); - } else { - ESP_LOGE(TAG, "could not send %d byte(s) to LoRa", - SendBuffer.MessageSize); - } - // sprintf(display_line7, "PACKET QUEUED"); + if (xQueueReceive(LoraSendQueue, &SendBuffer, (TickType_t)0) == pdTRUE) { + // SendBuffer now filled with next payload from queue + if (LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, + SendBuffer.MessageSize, + (cfg.countermode & 0x02)) == 0) { + ESP_LOGI(TAG, "%d byte(s) sent to LoRa", SendBuffer.MessageSize); + } else { + lora_enqueuedata(&SendBuffer); + // ESP_LOGE(TAG, "could not send %d byte(s) to LoRa, rescheduled", + // SendBuffer.MessageSize); } } // reschedule job every 0,5 - 1 sec. including a bit of random to prevent @@ -441,10 +436,12 @@ esp_err_t lora_stack_init() { return ESP_OK; // continue main program } -void lora_enqueuedata(MessageBuffer_t *message, sendprio_t prio) { +void lora_enqueuedata(MessageBuffer_t *message) { // enqueue message in LORA send queue BaseType_t ret; MessageBuffer_t DummyBuffer; + sendprio_t prio = message->MessagePrio; + switch (prio) { case prio_high: // clear space in queue if full, then fallthrough to normal diff --git a/src/senddata.cpp b/src/senddata.cpp index fd5df963..95577b24 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -10,9 +10,11 @@ void sendcycle() { // put data to send in RTos Queues used for transmit over channels Lora and SPI void SendPayload(uint8_t port, sendprio_t prio) { - MessageBuffer_t SendBuffer; // contains MessageSize, MessagePort, Message[] + MessageBuffer_t SendBuffer; // contains MessageSize, MessagePort, MessagePrio, Message[] SendBuffer.MessageSize = payload.getSize(); + SendBuffer.MessagePrio = prio; + switch (PAYLOAD_ENCODER) { case 1: // plain -> no mapping case 2: // packed -> no mapping @@ -42,10 +44,10 @@ void SendPayload(uint8_t port, sendprio_t prio) { // enqueue message in device's send queues #if (HAS_LORA) - lora_enqueuedata(&SendBuffer, prio); + lora_enqueuedata(&SendBuffer); #endif #ifdef HAS_SPI - spi_enqueuedata(&SendBuffer, prio); + spi_enqueuedata(&SendBuffer); #endif } // SendPayload diff --git a/src/spislave.cpp b/src/spislave.cpp index 9801058b..32bad108 100644 --- a/src/spislave.cpp +++ b/src/spislave.cpp @@ -147,10 +147,12 @@ esp_err_t spi_init() { return ret; } -void spi_enqueuedata(MessageBuffer_t *message, sendprio_t prio) { +void spi_enqueuedata(MessageBuffer_t *message) { // enqueue message in SPI send queue BaseType_t ret; MessageBuffer_t DummyBuffer; + sendprio_t prio = message->MessagePrio; + switch (prio) { case prio_high: // clear space in queue if full, then fallthrough to normal From 1c5edbb6a4906ddb1c901d89a9e947e1a6e4ca16 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 28 Aug 2019 10:49:25 +0200 Subject: [PATCH 024/105] esp_wifi_start (needed for next ESP-IDF release) --- src/wifiscan.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 85fdf6a1..12ec9c82 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -57,7 +57,7 @@ void wifi_sniffer_init(void) { wificfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM wificfg.wifi_task_core_id = 0; // we want wifi task running on core 0 - //wifi_promiscuous_filter_t filter = { + // wifi_promiscuous_filter_t filter = { // .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // only MGMT frames // .filter_mask = WIFI_PROMIS_FILTER_MASK_ALL}; // we use all frames @@ -71,9 +71,8 @@ void wifi_sniffer_init(void) { ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL)); - ESP_ERROR_CHECK(esp_wifi_stop()); - ESP_ERROR_CHECK( - esp_wifi_set_promiscuous_filter(&filter)); // set frame filter + ESP_ERROR_CHECK(esp_wifi_start()); // channel switch throws error without + ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter)); // set frame filter ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler)); ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode From 78c8ed3e9753df51ecbb6bed4a8fdddca1428ee0 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 28 Aug 2019 21:55:50 +0200 Subject: [PATCH 025/105] refactoring LMIC send queueing --- src/lorawan.cpp | 47 ++++++++++++++++++++++++++++------------------- src/senddata.cpp | 2 +- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 3974c7f4..fefb5db0 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -248,6 +248,11 @@ void onEvent(ev_t ev) { : PSTR("TX COMPLETE")); sprintf(display_line6, " "); // clear previous lmic status + // schedule next transmission with some random delay to prevent systematic + // collisions + os_setTimedCallback(&sendjob, os_getTime() + ms2osticks(random(500)), + lora_send); + if (LMIC.dataLen) { // did we receive payload data -> display info ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", LMIC.dataLen, LMIC.rssi, LMIC.snr / 4); @@ -391,22 +396,22 @@ void switch_lora(uint8_t sf, uint8_t tx) { void lora_send(osjob_t *job) { MessageBuffer_t SendBuffer; - if (xQueueReceive(LoraSendQueue, &SendBuffer, (TickType_t)0) == pdTRUE) { - // SendBuffer now filled with next payload from queue - if (LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, - SendBuffer.MessageSize, - (cfg.countermode & 0x02)) == 0) { - ESP_LOGI(TAG, "%d byte(s) sent to LoRa", SendBuffer.MessageSize); - } else { - lora_enqueuedata(&SendBuffer); - // ESP_LOGE(TAG, "could not send %d byte(s) to LoRa, rescheduled", - // SendBuffer.MessageSize); - } + + // Check if there is not a current TX/RX job running + if (LMIC.opmode & OP_TXRXPEND) { + ESP_LOGE(TAG, "LMIC busy, data not sent and lost"); + return; + } + + // fetch next payload to send from queue or wait until new payload shows up in + // queue + if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) == pdTRUE) { + if (LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, + SendBuffer.MessageSize, (cfg.countermode & 0x02)) == 0) + ESP_LOGI(TAG, "%d byte(s) delivered to LMIC", SendBuffer.MessageSize); + else + lora_enqueuedata(&SendBuffer); // re-enqueue unsent message } - // reschedule job every 0,5 - 1 sec. including a bit of random to prevent - // systematic collisions - os_setTimedCallback(job, os_getTime() + 500 + ms2osticks(random(500)), - lora_send); } esp_err_t lora_stack_init() { @@ -438,15 +443,17 @@ esp_err_t lora_stack_init() { void lora_enqueuedata(MessageBuffer_t *message) { // enqueue message in LORA send queue - BaseType_t ret; + BaseType_t ret = pdFALSE; MessageBuffer_t DummyBuffer; sendprio_t prio = message->MessagePrio; switch (prio) { case prio_high: - // clear space in queue if full, then fallthrough to normal - if (uxQueueSpacesAvailable(LoraSendQueue) == 0) + // clear some space in queue if full, then fallthrough to prio_normal + if (uxQueueSpacesAvailable(LoraSendQueue) == 0) { xQueueReceive(LoraSendQueue, &DummyBuffer, (TickType_t)0); + ESP_LOGW(TAG, "LORA sendqueue purged, data is lost"); + } case prio_normal: ret = xQueueSendToFront(LoraSendQueue, (void *)message, (TickType_t)0); break; @@ -455,7 +462,9 @@ void lora_enqueuedata(MessageBuffer_t *message) { ret = xQueueSendToBack(LoraSendQueue, (void *)message, (TickType_t)0); break; } - if (ret != pdTRUE) + if (ret == pdTRUE) + ESP_LOGD(TAG, "LORA sendqueue data enqueued"); + else ESP_LOGW(TAG, "LORA sendqueue is full"); } diff --git a/src/senddata.cpp b/src/senddata.cpp index 95577b24..65d656c5 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -40,7 +40,7 @@ void SendPayload(uint8_t port, sendprio_t prio) { default: SendBuffer.MessagePort = port; } - memcpy(SendBuffer.Message, payload.getBuffer(), payload.getSize()); + memcpy(SendBuffer.Message, payload.getBuffer(), SendBuffer.MessageSize); // enqueue message in device's send queues #if (HAS_LORA) From 9e42de67bdca5e5094fd1694dd3d18afb990297b Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 28 Aug 2019 22:04:24 +0200 Subject: [PATCH 026/105] v1.7.974 --- platformio.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index 33c863ce..75905821 100644 --- a/platformio.ini +++ b/platformio.ini @@ -42,7 +42,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.93 +release_version = 1.7.974 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 @@ -61,7 +61,7 @@ lib_deps_display = lib_deps_matrix_display = https://github.com/Seeed-Studio/Ultrathin_LED_Matrix.git lib_deps_rgbled = - SmartLeds@>=1.1.5 + SmartLeds@>=1.1.6 lib_deps_gps = 1655@>=1.0.2 ;TinyGPSPlus by Mikal Hart lib_deps_sensors = @@ -114,7 +114,7 @@ upload_protocol = custom upload_protocol = esptool [env:dev] -upload_protocol = esptool +upload_protocol = custom build_type = debug platform = https://github.com/platformio/platform-espressif32.git#develop platform_packages = From 258e830470ec2439329608315ca6c446ee862cc2 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Thu, 29 Aug 2019 10:13:47 +0200 Subject: [PATCH 027/105] move lmic os sendjob to new lora_send task --- include/lorawan.h | 2 +- src/lorawan.cpp | 51 ++++++++++++++++++++++++++--------------------- src/main.cpp | 1 + 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/lorawan.h b/include/lorawan.h index 5762297c..0010f9de 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -34,7 +34,7 @@ void os_getArtEui(u1_t *buf); void os_getDevEui(u1_t *buf); void showLoraKeys(void); void switch_lora(uint8_t sf, uint8_t tx); -void lora_send(osjob_t *job); +void lora_send(void *pvParameters); void lora_enqueuedata(MessageBuffer_t *message); void lora_queuereset(void); #if (TIME_SYNC_LORAWAN) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index fefb5db0..67fb175b 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -18,9 +18,8 @@ static const char TAG[] = "lora"; #endif #endif -osjob_t sendjob; QueueHandle_t LoraSendQueue; -TaskHandle_t lmicTask = NULL; +TaskHandle_t lmicTask = NULL, lorasendTask = NULL; class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t { @@ -218,8 +217,6 @@ void onEvent(ev_t ev) { // Set data rate and transmit power (note: txpower seems to be ignored by // the library) switch_lora(cfg.lorasf, cfg.txpower); - // kickoff first send job - os_setCallback(&sendjob, lora_send); // show effective LoRa parameters after join ESP_LOGI(TAG, "DEVaddr=%08X", LMIC.devaddr); break; @@ -248,11 +245,6 @@ void onEvent(ev_t ev) { : PSTR("TX COMPLETE")); sprintf(display_line6, " "); // clear previous lmic status - // schedule next transmission with some random delay to prevent systematic - // collisions - os_setTimedCallback(&sendjob, os_getTime() + ms2osticks(random(500)), - lora_send); - if (LMIC.dataLen) { // did we receive payload data -> display info ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", LMIC.dataLen, LMIC.rssi, LMIC.snr / 4); @@ -394,23 +386,27 @@ void switch_lora(uint8_t sf, uint8_t tx) { } } -void lora_send(osjob_t *job) { +// LMIC send task +void lora_send(void *pvParameters) { + configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check + MessageBuffer_t SendBuffer; - // Check if there is not a current TX/RX job running - if (LMIC.opmode & OP_TXRXPEND) { - ESP_LOGE(TAG, "LMIC busy, data not sent and lost"); - return; - } + while (1) { + // fetch next / wait for payload to send from queue + if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) == pdTRUE) { - // fetch next payload to send from queue or wait until new payload shows up in - // queue - if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) == pdTRUE) { - if (LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, - SendBuffer.MessageSize, (cfg.countermode & 0x02)) == 0) - ESP_LOGI(TAG, "%d byte(s) delivered to LMIC", SendBuffer.MessageSize); - else - lora_enqueuedata(&SendBuffer); // re-enqueue unsent message + // Check if there is not a current TX/RX job running + if (LMIC.opmode & OP_TXRXPEND) + lora_enqueuedata(&SendBuffer); // LMIC stack busy + else if (LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, + SendBuffer.MessageSize, + (cfg.countermode & 0x02)) == 0) + ESP_LOGI(TAG, "%d byte(s) delivered to LMIC", SendBuffer.MessageSize); + else + lora_enqueuedata(&SendBuffer); // LMIC stack denied tx + } + delay(2); // yield to CPU } } @@ -434,6 +430,15 @@ esp_err_t lora_stack_init() { &lmicTask, // task handle 1); // CPU core + // starting lmic send task + xTaskCreatePinnedToCore(lora_send, // task function + "lorasendtask", // name of task + 2048, // stack size of task + (void *)1, // parameter of the task + 2, // priority of the task + &lorasendTask, // task handle + 1); // CPU core + if (!LMIC_startJoining()) { // start joining ESP_LOGI(TAG, "Already joined"); } diff --git a/src/main.cpp b/src/main.cpp index eb9398aa..f042165f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,6 +36,7 @@ timesync_req 1 3 processes realtime time sync requests lmictask 1 2 MCCI LMiC LORAWAN stack irqhandler 1 1 display, timesync, gps, etc. triggered by timers gpsloop 1 1 reads data from GPS via serial or i2c +lorasendtask 1 1 feed data from lora sendqueue to lmcic IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator Low priority numbers denote low priority tasks. From c97140d822315dc49e39054f153b3e5ba1568959 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Thu, 29 Aug 2019 10:15:11 +0200 Subject: [PATCH 028/105] remove TX TIMESYNC event display --- src/lorawan.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 67fb175b..1a509380 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -305,13 +305,7 @@ void onEvent(ev_t ev) { case EV_TXSTART: if (!(LMIC.opmode & OP_JOINING)) { -#if (TIME_SYNC_LORASERVER) - // if last packet sent was a timesync request, store TX time - if (LMIC.pendTxPort == TIMEPORT) - strcpy_P(buff, PSTR("TX TIMESYNC")); - else -#endif - strcpy_P(buff, PSTR("TX START")); + strcpy_P(buff, PSTR("TX START")); } break; From 1cf12452bac572f061856ae106b8ee4649ae4ef0 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Thu, 29 Aug 2019 20:23:22 +0200 Subject: [PATCH 029/105] lorawan.cpp code sanitizations --- src/lorawan.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 1a509380..bbf8b0a6 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -387,18 +387,17 @@ void lora_send(void *pvParameters) { MessageBuffer_t SendBuffer; while (1) { - // fetch next / wait for payload to send from queue + // fetch next or wait for payload to send from queue if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) == pdTRUE) { - // Check if there is not a current TX/RX job running - if (LMIC.opmode & OP_TXRXPEND) - lora_enqueuedata(&SendBuffer); // LMIC stack busy + if (LMIC.opmode & OP_TXRXPEND) // LMIC is busy, we can't send... + lora_enqueuedata(&SendBuffer); // ...so we re-enqueue the message else if (LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, SendBuffer.MessageSize, (cfg.countermode & 0x02)) == 0) ESP_LOGI(TAG, "%d byte(s) delivered to LMIC", SendBuffer.MessageSize); - else - lora_enqueuedata(&SendBuffer); // LMIC stack denied tx + else // LMIC stack denied tx ... + lora_enqueuedata(&SendBuffer); // ...so we re-enqueue the message } delay(2); // yield to CPU } @@ -414,7 +413,7 @@ esp_err_t lora_stack_init() { ESP_LOGI(TAG, "LORA send queue created, size %d Bytes", SEND_QUEUE_SIZE * sizeof(MessageBuffer_t)); - // starting lorawan stack + // start lorawan stack ESP_LOGI(TAG, "Starting LMIC..."); xTaskCreatePinnedToCore(lmictask, // task function "lmictask", // name of task @@ -424,12 +423,12 @@ esp_err_t lora_stack_init() { &lmicTask, // task handle 1); // CPU core - // starting lmic send task + // start lmic send task xTaskCreatePinnedToCore(lora_send, // task function "lorasendtask", // name of task 2048, // stack size of task (void *)1, // parameter of the task - 2, // priority of the task + 1, // priority of the task &lorasendTask, // task handle 1); // CPU core @@ -437,7 +436,7 @@ esp_err_t lora_stack_init() { ESP_LOGI(TAG, "Already joined"); } - return ESP_OK; // continue main program + return ESP_OK; } void lora_enqueuedata(MessageBuffer_t *message) { From 63ff668a9663416d924722aadeb6a71b47c5882b Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 30 Aug 2019 14:06:30 +0200 Subject: [PATCH 030/105] LMIC message queuing refactored --- src/lorawan.cpp | 52 +++++++++++++++++++++++++++++++++--------------- src/spislave.cpp | 2 +- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index bbf8b0a6..ebf3707c 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -387,17 +387,39 @@ void lora_send(void *pvParameters) { MessageBuffer_t SendBuffer; while (1) { - // fetch next or wait for payload to send from queue - if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) == pdTRUE) { - if (LMIC.opmode & OP_TXRXPEND) // LMIC is busy, we can't send... - lora_enqueuedata(&SendBuffer); // ...so we re-enqueue the message - else if (LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, - SendBuffer.MessageSize, - (cfg.countermode & 0x02)) == 0) + // wait until we are joined if we are not + while (!LMIC.devaddr) { + vTaskDelay(pdMS_TO_TICKS(500)); + } + + // fetch next or wait for payload to send from queue + if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) != pdTRUE) { + ESP_LOGE(TAG, "Premature return from xQueueReceive() with no data!"); + continue; + } + + // attempt to transmit payload + else { + + switch (LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, + SendBuffer.MessageSize, + (cfg.countermode & 0x02))) { + case 0: ESP_LOGI(TAG, "%d byte(s) delivered to LMIC", SendBuffer.MessageSize); - else // LMIC stack denied tx ... - lora_enqueuedata(&SendBuffer); // ...so we re-enqueue the message + break; + case -1: // LMIC already has a tx message pending + ESP_LOGD(TAG, "LMIC busy, message re-enqueued"); + vTaskDelay(pdMS_TO_TICKS(1000 + random(500))); // wait a while + lora_enqueuedata(&SendBuffer); // re-enqueue the undeliverd message + break; + case -2: // message size exceeds LMIC buffer size + ESP_LOGW(TAG, "Message size exceeds LMIC buffer, message deleted"); + break; + default: // unknown LMIC return code + ESP_LOGE(TAG, "Unknown LMIC error, message deleted"); + + } // switch } delay(2); // yield to CPU } @@ -423,6 +445,10 @@ esp_err_t lora_stack_init() { &lmicTask, // task handle 1); // CPU core + if (!LMIC_startJoining()) { // start joining + ESP_LOGI(TAG, "Already joined"); + } + // start lmic send task xTaskCreatePinnedToCore(lora_send, // task function "lorasendtask", // name of task @@ -432,10 +458,6 @@ esp_err_t lora_stack_init() { &lorasendTask, // task handle 1); // CPU core - if (!LMIC_startJoining()) { // start joining - ESP_LOGI(TAG, "Already joined"); - } - return ESP_OK; } @@ -460,9 +482,7 @@ void lora_enqueuedata(MessageBuffer_t *message) { ret = xQueueSendToBack(LoraSendQueue, (void *)message, (TickType_t)0); break; } - if (ret == pdTRUE) - ESP_LOGD(TAG, "LORA sendqueue data enqueued"); - else + if (ret != pdTRUE) ESP_LOGW(TAG, "LORA sendqueue is full"); } diff --git a/src/spislave.cpp b/src/spislave.cpp index 32bad108..4d3a75ab 100644 --- a/src/spislave.cpp +++ b/src/spislave.cpp @@ -56,7 +56,7 @@ void spi_slave_task(void *param) { memset(txbuf, 0, sizeof(txbuf)); memset(rxbuf, 0, sizeof(rxbuf)); - // wait until data to send arrivey + // fetch next or wait for payload to send from queue if (xQueueReceive(SPISendQueue, &msg, portMAX_DELAY) != pdTRUE) { ESP_LOGE(TAG, "Premature return from xQueueReceive() with no data!"); continue; From 65045b3cad4e277773ff9e0b62591eca698cd237 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 30 Aug 2019 17:57:17 +0200 Subject: [PATCH 031/105] change startup order for init_display --- src/main.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f042165f..f0a34b14 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -174,6 +174,13 @@ void setup() { // read (and initialize on first run) runtime settings from NVRAM loadConfig(); // includes initialize if necessary +// initialize display +#ifdef HAS_DISPLAY + strcat_P(features, " OLED"); + DisplayIsOn = cfg.screenon; + init_display(PRODUCTNAME, PROGVERSION); // note: blocking call +#endif + #ifdef BOARD_HAS_PSRAM assert(psramFound()); ESP_LOGI(TAG, "PSRAM found and initialized"); @@ -305,13 +312,6 @@ void setup() { strcat_P(features, " FILTER"); #endif -// initialize display -#ifdef HAS_DISPLAY - strcat_P(features, " OLED"); - DisplayIsOn = cfg.screenon; - init_display(PRODUCTNAME, PROGVERSION); // note: blocking call -#endif - // initialize matrix display #ifdef HAS_MATRIX_DISPLAY strcat_P(features, " LED_MATRIX"); From 679582857a47e3225a6dc0beefaad19d6d0916c5 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 30 Aug 2019 18:53:30 +0200 Subject: [PATCH 032/105] battery level on / off --- README.md | 15 ++++++++++++--- src/configmanager.cpp | 6 +++++- src/rcommand.cpp | 26 ++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index cbdaab95..5fa9696b 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,7 @@ Output of sensor and peripheral data is internally switched by a bitmask registe | 4 | User sensor 1 | | 5 | User sensor 2 | | 6 | User sensor 3 | -| 7 | reserved | +| 7 | Batterylevel | # Time sync @@ -392,17 +392,26 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. 0 = BME data off 1 = BME data on, sends BME data on port 7 [default] +0x15 set battery data on/off + + 0 = battery data off [default] + 1 = battery data on, sends voltage on port 8 + 0x80 get device configuration Device answers with it's current configuration on Port 3. 0x81 get device status - Device answers with it's current status on Port 2. + Device answers with it's current status on Port 2. + +0x83 get battery status + + Device answers with battery voltage on Port 8. 0x84 get device GPS status - Device answers with it's current status on Port 4. + Device answers with it's current status on Port 4. 0x85 get BME280 / BME680 sensor data diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 1287d485..73e52f9d 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -8,6 +8,10 @@ static const char TAG[] = "flash"; nvs_handle my_handle; esp_err_t err; +#define PAYLOADMASK \ + (GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | \ + SENSOR2_DATA | SENSOR3_DATA & ~BATT_DATA) + // populate cfg vars with factory settings void defaultConfig() { cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora sf, see pacounter.conf @@ -29,7 +33,7 @@ void defaultConfig() { cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) cfg.monitormode = 0; // 0=disabled, 1=enabled cfg.runmode = 0; // 0=normal, 1=update - cfg.payloadmask = 0xFF; // all payload switched on + cfg.payloadmask = PAYLOADMASK; // all payload switched on cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = { 0}; // init BSEC state for BME680 sensor diff --git a/src/rcommand.cpp b/src/rcommand.cpp index be00f21e..33acf703 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -140,6 +140,16 @@ void set_bme(uint8_t val[]) { } } +void set_batt(uint8_t val[]) { + ESP_LOGI(TAG, "Remote command: set battery mode to %s", + val[0] ? "on" : "off"); + if (val[0]) { + cfg.payloadmask |= (uint8_t)BATT_DATA; // set bit in mask + } else { + cfg.payloadmask &= ~(uint8_t)BATT_DATA; // clear bit in mask + } +} + void set_payloadmask(uint8_t val[]) { ESP_LOGI(TAG, "Remote command: set payload mask to %X", val[0]); cfg.payloadmask = val[0]; @@ -288,6 +298,17 @@ void get_bme(uint8_t val[]) { #endif }; +void get_batt(uint8_t val[]) { + ESP_LOGI(TAG, "Remote command: get battery voltage"); +#ifdef BAT_MEASURE_ADC + payload.reset(); + payload.addVoltage(read_voltage()); + SendPayload(BATTPORT, prio_normal); +#else + ESP_LOGW(TAG, "Battery voltage not supported"); +#endif +}; + void get_time(uint8_t val[]) { ESP_LOGI(TAG, "Remote command: get time"); payload.reset(); @@ -322,8 +343,9 @@ cmd_t table[] = { {0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true}, {0x11, set_monitor, 1, true}, {0x12, set_beacon, 7, false}, {0x13, set_sensor, 2, true}, {0x14, set_payloadmask, 1, true}, - {0x15, set_bme, 1, true}, {0x80, get_config, 0, false}, - {0x81, get_status, 0, false}, {0x84, get_gps, 0, false}, + {0x15, set_bme, 1, true}, {0x16, set_batt, 1, true}, + {0x80, get_config, 0, false}, {0x81, get_status, 0, false}, + {0x83, get_batt, 0, false}, {0x84, get_gps, 0, false}, {0x85, get_bme, 0, false}, {0x86, get_time, 0, false}, {0x87, set_time, 0, false}, {0x99, set_flush, 0, false}}; From 02326a1c7f3b0b9558c62006fa1526f6e1470e9e Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 30 Aug 2019 18:54:53 +0200 Subject: [PATCH 033/105] lora_send code sanitization --- include/lorawan.h | 2 +- include/senddata.h | 2 +- src/cyclic.cpp | 6 ++++-- src/irqhandler.cpp | 2 +- src/senddata.cpp | 4 ++-- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/lorawan.h b/include/lorawan.h index 0010f9de..58b0f3e2 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -21,7 +21,7 @@ #endif extern QueueHandle_t LoraSendQueue; -extern TaskHandle_t lmicTask; +extern TaskHandle_t lmicTask, lorasendTask; esp_err_t lora_stack_init(); void lmictask(void *pvParameters); diff --git a/include/senddata.h b/include/senddata.h index d81b852b..4a748445 100644 --- a/include/senddata.h +++ b/include/senddata.h @@ -10,7 +10,7 @@ extern Ticker sendcycler; void SendPayload(uint8_t port, sendprio_t prio); -void sendCounter(void); +void sendData(void); void checkSendQueues(void); void flushQueues(); void sendcycle(void); diff --git a/src/cyclic.cpp b/src/cyclic.cpp index d78d56c4..a4ba6703 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -30,10 +30,12 @@ void doHousekeeping() { #if (HAS_LORA) ESP_LOGD(TAG, "LMiCtask %d bytes left | Taskstate = %d", uxTaskGetStackHighWaterMark(lmicTask), eTaskGetState(lmicTask)); + ESP_LOGD(TAG, "Lorasendtask %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(lorasendTask), eTaskGetState(lorasendTask)); #endif #if (HAS_GPS) - ESP_LOGD(TAG, "Gpsloop %d bytes left | Taskstate = %d", - uxTaskGetStackHighWaterMark(GpsTask), eTaskGetState(GpsTask)); + ESP_LOGD(TAG, "Gpsloop %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(GpsTask), eTaskGetState(GpsTask)); #endif #ifdef HAS_SPI ESP_LOGD(TAG, "spiloop %d bytes left | Taskstate = %d", diff --git a/src/irqhandler.cpp b/src/irqhandler.cpp index cb5de1ec..db4201a1 100644 --- a/src/irqhandler.cpp +++ b/src/irqhandler.cpp @@ -65,7 +65,7 @@ void irqHandler(void *pvParameters) { // is time to send the payload? if (InterruptStatus & SENDCYCLE_IRQ) - sendCounter(); + sendData(); } } diff --git a/src/senddata.cpp b/src/senddata.cpp index 65d656c5..5e209faf 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -53,7 +53,7 @@ void SendPayload(uint8_t port, sendprio_t prio) { } // SendPayload // interrupt triggered function to prepare payload to send -void sendCounter() { +void sendData() { uint8_t bitmask = cfg.payloadmask; uint8_t mask = 1; @@ -130,7 +130,7 @@ void sendCounter() { mask <<= 1; } // while (bitmask) -} // sendCounter() +} // sendData() void flushQueues() { #if (HAS_LORA) From 93005efce8c8c229b5ccdc4d1a1e6c8658ce3ec8 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 30 Aug 2019 18:55:08 +0200 Subject: [PATCH 034/105] timesync.cpp send alive after sync --- src/timesync.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/timesync.cpp b/src/timesync.cpp index b44a955a..524ac10f 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -106,7 +106,7 @@ void process_timesync_req(void *taskparameter) { payload.addByte(0x99); SendPayload(RCMDPORT, prio_high); // ...send a alive open a receive window for last time_sync_answer - // LMIC_sendAlive(); + LMIC_sendAlive(); } } // end of for loop to collect timestamp samples From 6096c4000071341940e6ad30486114f1e0887b86 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 30 Aug 2019 18:59:45 +0200 Subject: [PATCH 035/105] lora_send stacksize increased --- src/lorawan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index ebf3707c..2329eed3 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -452,7 +452,7 @@ esp_err_t lora_stack_init() { // start lmic send task xTaskCreatePinnedToCore(lora_send, // task function "lorasendtask", // name of task - 2048, // stack size of task + 3072, // stack size of task (void *)1, // parameter of the task 1, // priority of the task &lorasendTask, // task handle From 9475c5e6338e0add2c2268bbe8c904d6c3503023 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 30 Aug 2019 19:34:55 +0200 Subject: [PATCH 036/105] update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5fa9696b..8f414aab 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ You can add up to 3 user defined sensors. Insert sensor's payload scheme in [*se Output of user sensor data can be switched by user remote control command 0x14 sent to Port 2. -Output of sensor and peripheral data is internally switched by a bitmask register. Default mask (0xFF) can be tailored by editing *cfg.payloadmask* initialization value in [*configmanager.cpp*](src/configmanager.cpp) following this scheme: +Output of sensor and peripheral data is internally switched by a bitmask register. Default mask can be tailored by editing *cfg.payloadmask* initialization value in [*configmanager.cpp*](src/configmanager.cpp) following this scheme: | Bit | Sensordata | | --- | ------------- | From 80a24f10ab461f26142da834b9039d10a329d74c Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 31 Aug 2019 15:19:49 +0200 Subject: [PATCH 037/105] introduced LMIC user events --- include/lorawan.h | 5 ++- include/rcommand.h | 2 +- include/timesync.h | 2 +- src/lmic_config.h | 11 ++++-- src/lorawan.cpp | 81 +++++++++++++++++++++++++-------------------- src/paxcounter.conf | 1 + src/rcommand.cpp | 2 +- src/timesync.cpp | 2 +- 8 files changed, 62 insertions(+), 44 deletions(-) diff --git a/include/lorawan.h b/include/lorawan.h index 58b0f3e2..e5af3504 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -4,7 +4,7 @@ #include "globals.h" #include "rcommand.h" #include "timekeeper.h" -#if(TIME_SYNC_LORASERVER) +#if (TIME_SYNC_LORASERVER) #include "timesync.h" #endif @@ -37,6 +37,9 @@ void switch_lora(uint8_t sf, uint8_t tx); void lora_send(void *pvParameters); void lora_enqueuedata(MessageBuffer_t *message); void lora_queuereset(void); +void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, + size_t nMsg); +void myTxCallback(void *pUserData, int fSuccess); #if (TIME_SYNC_LORAWAN) void user_request_network_time_callback(void *pVoidUserUTCTime, int flagSuccess); diff --git a/include/rcommand.h b/include/rcommand.h index e964eb85..7895c257 100644 --- a/include/rcommand.h +++ b/include/rcommand.h @@ -23,7 +23,7 @@ typedef struct { const bool store; } cmd_t; -void rcommand(uint8_t cmd[], uint8_t cmdlength); +void rcommand(const uint8_t cmd[], const uint8_t cmdlength); void do_reset(); #endif diff --git a/include/timesync.h b/include/timesync.h index 7a0013ec..c102c1c4 100644 --- a/include/timesync.h +++ b/include/timesync.h @@ -12,7 +12,7 @@ void timesync_init(void); void send_timesync_req(void); -int recv_timesync_ans(uint8_t seq_no, uint8_t buf[], uint8_t buf_len); +int recv_timesync_ans(const uint8_t seq_no, const uint8_t buf[], const uint8_t buf_len); void process_timesync_req(void *taskparameter); void store_time_sync_req(uint32_t t_millisec); diff --git a/src/lmic_config.h b/src/lmic_config.h index f4ddf4ab..fb6fc771 100644 --- a/src/lmic_config.h +++ b/src/lmic_config.h @@ -19,10 +19,15 @@ // LMIC LORAWAN STACK SETTINGS // --> adapt to your device only if necessary +// use interrupts only if LORA_IRQ and LORA_DIO are connected to interrupt +// capable GPIO pins on your board, if not disable interrupts //#define LMIC_USE_INTERRUPTS 1 -//time sync via LoRaWAN network, is not yet supported by TTN (LoRaWAN spec v1.0.3) -//#define LMIC_ENABLE_DeviceTimeReq 1 +// needed for paxcounter code +#define LMIC_ENABLE_user_events 1 + +// time sync via LoRaWAN network, note: not supported by TTNv2 +// #define LMIC_ENABLE_DeviceTimeReq 1 // 16 μs per tick // LMIC requires ticks to be 15.5μs - 100 μs long @@ -33,7 +38,7 @@ // This tells LMIC to make the receive windows bigger, in case your clock is // faster or slower. This causes the transceiver to be earlier switched on, // so consuming more power. You may sharpen (reduce) this value if you are -// limited on battery. +// limited on battery. // ATTN: VALUES > 7 WILL CAUSE RECEPTION AND JOIN PROBLEMS WITH HIGH SF RATES #define CLOCK_ERROR_PROCENTAGE 7 diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 2329eed3..ae019276 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -244,38 +244,6 @@ void onEvent(ev_t ev) { strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED ACK") : PSTR("TX COMPLETE")); sprintf(display_line6, " "); // clear previous lmic status - - if (LMIC.dataLen) { // did we receive payload data -> display info - ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", - LMIC.dataLen, LMIC.rssi, LMIC.snr / 4); - sprintf(display_line6, "RSSI %d SNR %d", LMIC.rssi, LMIC.snr / 4); - - if (LMIC.txrxFlags & TXRX_PORT) { // FPort -> use to switch - - switch (LMIC.frame[LMIC.dataBeg - 1]) { - - case RCMDPORT: // opcode -> call rcommand interpreter - rcommand(LMIC.frame + LMIC.dataBeg, LMIC.dataLen); - break; - - default: - -#if (TIME_SYNC_LORASERVER) - // timesync answer -> call timesync processor - if ((LMIC.frame[LMIC.dataBeg - 1] >= TIMEANSWERPORT_MIN) && - (LMIC.frame[LMIC.dataBeg - 1] <= TIMEANSWERPORT_MAX)) { - recv_timesync_ans(LMIC.frame[LMIC.dataBeg - 1], - LMIC.frame + LMIC.dataBeg, LMIC.dataLen); - break; - } -#endif - // unknown port -> display info - ESP_LOGI(TAG, "Received data on unsupported port #%d", - LMIC.frame[LMIC.dataBeg - 1]); - break; - } - } - } break; case EV_LOST_TSYNC: @@ -402,9 +370,10 @@ void lora_send(void *pvParameters) { // attempt to transmit payload else { - switch (LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message, - SendBuffer.MessageSize, - (cfg.countermode & 0x02))) { + switch (LMIC_sendWithCallback( + SendBuffer.MessagePort, SendBuffer.Message, SendBuffer.MessageSize, + (cfg.countermode & 0x02), myTxCallback, NULL)) { + case 0: ESP_LOGI(TAG, "%d byte(s) delivered to LMIC", SendBuffer.MessageSize); break; @@ -554,6 +523,9 @@ void lmictask(void *pvParameters) { // rate for 125 kHz channels, and it minimizes air time and battery power. // Set the transmission power to 14 dBi (25 mW). LMIC_setDrTxpow(DR_SF7, 14); + // register a callback for downlink messages. We aren't trying to write + // reentrant code, so pUserData is NULL. + LMIC_registerRxMessageCb(myRxCallback, NULL); #if defined(CFG_US915) || defined(CFG_au921) // in the US, with TTN, it saves join time if we start on subband 1 @@ -569,4 +541,41 @@ void lmictask(void *pvParameters) { } } // lmictask -#endif // HAS_LORA +// receive message handler +void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, + size_t nMsg) { + + // did we receive payload data -> display info + if (nMsg) + ESP_LOGI(TAG, "Received %d bytes of payload on port %d", nMsg, port); + + switch (port) { + + // ignore mac messages + case MACPORT: + break; + + // rcommand received -> call interpreter + case RCMDPORT: + rcommand(pMsg, nMsg); + break; + + default: + +#if (TIME_SYNC_LORASERVER) + // valid timesync answer -> call timesync processor + if ((port >= TIMEANSWERPORT_MIN) && (port <= TIMEANSWERPORT_MAX)) + recv_timesync_ans(port, pMsg, nMsg); + break; +#endif + + // unknown port -> display info + ESP_LOGI(TAG, "Received data on unsupported port %d", port); + break; + } // switch +} + +// transmit complete message handler +void myTxCallback(void *pUserData, int fSuccess) { /* currently unused */ } + +#endif // HAS_LORA \ No newline at end of file diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 7382d8d8..d78d0035 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -85,6 +85,7 @@ // Ports on which the device sends and listenes on LoRaWAN and SPI #define COUNTERPORT 1 // counts +#define MACPORT 0 // network commands #define RCMDPORT 2 // remote commands #define STATUSPORT 2 // remote command results #define CONFIGPORT 3 // config query results diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 33acf703..2f2e14ca 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -353,7 +353,7 @@ const uint8_t cmdtablesize = sizeof(table) / sizeof(table[0]); // number of commands in command table // check and execute remote command -void rcommand(uint8_t cmd[], uint8_t cmdlength) { +void rcommand(const uint8_t cmd[], const uint8_t cmdlength) { if (cmdlength == 0) return; diff --git a/src/timesync.cpp b/src/timesync.cpp index 524ac10f..8ce3238f 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -154,7 +154,7 @@ void store_time_sync_req(uint32_t timestamp) { } // process timeserver timestamp answer, called from lorawan.cpp -int recv_timesync_ans(uint8_t seq_no, uint8_t buf[], uint8_t buf_len) { +int recv_timesync_ans(const uint8_t seq_no, const uint8_t buf[], const uint8_t buf_len) { // if no timesync handshake is pending then exit if (!timeSyncPending) From 1d2c79133f415b0102c62446deb57086c80e8c1c Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 31 Aug 2019 18:36:49 +0200 Subject: [PATCH 038/105] MAC command decoder (experimental) --- include/lorawan.h | 9 +++++ src/lorawan.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/include/lorawan.h b/include/lorawan.h index e5af3504..9094c132 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -23,6 +23,13 @@ extern QueueHandle_t LoraSendQueue; extern TaskHandle_t lmicTask, lorasendTask; +// table of LORAWAN MAC commands +typedef struct { + const uint8_t opcode; + const char cmdname[20]; + const uint8_t params; +} mac_t; + esp_err_t lora_stack_init(); void lmictask(void *pvParameters); void onEvent(ev_t ev); @@ -40,6 +47,8 @@ void lora_queuereset(void); void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, size_t nMsg); void myTxCallback(void *pUserData, int fSuccess); +void mac_decode(const uint8_t cmd[], const uint8_t cmdlength); + #if (TIME_SYNC_LORAWAN) void user_request_network_time_callback(void *pVoidUserUTCTime, int flagSuccess); diff --git a/src/lorawan.cpp b/src/lorawan.cpp index ae019276..31448f08 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -375,10 +375,10 @@ void lora_send(void *pvParameters) { (cfg.countermode & 0x02), myTxCallback, NULL)) { case 0: - ESP_LOGI(TAG, "%d byte(s) delivered to LMIC", SendBuffer.MessageSize); + ESP_LOGI(TAG, "%d byte(s) sent to LORA", SendBuffer.MessageSize); break; case -1: // LMIC already has a tx message pending - ESP_LOGD(TAG, "LMIC busy, message re-enqueued"); + // ESP_LOGD(TAG, "LMIC busy, message re-enqueued"); vTaskDelay(pdMS_TO_TICKS(1000 + random(500))); // wait a while lora_enqueuedata(&SendBuffer); // re-enqueue the undeliverd message break; @@ -545,9 +545,27 @@ void lmictask(void *pvParameters) { void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, size_t nMsg) { - // did we receive payload data -> display info + // tell the compiler that pUserData is required by the API, but we don't + // happen to use it. + LMIC_API_PARAMETER(pUserData); + + // display type of received data if (nMsg) - ESP_LOGI(TAG, "Received %d bytes of payload on port %d", nMsg, port); + ESP_LOGI(TAG, "Received %u bytes of payload on port %u", nMsg, port); + else if (port) + ESP_LOGI(TAG, "Received empty message on port %u", port); + + // list MAC messages, if any + uint8_t nMac = pMsg - &LMIC.frame[0]; + if (port != MACPORT) + --nMac; + if (nMac) { + ESP_LOGI(TAG, "Received %u MAC messages:", nMac); + // NOT WORKING YET + // whe need to strip some protocol overhead from LMIC.frame to unwrap the + // MAC command + mac_decode(LMIC.frame, nMac); + } switch (port) { @@ -570,12 +588,71 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, #endif // unknown port -> display info - ESP_LOGI(TAG, "Received data on unsupported port %d", port); + ESP_LOGI(TAG, "Received data on unsupported port %u", port); break; } // switch } // transmit complete message handler -void myTxCallback(void *pUserData, int fSuccess) { /* currently unused */ } +void myTxCallback(void *pUserData, int fSuccess) { + + /* currently no code here */ + + // tell the compiler that pUserData is required by the API, but we don't + // happen to use it. + LMIC_API_PARAMETER(pUserData); +} + +// LORAWAN MAC interpreter + +// table of LORAWAN MAC messages sent by the network to the device +// format: opcode, cmdname (max 19 chars), #bytes params +// source: LoRaWAN 1.1 Specification (October 11, 2017) + +static mac_t table[] = { + {0x01, "ResetConf", 1}, {0x02, "LinkCheckAns", 2}, + {0x03, "LinkADRReq", 4}, {0x04, "DutyCycleReq", 1}, + {0x05, "RXParamSetupReq", 4}, {0x06, "DevStatusReq", 0}, + {0x07, "NewChannelReq", 5}, {0x08, "RxTimingSetupReq", 1}, + {0x09, "TxParamSetupReq", 1}, {0x0A, "DlChannelReq", 4}, + {0x0B, "RekeyConf", 1}, {0x0C, "ADRParamSetupReq", 1}, + {0x0D, "DeviceTimeAns", 5}, {0x0E, "ForceRejoinReq", 2}, + {0x0F, "RejoinParamSetupReq", 1}}; + +static const uint8_t cmdtablesize = + sizeof(table) / sizeof(table[0]); // number of commands in command table + +// decode mac message +void mac_decode(const uint8_t cmd[], const uint8_t cmdlength) { + + if (!cmdlength) + return; + + uint8_t foundcmd[cmdlength], cursor = 0; + + while (cursor < cmdlength) { + + int i = cmdtablesize; + while (i--) { + if (cmd[cursor] == table[i].opcode) { // lookup command in opcode table + cursor++; // strip 1 byte opcode + if ((cursor + table[i].params) <= cmdlength) { + memmove(foundcmd, cmd + cursor, + table[i].params); // strip opcode from cmd array + cursor += table[i].params; + ESP_LOGI(TAG, "Network command %s", table[i].cmdname); + } else + ESP_LOGI(TAG, "MAC message 0x%02X with missing parameter(s)", + table[i].opcode); + break; // command found -> exit table lookup loop + } // end of command validation + } // end of command table lookup loop + if (i < 0) { // command not found -> skip it + ESP_LOGI(TAG, "Unknown MAC message 0x%02X", cmd[cursor]); + cursor++; + } + } // command parsing loop + +} // mac_decode() #endif // HAS_LORA \ No newline at end of file From ac2f67e98fae2c69f670bdb3fa0da97c89bd3fd4 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 31 Aug 2019 18:37:36 +0200 Subject: [PATCH 039/105] rcommand code sanitization --- include/rcommand.h | 2 +- src/rcommand.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/rcommand.h b/include/rcommand.h index 7895c257..78e1bae4 100644 --- a/include/rcommand.h +++ b/include/rcommand.h @@ -19,7 +19,7 @@ typedef struct { const uint8_t opcode; void (*func)(uint8_t []); - uint8_t params; + const uint8_t params; const bool store; } cmd_t; diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 2f2e14ca..90f55ead 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -332,7 +332,7 @@ void set_flush(uint8_t val[]) { // format: opcode, function, #bytes params, // flag (true = do make settings persistent / false = don't) // -cmd_t table[] = { +static cmd_t table[] = { {0x01, set_rssi, 1, true}, {0x02, set_countmode, 1, true}, {0x03, set_gps, 1, true}, {0x04, set_display, 1, true}, {0x05, set_lorasf, 1, true}, {0x06, set_lorapower, 1, true}, @@ -349,7 +349,7 @@ cmd_t table[] = { {0x85, get_bme, 0, false}, {0x86, get_time, 0, false}, {0x87, set_time, 0, false}, {0x99, set_flush, 0, false}}; -const uint8_t cmdtablesize = +static const uint8_t cmdtablesize = sizeof(table) / sizeof(table[0]); // number of commands in command table // check and execute remote command From 0db8e37563210ed5049de8cf63624101d724eebe Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 1 Sep 2019 00:11:20 +0200 Subject: [PATCH 040/105] bugfix payloadmask --- src/bmesensor.cpp | 2 +- src/gpsread.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bmesensor.cpp b/src/bmesensor.cpp index c6b77fc4..4a53bf89 100644 --- a/src/bmesensor.cpp +++ b/src/bmesensor.cpp @@ -144,7 +144,7 @@ int checkIaqSensorStatus(void) { // store current BME sensor data in struct void bme_storedata(bmeStatus_t *bme_store) { - if ((cfg.payloadmask && MEMS_DATA) & + if ((cfg.payloadmask & MEMS_DATA) && (I2C_MUTEX_LOCK())) { // block i2c bus access #ifdef HAS_BME680 diff --git a/src/gpsread.cpp b/src/gpsread.cpp index bcefd2a2..a4dced58 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -138,7 +138,7 @@ void gps_loop(void *pvParameters) { while (1) { - if (cfg.payloadmask && GPS_DATA) { + if (cfg.payloadmask & GPS_DATA) { #ifdef GPS_SERIAL // feed GPS decoder with serial NMEA data from GPS device while (GPS_Serial.available()) { From 6ec704d0509add5344a9c54965099198d98cec25 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 1 Sep 2019 00:17:13 +0200 Subject: [PATCH 041/105] rcommand.cpp bugfix payloadmask invert --- src/rcommand.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 90f55ead..a5cca590 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -127,7 +127,7 @@ void set_gps(uint8_t val[]) { if (val[0]) { cfg.payloadmask |= (uint8_t)GPS_DATA; // set bit in mask } else { - cfg.payloadmask &= ~(uint8_t)GPS_DATA; // clear bit in mask + cfg.payloadmask &= (uint8_t)~GPS_DATA; // clear bit in mask } } @@ -136,7 +136,7 @@ void set_bme(uint8_t val[]) { if (val[0]) { cfg.payloadmask |= (uint8_t)MEMS_DATA; // set bit in mask } else { - cfg.payloadmask &= ~(uint8_t)MEMS_DATA; // clear bit in mask + cfg.payloadmask &= (uint8_t)~MEMS_DATA; // clear bit in mask } } @@ -146,7 +146,7 @@ void set_batt(uint8_t val[]) { if (val[0]) { cfg.payloadmask |= (uint8_t)BATT_DATA; // set bit in mask } else { - cfg.payloadmask &= ~(uint8_t)BATT_DATA; // clear bit in mask + cfg.payloadmask &= (uint8_t)~BATT_DATA; // clear bit in mask } } From 8385beb19ba9f20421657dc24ec5b7802c33d090 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 1 Sep 2019 00:18:09 +0200 Subject: [PATCH 042/105] v1.7.979 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 75905821..e4f84112 100644 --- a/platformio.ini +++ b/platformio.ini @@ -42,7 +42,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.974 +release_version = 1.7.979 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 From cc2cfd3c134e92e637245ed717f1ee859de67b66 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 1 Sep 2019 00:56:42 +0200 Subject: [PATCH 043/105] configmanager payloadmask default fixed --- src/configmanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 73e52f9d..496bcacb 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -9,8 +9,8 @@ nvs_handle my_handle; esp_err_t err; #define PAYLOADMASK \ - (GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | \ - SENSOR2_DATA | SENSOR3_DATA & ~BATT_DATA) + ((GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | \ + SENSOR2_DATA | SENSOR3_DATA) & ~BATT_DATA) // populate cfg vars with factory settings void defaultConfig() { From b97361ca8cd8e9f64797f0ad71b0e152d9f26164 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 1 Sep 2019 00:57:19 +0200 Subject: [PATCH 044/105] lorawan.cpp: MAC decoder (experimental) --- src/lorawan.cpp | 60 +++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 31448f08..b8cbc1b4 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -21,6 +21,23 @@ static const char TAG[] = "lora"; QueueHandle_t LoraSendQueue; TaskHandle_t lmicTask = NULL, lorasendTask = NULL; +// table of LORAWAN MAC messages sent by the network to the device +// format: opcode, cmdname (max 19 chars), #bytes params +// source: LoRaWAN 1.1 Specification (October 11, 2017) + +static mac_t table[] = { + {0x01, "ResetConf", 1}, {0x02, "LinkCheckAns", 2}, + {0x03, "LinkADRReq", 4}, {0x04, "DutyCycleReq", 1}, + {0x05, "RXParamSetupReq", 4}, {0x06, "DevStatusReq", 0}, + {0x07, "NewChannelReq", 5}, {0x08, "RxTimingSetupReq", 1}, + {0x09, "TxParamSetupReq", 1}, {0x0A, "DlChannelReq", 4}, + {0x0B, "RekeyConf", 1}, {0x0C, "ADRParamSetupReq", 1}, + {0x0D, "DeviceTimeAns", 5}, {0x0E, "ForceRejoinReq", 2}, + {0x0F, "RejoinParamSetupReq", 1}}; + +static const uint8_t cmdtablesize = + sizeof(table) / sizeof(table[0]); // number of commands in MAC table + class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t { public: @@ -545,10 +562,6 @@ void lmictask(void *pvParameters) { void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, size_t nMsg) { - // tell the compiler that pUserData is required by the API, but we don't - // happen to use it. - LMIC_API_PARAMETER(pUserData); - // display type of received data if (nMsg) ESP_LOGI(TAG, "Received %u bytes of payload on port %u", nMsg, port); @@ -560,7 +573,7 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, if (port != MACPORT) --nMac; if (nMac) { - ESP_LOGI(TAG, "Received %u MAC messages:", nMac); + ESP_LOGI(TAG, "Received %u byte MAC message", nMac); // NOT WORKING YET // whe need to strip some protocol overhead from LMIC.frame to unwrap the // MAC command @@ -582,9 +595,10 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, #if (TIME_SYNC_LORASERVER) // valid timesync answer -> call timesync processor - if ((port >= TIMEANSWERPORT_MIN) && (port <= TIMEANSWERPORT_MAX)) + if ((port >= TIMEANSWERPORT_MIN) && (port <= TIMEANSWERPORT_MAX)) { recv_timesync_ans(port, pMsg, nMsg); - break; + break; + } #endif // unknown port -> display info @@ -595,34 +609,10 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, // transmit complete message handler void myTxCallback(void *pUserData, int fSuccess) { - /* currently no code here */ - - // tell the compiler that pUserData is required by the API, but we don't - // happen to use it. - LMIC_API_PARAMETER(pUserData); } -// LORAWAN MAC interpreter - -// table of LORAWAN MAC messages sent by the network to the device -// format: opcode, cmdname (max 19 chars), #bytes params -// source: LoRaWAN 1.1 Specification (October 11, 2017) - -static mac_t table[] = { - {0x01, "ResetConf", 1}, {0x02, "LinkCheckAns", 2}, - {0x03, "LinkADRReq", 4}, {0x04, "DutyCycleReq", 1}, - {0x05, "RXParamSetupReq", 4}, {0x06, "DevStatusReq", 0}, - {0x07, "NewChannelReq", 5}, {0x08, "RxTimingSetupReq", 1}, - {0x09, "TxParamSetupReq", 1}, {0x0A, "DlChannelReq", 4}, - {0x0B, "RekeyConf", 1}, {0x0C, "ADRParamSetupReq", 1}, - {0x0D, "DeviceTimeAns", 5}, {0x0E, "ForceRejoinReq", 2}, - {0x0F, "RejoinParamSetupReq", 1}}; - -static const uint8_t cmdtablesize = - sizeof(table) / sizeof(table[0]); // number of commands in command table - -// decode mac message +// decode LORAWAN MAC message void mac_decode(const uint8_t cmd[], const uint8_t cmdlength) { if (!cmdlength) @@ -640,15 +630,15 @@ void mac_decode(const uint8_t cmd[], const uint8_t cmdlength) { memmove(foundcmd, cmd + cursor, table[i].params); // strip opcode from cmd array cursor += table[i].params; - ESP_LOGI(TAG, "Network command %s", table[i].cmdname); + ESP_LOGD(TAG, "Network command %s", table[i].cmdname); } else - ESP_LOGI(TAG, "MAC message 0x%02X with missing parameter(s)", + ESP_LOGD(TAG, "MAC message 0x%02X with missing parameter(s)", table[i].opcode); break; // command found -> exit table lookup loop } // end of command validation } // end of command table lookup loop if (i < 0) { // command not found -> skip it - ESP_LOGI(TAG, "Unknown MAC message 0x%02X", cmd[cursor]); + ESP_LOGD(TAG, "Unknown MAC message 0x%02X", cmd[cursor]); cursor++; } } // command parsing loop From 9b925ee47b33132909c6d6324c86db62c0cee178 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 1 Sep 2019 22:50:24 +0200 Subject: [PATCH 045/105] LMIC: use interrupts to improve timing accuracy --- src/lmic_config.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/lmic_config.h b/src/lmic_config.h index fb6fc771..0f1f426b 100644 --- a/src/lmic_config.h +++ b/src/lmic_config.h @@ -21,10 +21,7 @@ // use interrupts only if LORA_IRQ and LORA_DIO are connected to interrupt // capable GPIO pins on your board, if not disable interrupts -//#define LMIC_USE_INTERRUPTS 1 - -// needed for paxcounter code -#define LMIC_ENABLE_user_events 1 +#define LMIC_USE_INTERRUPTS 1 // time sync via LoRaWAN network, note: not supported by TTNv2 // #define LMIC_ENABLE_DeviceTimeReq 1 From 31a459beb20d2aedb001545d131114305e671396 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 1 Sep 2019 22:53:57 +0200 Subject: [PATCH 046/105] v1.8.0 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index e4f84112..0fddc0b8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -42,7 +42,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.979 +release_version = 1.8.0 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 From a7f3dd5a59de6727086c7617923d34ce5766197b Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 2 Sep 2019 16:08:12 +0200 Subject: [PATCH 047/105] fix i2c address for serial eeprom --- src/lorawan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index b8cbc1b4..fcba037a 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -151,7 +151,7 @@ void get_hard_deveui(uint8_t *pdeveui) { uint8_t i2c_ret; // Init this just in case, no more to 100KHz - Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 100000); + Wire.begin(SDA, SCL, 100000); Wire.beginTransmission(MCP_24AA02E64_I2C_ADDRESS); Wire.write(MCP_24AA02E64_MAC_ADDRESS); i2c_ret = Wire.endTransmission(); From 8f4c1ff59af3783bc596543684c38a2ffcea0bc0 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 2 Sep 2019 16:51:36 +0200 Subject: [PATCH 048/105] readme.md updated --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f414aab..c8bebf56 100644 --- a/README.md +++ b/README.md @@ -392,7 +392,7 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. 0 = BME data off 1 = BME data on, sends BME data on port 7 [default] -0x15 set battery data on/off +0x16 set battery data on/off 0 = battery data off [default] 1 = battery data on, sends voltage on port 8 From 8b12b7aee22b6229a17ae18c8e049c1ce89793c7 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 2 Sep 2019 16:53:39 +0200 Subject: [PATCH 049/105] axp192 support added --- include/i2cscan.h | 12 + include/main.h | 1 + lib/AXP202X/.gitignore | 2 + lib/AXP202X/LICENSE | 21 + lib/AXP202X/README.md | 9 + lib/AXP202X/keywords.txt | 163 +++++ lib/AXP202X/library.properties | 10 + lib/AXP202X/src/axp20x.cpp | 1160 ++++++++++++++++++++++++++++++++ lib/AXP202X/src/axp20x.h | 766 +++++++++++++++++++++ src/i2cscan.cpp | 101 +++ src/main.cpp | 2 + 11 files changed, 2247 insertions(+) create mode 100644 include/i2cscan.h create mode 100644 lib/AXP202X/.gitignore create mode 100644 lib/AXP202X/LICENSE create mode 100644 lib/AXP202X/README.md create mode 100644 lib/AXP202X/keywords.txt create mode 100644 lib/AXP202X/library.properties create mode 100644 lib/AXP202X/src/axp20x.cpp create mode 100644 lib/AXP202X/src/axp20x.h create mode 100644 src/i2cscan.cpp diff --git a/include/i2cscan.h b/include/i2cscan.h new file mode 100644 index 00000000..b834b34f --- /dev/null +++ b/include/i2cscan.h @@ -0,0 +1,12 @@ +#ifndef _I2CSCAN_H +#define _I2CSCAN_H + +#include +#ifdef HAS_PMU +#include "axp20x.h" +#endif + +int i2c_scan(void); +void AXP192_init(void); + +#endif \ No newline at end of file diff --git a/include/main.h b/include/main.h index bce12e51..ddc49d5d 100644 --- a/include/main.h +++ b/include/main.h @@ -7,6 +7,7 @@ #include // needed for showing coex sw version #include "globals.h" +#include "i2cscan.h" #include "blescan.h" #include "wifiscan.h" #include "configmanager.h" diff --git a/lib/AXP202X/.gitignore b/lib/AXP202X/.gitignore new file mode 100644 index 00000000..6d0ee45d --- /dev/null +++ b/lib/AXP202X/.gitignore @@ -0,0 +1,2 @@ +.vscode +.DS_Store \ No newline at end of file diff --git a/lib/AXP202X/LICENSE b/lib/AXP202X/LICENSE new file mode 100644 index 00000000..3b7bfa9f --- /dev/null +++ b/lib/AXP202X/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 lewis he + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/AXP202X/README.md b/lib/AXP202X/README.md new file mode 100644 index 00000000..8623bc5a --- /dev/null +++ b/lib/AXP202X/README.md @@ -0,0 +1,9 @@ +AXP202X_Library +===================================== +- axp192 partial support, the function is not fully tested, please refer to the manual +- The `setPowerOutPut` function has forced DCDC3 to be turned on and cannot be controlled because T-Watch uses DCDC3 as the esp32 to power the main chip. If it is turned off, the hardware cannot be programmed. + + +TTGO invests time and resources to provide this open source code, please support TTGO and open source hardware by purchasing products from TTGO! + +Written by Lewis He for TTGO. MIT license, all text above must be included in any redistribution \ No newline at end of file diff --git a/lib/AXP202X/keywords.txt b/lib/AXP202X/keywords.txt new file mode 100644 index 00000000..55ffde3f --- /dev/null +++ b/lib/AXP202X/keywords.txt @@ -0,0 +1,163 @@ +####################################### +# Syntax Coloring Map For X-Power AXP20X Library By lewis He +# github:https://github.com/lewisxhe +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### +AXP20X_Class KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +isChargeing KEYWORD2 +isLDO2Enable KEYWORD2 +isLDO3Enable KEYWORD2 +isLDO4Enable KEYWORD2 +isDCDC3Enable KEYWORD2 +isDCDC2Enable KEYWORD2 +isChargeingEnable KEYWORD2 +isAcinOverVoltageIRQ KEYWORD2 +isAcinPlugInIRQ KEYWORD2 +isAcinRemoveIRQ KEYWORD2 +isVbusOverVoltageIRQ KEYWORD2 +isVbusPlugInIRQ KEYWORD2 +isVbusRemoveIRQ KEYWORD2 +isVbusLowVHOLDIRQ KEYWORD2 +isBattPlugInIRQ KEYWORD2 +isBattRemoveIRQ KEYWORD2 +isBattEnterActivateIRQ KEYWORD2 +isBattExitActivateIRQ KEYWORD2 +isChargingIRQ KEYWORD2 +isChargingDoneIRQ KEYWORD2 +isBattTempLowIRQ KEYWORD2 +isBattTempHighIRQ KEYWORD2 +isPEKShortPressIRQ KEYWORD2 +isPEKLongtPressIRQ KEYWORD2 +getAcinVoltage KEYWORD2 +getAcinCurrent KEYWORD2 +getVbusVoltage KEYWORD2 +getVbusCurrent KEYWORD2 +getTemp KEYWORD2 +getTSTemp KEYWORD2 +getGPIO0Voltage KEYWORD2 +getGPIO1Voltage KEYWORD2 +getBattInpower KEYWORD2 +getBattVoltage KEYWORD2 +getBattChargeCurrent KEYWORD2 +getBattDischargeCurrent KEYWORD2 +getSysIPSOUTVoltage KEYWORD2 +getBattChargeCoulomb KEYWORD2 +getBattDischargeCoulomb KEYWORD2 +getSettingChargeCurrent KEYWORD2 +setChargingTargetVoltage KEYWORD2 +enableChargeing KEYWORD2 +adc1Enable KEYWORD2 +adc2Enable KEYWORD2 +setStartupTime KEYWORD2 +setlongPressTime KEYWORD2 +setShutdownTime KEYWORD2 +setTimeOutShutdown KEYWORD2 +enableIRQ KEYWORD2 +readIRQ KEYWORD2 +clearIRQ KEYWORD2 +setDCDC2Voltage KEYWORD2 +setDCDC3Voltage KEYWORD2 +setLDO2Voltage KEYWORD2 +setLDO3Voltage KEYWORD2 +setLDO4Voltage KEYWORD2 +getBattPercentage KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + + +####################################### +# Constants (LITERAL1) +####################################### +AXP202_LDO4_1250MV LITERAL1 +AXP202_LDO4_1300MV LITERAL1 +AXP202_LDO4_1400MV LITERAL1 +AXP202_LDO4_1500MV LITERAL1 +AXP202_LDO4_1600MV LITERAL1 +AXP202_LDO4_1700MV LITERAL1 +AXP202_LDO4_1800MV LITERAL1 +AXP202_LDO4_1900MV LITERAL1 +AXP202_LDO4_2000MV LITERAL1 +AXP202_LDO4_2500MV LITERAL1 +AXP202_LDO4_2700MV LITERAL1 +AXP202_LDO4_2800MV LITERAL1 +AXP202_LDO4_3000MV LITERAL1 +AXP202_LDO4_3100MV LITERAL1 +AXP202_LDO4_3200MV LITERAL1 +AXP202_LDO4_3300MV LITERAL1 + +AXP202_VBUS_VHOLD_LOW_IRQ LITERAL1 +AXP202_VBUS_REMOVED_IRQ LITERAL1 +AXP202_VBUS_CONNECT_IRQ LITERAL1 +AXP202_VBUS_OVER_VOL_IRQ LITERAL1 +AXP202_ACIN_REMOVED_IRQ LITERAL1 +AXP202_ACIN_CONNECT_IRQ LITERAL1 +AXP202_ACIN_OVER_VOL_IRQ LITERAL1 +AXP202_BATT_LOW_TEMP_IRQ LITERAL1 +AXP202_BATT_OVER_TEMP_IRQ LITERAL1 +AXP202_CHARGING_FINISHED_IRQ LITERAL1 +AXP202_CHARGING_IRQ LITERAL1 +AXP202_BATT_EXIT_ACTIVATE_IRQ LITERAL1 +AXP202_BATT_ACTIVATE_IRQ LITERAL1 +AXP202_BATT_REMOVED_IRQ LITERAL1 +AXP202_BATT_CONNECT_IRQ LITERAL1 +AXP202_PEK_LONGPRESS_IRQ LITERAL1 +AXP202_PEL_SHORTPRESS_IRQ LITERAL1 +AXP202_LDO3_LOW_VOL_IRQ LITERAL1 +AXP202_DC3_LOW_VOL_IRQ LITERAL1 +AXP202_DC2_LOW_VOL_IRQ LITERAL1 +AXP202_CHARGE_LOW_CUR_IRQ LITERAL1 +AXP202_CHIP_TEMP_HIGH_IRQ LITERAL1 +AXP202_APS_LOW_VOL_LEVEL2_IRQ LITERAL1 +APX202_APS_LOW_VOL_LEVEL1_IRQ LITERAL1 +AXP202_VBUS_SESSION_END_IRQ LITERAL1 +AXP202_VBUS_SESSION_AB_IRQ LITERAL1 +AXP202_VBUS_INVALID_IRQ LITERAL1 +AXP202_VBUS_VAILD_IRQ LITERAL1 +AXP202_NOE_OFF_IRQ LITERAL1 +AXP202_NOE_ON_IRQ LITERAL1 + +AXP202_TEMP_MONITORING_ADC2 LITERAL1 +AXP202_GPIO1_FUNC_ADC2 LITERAL1 +AXP202_GPIO0_FUNC_ADC2 LITERAL1 + +AXP202_BATT_VOL_ADC1 LITERAL1 +AXP202_BATT_CUR_ADC1 LITERAL1 +AXP202_ACIN_VOL_ADC1 LITERAL1 +AXP202_ACIN_CUR_ADC1 LITERAL1 +AXP202_VBUS_VOL_ADC1 LITERAL1 +AXP202_VBUS_CUR_ADC1 LITERAL1 +AXP202_APS_VOL_ADC1 LITERAL1 +AXP202_TS_PIN_ADC1 LITERAL1 + +AXP202_TARGET_VOL_4_1V LITERAL1 +AXP202_TARGET_VOL_4_15V LITERAL1 +AXP202_TARGET_VOL_4_2V LITERAL1 +AXP202_TARGET_VOL_4_36V LITERAL1 +AXP202_STARTUP_TIME_128MS LITERAL1 +AXP202_STARTUP_TIME_3S LITERAL1 +AXP202_STARTUP_TIME_1S LITERAL1 +AXP202_STARTUP_TIME_2S LITERAL1 +AXP202_STARTUP_TIME LITERAL1 +AXP202_LONGPRESS_TIME LITERAL1 +AXP202_SHUTDOWN_EXCEEDS_TIME LITERAL1 +AXP202_PWROK_SIGNAL_DELAY LITERAL1 +AXP202_SHUTDOWN_TIME LITERAL1 + + +AXP202_EXTEN LITERAL1 +AXP202_DCDC3 LITERAL1 +AXP202_LDO2 LITERAL1 +AXP202_LDO4 LITERAL1 +AXP202_DCDC2 LITERAL1 +AXP202_LDO3 LITERAL1 \ No newline at end of file diff --git a/lib/AXP202X/library.properties b/lib/AXP202X/library.properties new file mode 100644 index 00000000..9824467d --- /dev/null +++ b/lib/AXP202X/library.properties @@ -0,0 +1,10 @@ +name=AXP202X_Library +version=1.0.0 +author=Lewis He +maintainer=Lewis He +sentence=Arduino library for X-Power AXP202 chip +paragraph=Arduino library for X-Power AXP202 chip. Tested with ESP32 +category=Communication +url=https://github.com/lewisxhe/AXP202X_Library +architectures=* +architectures=esp32 \ No newline at end of file diff --git a/lib/AXP202X/src/axp20x.cpp b/lib/AXP202X/src/axp20x.cpp new file mode 100644 index 00000000..2293f2f6 --- /dev/null +++ b/lib/AXP202X/src/axp20x.cpp @@ -0,0 +1,1160 @@ +///////////////////////////////////////////////////////////////// +/* +MIT License + +Copyright (c) 2019 lewis he + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +axp20x.cpp - Arduino library for X-Power AXP202 chip. +Created by Lewis he on April 1, 2019. +github:https://github.com/lewisxhe/AXP202X_Libraries +*/ +///////////////////////////////////////////////////////////////// + +#include "axp20x.h" +#include + +const uint8_t AXP20X_Class::startupParams[] = { + 0b00000000, + 0b01000000, + 0b10000000, + 0b11000000 +}; + +const uint8_t AXP20X_Class::longPressParams[] = { + 0b00000000, + 0b00010000, + 0b00100000, + 0b00110000 +}; + +const uint8_t AXP20X_Class::shutdownParams[] = { + 0b00000000, + 0b00000001, + 0b00000010, + 0b00000011 +}; + +const uint8_t AXP20X_Class::targetVolParams[] = { + 0b00000000, + 0b00100000, + 0b01000000, + 0b01100000 +}; + + +// Power Output Control register +uint8_t AXP20X_Class::_outputReg; + +int AXP20X_Class::begin(TwoWire &port, uint8_t addr) +{ + _i2cPort = &port; //Grab which port the user wants us to use + _address = addr; + _readByte(AXP202_IC_TYPE, 1, &_chip_id); + AXP_DEBUG("chip id detect 0x%x\n", _chip_id); + if (_chip_id == AXP202_CHIP_ID || _chip_id == AXP192_CHIP_ID) { + AXP_DEBUG("Detect CHIP :%s\n", _chip_id == AXP202_CHIP_ID ? "AXP202" : "AXP192"); + _readByte(AXP202_LDO234_DC23_CTL, 1, &_outputReg); + AXP_DEBUG("OUTPUT Register 0x%x\n", _outputReg); + _init = true; + } + return _init ? AXP_PASS : AXP_FAIL; +} + +//Only axp192 chip +bool AXP20X_Class::isDCDC1Enable() +{ + if (_chip_id == AXP192_CHIP_ID) + return IS_OPEN(_outputReg, AXP192_DCDC1); + return false; +} +//Only axp192 chip +bool AXP20X_Class::isExtenEnable() +{ + if (_chip_id == AXP192_CHIP_ID) + return IS_OPEN(_outputReg, AXP192_EXTEN); + return false; +} + +bool AXP20X_Class::isLDO2Enable() +{ + //axp192 same axp202 ldo2 bit + return IS_OPEN(_outputReg, AXP202_LDO2); +} + +bool AXP20X_Class::isLDO3Enable() +{ + if (_chip_id == AXP192_CHIP_ID) + return IS_OPEN(_outputReg, AXP192_LDO3); + else if (_chip_id == AXP202_CHIP_ID) + return IS_OPEN(_outputReg, AXP202_LDO3); + return false; +} + +bool AXP20X_Class::isLDO4Enable() +{ + if (_chip_id == AXP202_CHIP_ID) + return IS_OPEN(_outputReg, AXP202_LDO4); + return false; +} + +bool AXP20X_Class::isDCDC2Enable() +{ + //axp192 same axp202 dc2 bit + return IS_OPEN(_outputReg, AXP202_DCDC2); +} + +bool AXP20X_Class::isDCDC3Enable() +{ + //axp192 same axp202 dc3 bit + return IS_OPEN(_outputReg, AXP202_DCDC3); +} + +int AXP20X_Class::setPowerOutPut(uint8_t ch, bool en) +{ + uint8_t data; + uint8_t val = 0; + if (!_init)return AXP_NOT_INIT; + + _readByte(AXP202_LDO234_DC23_CTL, 1, &data); + if (en) { + data |= (1 << ch); + } else { + data &= (~(1 << ch)); + } + + FORCED_OPEN_DCDC3(data); //! Must be forced open in T-Watch + + _writeByte(AXP202_LDO234_DC23_CTL, 1, &data); + delay(1); + _readByte(AXP202_LDO234_DC23_CTL, 1, &val); + if (data == val) { + _outputReg = val; + return AXP_PASS; + } + return AXP_FAIL; +} + +bool AXP20X_Class::isChargeing() +{ + uint8_t reg; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_MODE_CHGSTATUS, 1, ®); + return IS_OPEN(reg, 6); +} + +bool AXP20X_Class::isBatteryConnect() +{ + uint8_t reg; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_MODE_CHGSTATUS, 1, ®); + return IS_OPEN(reg, 5); +} + +float AXP20X_Class::getAcinVoltage() +{ + if (!_init)return AXP_NOT_INIT; + return _getRegistResult(AXP202_ACIN_VOL_H8, AXP202_ACIN_VOL_L4) * AXP202_ACIN_VOLTAGE_STEP; +} + +float AXP20X_Class::getAcinCurrent() +{ + if (!_init)return AXP_NOT_INIT; + float rslt; + uint8_t hv, lv; + return _getRegistResult(AXP202_ACIN_CUR_H8, AXP202_ACIN_CUR_L4) * AXP202_ACIN_CUR_STEP; +} + +float AXP20X_Class::getVbusVoltage() +{ + if (!_init)return AXP_NOT_INIT; + return _getRegistResult(AXP202_VBUS_VOL_H8, AXP202_VBUS_VOL_L4) * AXP202_VBUS_VOLTAGE_STEP; +} + +float AXP20X_Class::getVbusCurrent() +{ + if (!_init)return AXP_NOT_INIT; + return _getRegistResult(AXP202_VBUS_CUR_H8, AXP202_VBUS_CUR_L4) * AXP202_VBUS_CUR_STEP; +} + +float AXP20X_Class::getTemp() +{ + if (!_init)return AXP_NOT_INIT; + uint8_t hv, lv; + _readByte(AXP202_INTERNAL_TEMP_H8, 1, &hv); + _readByte(AXP202_INTERNAL_TEMP_L4, 1, &lv); + float rslt = hv << 8 | (lv & 0xF); + return rslt / 1000; +} + +float AXP20X_Class::getTSTemp() +{ + if (!_init)return AXP_NOT_INIT; + return _getRegistResult(AXP202_TS_IN_H8, AXP202_TS_IN_L4) * AXP202_TS_PIN_OUT_STEP; +} + +float AXP20X_Class::getGPIO0Voltage() +{ + if (!_init)return AXP_NOT_INIT; + return _getRegistResult(AXP202_GPIO0_VOL_ADC_H8, AXP202_GPIO0_VOL_ADC_L4) * AXP202_GPIO0_STEP; +} + +float AXP20X_Class::getGPIO1Voltage() +{ + if (!_init)return AXP_NOT_INIT; + return _getRegistResult(AXP202_GPIO1_VOL_ADC_H8, AXP202_GPIO1_VOL_ADC_L4) * AXP202_GPIO1_STEP; +} + +/* +Note: the battery power formula: +Pbat =2* register value * Voltage LSB * Current LSB / 1000. +(Voltage LSB is 1.1mV; Current LSB is 0.5mA, and unit of calculation result is mW.) +*/ +float AXP20X_Class::getBattInpower() +{ + float rslt; + uint8_t hv, mv, lv; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_BAT_POWERH8, 1, &hv); + _readByte(AXP202_BAT_POWERM8, 1, &mv); + _readByte(AXP202_BAT_POWERL8, 1, &lv); + rslt = (hv << 16) | (mv << 8) | lv; + rslt = 2 * rslt * 1.1 * 0.5 / 1000; + return rslt; +} + +float AXP20X_Class::getBattVoltage() +{ + if (!_init)return AXP_NOT_INIT; + return _getRegistResult(AXP202_BAT_AVERVOL_H8, AXP202_BAT_AVERVOL_L4) * AXP202_BATT_VOLTAGE_STEP; +} + +float AXP20X_Class::getBattChargeCurrent() +{ + if (!_init)return AXP_NOT_INIT; + switch (_chip_id) { + case AXP202_CHIP_ID: + return _getRegistResult(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L4) * AXP202_BATT_CHARGE_CUR_STEP; + case AXP192_CHIP_ID: + return _getRegistH8L5(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L4) * AXP202_BATT_CHARGE_CUR_STEP; + default: + break; + } +} + +float AXP20X_Class::getBattDischargeCurrent() +{ + float rslt; + uint8_t hv, lv; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_BAT_AVERDISCHGCUR_H8, 1, &hv); + _readByte(AXP202_BAT_AVERDISCHGCUR_L5, 1, &lv); + rslt = (hv << 5) | (lv & 0x1F); + return rslt * AXP202_BATT_DISCHARGE_CUR_STEP; +} + +float AXP20X_Class::getSysIPSOUTVoltage() +{ + float rslt; + uint8_t hv, lv; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_APS_AVERVOL_H8, 1, &hv); + _readByte(AXP202_APS_AVERVOL_L4, 1, &lv); + rslt = (hv << 4) | (lv & 0xF); + return rslt; +} + +/* +Coulomb calculation formula: +C= 65536 * current LSB *(charge coulomb counter value - discharge coulomb counter value) / +3600 / ADC sample rate. Refer to REG84H setting for ADC sample rate;the current LSB is +0.5mA;unit of the calculation result is mAh. ) +*/ +uint32_t AXP20X_Class::getBattChargeCoulomb() +{ + uint8_t buffer[4]; + if (!_init)return AXP_NOT_INIT; + _readByte(0xB1, 4, buffer); + return buffer[0] << 24 + buffer[1] << 16 + buffer[2] << 8 + buffer[3]; +} + +uint32_t AXP20X_Class::getBattDischargeCoulomb() +{ + uint8_t buffer[4]; + if (!_init)return AXP_NOT_INIT; + _readByte(0xB4, 4, buffer); + return buffer[0] << 24 + buffer[1] << 16 + buffer[2] << 8 + buffer[3]; +} + +float AXP20X_Class::getCoulombData() +{ + if (!_init)return AXP_NOT_INIT; + uint32_t charge = getBattChargeCoulomb(); + uint32_t discharge = getBattDischargeCoulomb(); + uint8_t rate = getAdcSamplingRate(); + float result = 65536.0 * 0.5 * (charge - discharge) / 3600.0 / rate; + return result; +} + +uint8_t AXP20X_Class::getAdcSamplingRate() +{ + //axp192 same axp202 aregister address 0x84 + if (!_init)return AXP_NOT_INIT; + uint8_t val; + _readByte(AXP202_ADC_SPEED, 1, &val); + return 25 * (int)pow(2, (val & 0xC0) >> 6); +} + +int AXP20X_Class::setAdcSamplingRate(axp_adc_sampling_rate_t rate) +{ + //axp192 same axp202 aregister address 0x84 + if (!_init)return AXP_NOT_INIT; + if (rate > AXP_ADC_SAMPLING_RATE_200HZ) return AXP_FAIL; + uint8_t val; + _readByte(AXP202_ADC_SPEED, 1, &val); + uint8_t rw = rate; + val &= 0x3F; + val |= (rw << 6); + _writeByte(AXP202_ADC_SPEED, 1, &val); + return AXP_PASS; +} + + +int AXP20X_Class::adc1Enable(uint16_t params, bool en) +{ + if (!_init)return AXP_NOT_INIT; + uint8_t val; + _readByte(AXP202_ADC_EN1, 1, &val); + if (en) + val |= params; + else + val &= ~(params); + _writeByte(AXP202_ADC_EN1, 1, &val); + + _readByte(AXP202_ADC_EN1, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::adc2Enable(uint16_t params, bool en) +{ + if (!_init)return AXP_NOT_INIT; + uint8_t val; + _readByte(AXP202_ADC_EN2, 1, &val); + if (en) + val |= params; + else + val &= ~(params); + _writeByte(AXP202_ADC_EN2, 1, &val); + return AXP_PASS; +} + + + +int AXP20X_Class::enableIRQ(uint32_t params, bool en) +{ + if (!_init)return AXP_NOT_INIT; + uint8_t val, val1; + if (params & 0xFF) { + val1 = params & 0xFF; + _readByte(AXP202_INTEN1, 1, &val); + if (en) + val |= val1; + else + val &= ~(val1); + AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN1, val); + _writeByte(AXP202_INTEN1, 1, &val); + } + if (params & 0xFF00) { + val1 = params >> 8; + _readByte(AXP202_INTEN2, 1, &val); + if (en) + val |= val1; + else + val &= ~(val1); + AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN2, val); + _writeByte(AXP202_INTEN2, 1, &val); + } + + if (params & 0xFF0000) { + val1 = params >> 16; + _readByte(AXP202_INTEN3, 1, &val); + if (en) + val |= val1; + else + val &= ~(val1); + AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN3, val); + _writeByte(AXP202_INTEN3, 1, &val); + } + + if (params & 0xFF000000) { + val1 = params >> 24; + _readByte(AXP202_INTEN4, 1, &val); + if (en) + val |= val1; + else + val &= ~(val1); + AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN4, val); + _writeByte(AXP202_INTEN4, 1, &val); + } + return AXP_PASS; +} + +int AXP20X_Class::readIRQ() +{ + if (!_init)return AXP_NOT_INIT; + switch (_chip_id) { + case AXP192_CHIP_ID: + for (int i = 0; i < 4; ++i) { + _readByte(AXP192_INTSTS1 + i, 1, &_irq[i]); + } + _readByte(AXP192_INTSTS5, 1, &_irq[4]); + return AXP_PASS; + + case AXP202_CHIP_ID: + for (int i = 0; i < 5; ++i) { + _readByte(AXP202_INTSTS1 + i, 1, &_irq[i]); + } + return AXP_PASS; + default: + return AXP_FAIL; + } +} + +void AXP20X_Class::clearIRQ() +{ + uint8_t val = 0xFF; + switch (_chip_id) { + case AXP192_CHIP_ID: + for (int i = 0; i < 3; i++) { + _writeByte(AXP192_INTSTS1 + i, 1, &val); + } + _writeByte(AXP192_INTSTS5, 1, &val); + break; + case AXP202_CHIP_ID: + for (int i = 0; i < 5; i++) { + _writeByte(AXP202_INTSTS1 + i, 1, &val); + } + break; + default: + break; + } + memset(_irq, 0, sizeof(_irq)); +} + + +bool AXP20X_Class::isAcinOverVoltageIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(7)); +} + +bool AXP20X_Class::isAcinPlugInIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(6)); +} + +bool AXP20X_Class::isAcinRemoveIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(5)); +} + +bool AXP20X_Class::isVbusOverVoltageIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(4)); +} + +bool AXP20X_Class::isVbusPlugInIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(3)); +} + +bool AXP20X_Class::isVbusRemoveIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(2)); +} + +bool AXP20X_Class::isVbusLowVHOLDIRQ() +{ + return (bool)(_irq[0] & BIT_MASK(1)); +} + +bool AXP20X_Class::isBattPlugInIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(7)); +} +bool AXP20X_Class::isBattRemoveIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(6)); +} +bool AXP20X_Class::isBattEnterActivateIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(5)); +} +bool AXP20X_Class::isBattExitActivateIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(4)); +} +bool AXP20X_Class::isChargingIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(3)); +} +bool AXP20X_Class::isChargingDoneIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(2)); +} +bool AXP20X_Class::isBattTempLowIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(1)); +} +bool AXP20X_Class::isBattTempHighIRQ() +{ + return (bool)(_irq[1] & BIT_MASK(0)); +} + +bool AXP20X_Class::isPEKShortPressIRQ() +{ + return (bool)(_irq[2] & BIT_MASK(1)); +} + +bool AXP20X_Class::isPEKLongtPressIRQ() +{ + return (bool)(_irq[2] & BIT_MASK(0)); +} + +bool AXP20X_Class::isVBUSPlug() +{ + if (!_init)return AXP_NOT_INIT; + uint8_t val; + _readByte(AXP202_STATUS, 1, &val); + return (bool)(_irq[2] & BIT_MASK(5)); +} + +int AXP20X_Class::setDCDC2Voltage(uint16_t mv) +{ + if (!_init)return AXP_NOT_INIT; + if (mv < 700) { + AXP_DEBUG("DCDC2:Below settable voltage:700mV~2275mV"); + mv = 700; + } + if (mv > 2275) { + AXP_DEBUG("DCDC2:Above settable voltage:700mV~2275mV"); + mv = 2275; + } + uint8_t val = (mv - 700) / 25; + _writeByte(AXP202_DC2OUT_VOL, 1, &val); + return AXP_PASS; +} + + + +uint16_t AXP20X_Class::getDCDC2Voltage() +{ + uint8_t val = 0; + _readByte(AXP202_DC2OUT_VOL, 1, &val); + return val * 25 + 700; +} + +uint16_t AXP20X_Class::getDCDC3Voltage() +{ + uint8_t val = 0; + _readByte(AXP202_DC3OUT_VOL, 1, &val); + return val * 25 + 700; +} + + +int AXP20X_Class::setDCDC3Voltage(uint16_t mv) +{ + if (!_init)return AXP_NOT_INIT; + if (mv < 700) { + AXP_DEBUG("DCDC3:Below settable voltage:700mV~3500mV"); + mv = 700; + } + if (mv > 3500) { + AXP_DEBUG("DCDC3:Above settable voltage:700mV~3500mV"); + mv = 3500; + } + uint8_t val = (mv - 700) / 25; + _writeByte(AXP202_DC3OUT_VOL, 1, &val); + return AXP_PASS; +} + + +int AXP20X_Class::setLDO2Voltage(uint16_t mv) +{ + uint8_t rVal, wVal; + if (!_init)return AXP_NOT_INIT; + if (mv < 1800) { + AXP_DEBUG("LDO2:Below settable voltage:1800mV~3300mV"); + mv = 1800; + } + if (mv > 3300) { + AXP_DEBUG("LDO2:Above settable voltage:1800mV~3300mV"); + mv = 3300; + } + wVal = (mv - 1800) / 100; + if (_chip_id == AXP202_CHIP_ID ) { + _readByte(AXP202_LDO24OUT_VOL, 1, &rVal); + rVal &= 0x0F; + rVal |= (wVal << 4); + _writeByte(AXP202_LDO24OUT_VOL, 1, &rVal); + return AXP_PASS; + } else if (_chip_id == AXP192_CHIP_ID) { + _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); + rVal &= 0x0F; + rVal |= (wVal << 4); + _writeByte(AXP192_LDO23OUT_VOL, 1, &rVal); + return AXP_PASS; + } + return AXP_FAIL; +} + + +uint16_t AXP20X_Class::getLDO2Voltage() +{ + uint8_t rVal; + if (_chip_id == AXP202_CHIP_ID ) { + _readByte(AXP202_LDO24OUT_VOL, 1, &rVal); + rVal &= 0xF0; + rVal >>= 4; + return rVal * 100 + 1800; + } else if (_chip_id == AXP192_CHIP_ID) { + _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); + AXP_DEBUG("get result:%x\n", rVal); + rVal &= 0xF0; + rVal >>= 4; + return rVal * 100 + 1800; + } + return 0; +} + +int AXP20X_Class::setLDO3Voltage(uint16_t mv) +{ + uint8_t rVal; + if (!_init)return AXP_NOT_INIT; + if (_chip_id == AXP202_CHIP_ID && mv < 700) { + AXP_DEBUG("LDO3:Below settable voltage:700mV~2275mV"); + mv = 700; + } else if (_chip_id == AXP192_CHIP_ID && mv < 1800) { + AXP_DEBUG("LDO3:Below settable voltage:1800mV~3300mV"); + mv = 1800; + } + + if (_chip_id == AXP202_CHIP_ID && mv > 2275) { + AXP_DEBUG("LDO3:Above settable voltage:700mV~2275mV"); + mv = 2275; + } else if (_chip_id == AXP192_CHIP_ID && mv > 3300) { + AXP_DEBUG("LDO3:Above settable voltage:1800mV~3300mV"); + mv = 3300; + } + + if (_chip_id == AXP202_CHIP_ID ) { + + _readByte(AXP202_LDO3OUT_VOL, 1, &rVal); + rVal &= 0x80; + rVal |= ((mv - 700) / 25); + _writeByte(AXP202_LDO3OUT_VOL, 1, &rVal); + return AXP_PASS; + + } else if (_chip_id == AXP192_CHIP_ID) { + + _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); + rVal &= 0xF0; + rVal |= ((mv - 1800) / 100); + _writeByte(AXP192_LDO23OUT_VOL, 1, &rVal); + return AXP_PASS; + } + return AXP_FAIL; +} + + +uint16_t AXP20X_Class::getLDO3Voltage() +{ + uint8_t rVal; + if (!_init)return AXP_NOT_INIT; + + if (_chip_id == AXP202_CHIP_ID ) { + + _readByte(AXP202_LDO3OUT_VOL, 1, &rVal); + if (rVal & 0x80) { + //! According to the hardware N_VBUSEN Pin selection + return getVbusVoltage() * 1000; + } else { + return (rVal & 0x7F) * 25 + 700; + } + } else if (_chip_id == AXP192_CHIP_ID) { + _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); + rVal &= 0x0F; + return rVal * 100 + 1800; + } + return 0; +} + +//! Only axp202 support +int AXP20X_Class::setLDO4Voltage(axp_ldo4_table_t param) +{ + if (!_init)return AXP_NOT_INIT; + if (_chip_id != AXP202_CHIP_ID ) return AXP_FAIL; + if (param >= AXP202_LDO4_MAX)return AXP_INVALID; + uint8_t val; + _readByte(AXP202_LDO24OUT_VOL, 1, &val); + val &= 0xF0; + val |= param; + _writeByte(AXP202_LDO24OUT_VOL, 1, &val); + return AXP_PASS; +} + +//! Only AXP202 support +// 0 : LDO 1 : DCIN +int AXP20X_Class::setLDO3Mode(uint8_t mode) +{ + uint8_t val; + if (_chip_id != AXP202_CHIP_ID ) return AXP_FAIL; + _readByte(AXP202_LDO3OUT_VOL, 1, &val); + if (mode) { + val |= BIT_MASK(7); + } else { + val &= (~BIT_MASK(7)); + } + _writeByte(AXP202_LDO3OUT_VOL, 1, &val); + return AXP_PASS; + +} + +int AXP20X_Class::setStartupTime(uint8_t param) +{ + uint8_t val; + if (!_init)return AXP_NOT_INIT; + if (param > sizeof(startupParams) / sizeof(startupParams[0]))return AXP_INVALID; + _readByte(AXP202_POK_SET, 1, &val); + val &= (~0b11000000); + val |= startupParams[param]; + _writeByte(AXP202_POK_SET, 1, &val); +} + +int AXP20X_Class::setlongPressTime(uint8_t param) +{ + uint8_t val; + if (!_init)return AXP_NOT_INIT; + if (param > sizeof(longPressParams) / sizeof(longPressParams[0]))return AXP_INVALID; + _readByte(AXP202_POK_SET, 1, &val); + val &= (~0b00110000); + val |= longPressParams[param]; + _writeByte(AXP202_POK_SET, 1, &val); +} + +int AXP20X_Class::setShutdownTime(uint8_t param) +{ + uint8_t val; + if (!_init)return AXP_NOT_INIT; + if (param > sizeof(shutdownParams) / sizeof(shutdownParams[0]))return AXP_INVALID; + _readByte(AXP202_POK_SET, 1, &val); + val &= (~0b00000011); + val |= shutdownParams[param]; + _writeByte(AXP202_POK_SET, 1, &val); +} + +int AXP20X_Class::setTimeOutShutdown(bool en) +{ + uint8_t val; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_POK_SET, 1, &val); + if (en) + val |= (1 << 3); + else + val &= (~(1 << 3)); + _writeByte(AXP202_POK_SET, 1, &val); +} + + +int AXP20X_Class::shutdown() +{ + uint8_t val; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_OFF_CTL, 1, &val); + val |= (1 << 7); + _writeByte(AXP202_OFF_CTL, 1, &val); +} + + +float AXP20X_Class::getSettingChargeCurrent() +{ + uint8_t val; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_CHARGE1, 1, &val); + val &= 0b00000111; + float cur = 300.0 + val * 100.0; + AXP_DEBUG("Setting Charge current : %.2f mA\n", cur); + return cur; +} + +bool AXP20X_Class::isChargeingEnable() +{ + uint8_t val; + if (!_init)return false; + _readByte(AXP202_CHARGE1, 1, &val); + if (val & (1 << 7)) { + AXP_DEBUG("Charging enable is enable\n"); + val = true; + } else { + AXP_DEBUG("Charging enable is disable\n"); + val = false; + } + return val; +} + +int AXP20X_Class::enableChargeing(bool en) +{ + uint8_t val; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_CHARGE1, 1, &val); + val |= (1 << 7); + _writeByte(AXP202_CHARGE1, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setChargingTargetVoltage(axp_chargeing_vol_t param) +{ + uint8_t val; + if (!_init)return AXP_NOT_INIT; + if (param > sizeof(targetVolParams) / sizeof(targetVolParams[0]))return AXP_INVALID; + _readByte(AXP202_CHARGE1, 1, &val); + val &= ~(0b01100000); + val |= targetVolParams[param]; + _writeByte(AXP202_CHARGE1, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::getBattPercentage() +{ + if (!_init)return AXP_NOT_INIT; + uint8_t val; + _readByte(AXP202_BATT_PERCENTAGE, 1, &val); + if (!(val & BIT_MASK(7))) { + return val & (~BIT_MASK(7)); + } + return 0; +} + + + +int AXP20X_Class::setChgLEDMode(uint8_t mode) +{ + uint8_t val; + _readByte(AXP202_OFF_CTL, 1, &val); + val |= BIT_MASK(3); + switch (mode) { + case AXP20X_LED_OFF: + val &= 0b11001111; + _writeByte(AXP202_OFF_CTL, 1, &val); + break; + case AXP20X_LED_BLINK_1HZ: + val &= 0b11001111; + val |= 0b00010000; + _writeByte(AXP202_OFF_CTL, 1, &val); + break; + case AXP20X_LED_BLINK_4HZ: + val &= 0b11001111; + val |= 0b00100000; + _writeByte(AXP202_OFF_CTL, 1, &val); + break; + case AXP20X_LED_LOW_LEVEL: + val &= 0b11001111; + val |= 0b00110000; + _writeByte(AXP202_OFF_CTL, 1, &val); + break; + default: + break; + } + return AXP_PASS; +} + +int AXP20X_Class::debugCharging() +{ + uint8_t val; + _readByte(AXP202_CHARGE1, 1, &val); + AXP_DEBUG("SRC REG:0x%x\n", val); + if (val & (1 << 7)) { + AXP_DEBUG("Charging enable is enable\n"); + } else { + AXP_DEBUG("Charging enable is disable\n"); + } + AXP_DEBUG("Charging target-voltage : 0x%x\n", ((val & 0b01100000) >> 5 ) & 0b11); + if (val & (1 << 4)) { + AXP_DEBUG("end when the charge current is lower than 15%% of the set value\n"); + } else { + AXP_DEBUG(" end when the charge current is lower than 10%% of the set value\n"); + } + val &= 0b00000111; + float cur = 300.0 + val * 100.0; + AXP_DEBUG("Charge current : %.2f mA\n", cur); +} + + +int AXP20X_Class::debugStatus() +{ + if (!_init)return AXP_NOT_INIT; + uint8_t val, val1, val2; + _readByte(AXP202_STATUS, 1, &val); + _readByte(AXP202_MODE_CHGSTATUS, 1, &val1); + _readByte(AXP202_IPS_SET, 1, &val2); + AXP_DEBUG("AXP202_STATUS: AXP202_MODE_CHGSTATUS AXP202_IPS_SET\n"); + AXP_DEBUG("0x%x\t\t\t 0x%x\t\t\t 0x%x\n", val, val1, val2); +} + + +int AXP20X_Class::limitingOff() +{ + if (!_init)return AXP_NOT_INIT; + uint8_t val; + _readByte(AXP202_IPS_SET, 1, &val); + if (_chip_id == AXP202_CHIP_ID) { + val |= 0x03; + } else { + val &= ~(1 << 1); + } + _writeByte(AXP202_IPS_SET, 1, &val); + return AXP_PASS; +} + +// Only AXP129 chip +int AXP20X_Class::setDCDC1Voltage(uint16_t mv) +{ + if (!_init)return AXP_NOT_INIT; + if (_chip_id != AXP192_CHIP_ID) return AXP_FAIL; + if (mv < 700) { + AXP_DEBUG("DCDC1:Below settable voltage:700mV~3500mV"); + mv = 700; + } + if (mv > 3500) { + AXP_DEBUG("DCDC1:Above settable voltage:700mV~3500mV"); + mv = 3500; + } + uint8_t val = (mv - 700) / 25; + _writeByte(AXP192_DC1_VLOTAGE, 1, &val); + return AXP_PASS; +} + +// Only AXP129 chip +uint16_t AXP20X_Class::getDCDC1Voltage() +{ + if (_chip_id != AXP192_CHIP_ID) return AXP_FAIL; + uint8_t val = 0; + _readByte(AXP192_DC1_VLOTAGE, 1, &val); + return val * 25 + 700; +} + + +int AXP20X_Class::setGPIO0Voltage(uint8_t param) +{ + uint8_t params[] = { + 0b11111000, + 0b11111001, + 0b11111010, + 0b11111011, + 0b11111100, + 0b11111101, + 0b11111110, + 0b11111111, + }; + if (!_init)return AXP_NOT_INIT; + if (param > sizeof(params) / sizeof(params[0]))return AXP_INVALID; + uint8_t val = 0; + _readByte(AXP202_GPIO0_VOL, 1, &val); + val &= 0b11111000; + val |= params[param]; + _writeByte(AXP202_GPIO0_VOL, 1, &val); + return AXP_PASS; +} + +int AXP20X_Class::setGPIO0Level(uint8_t level) +{ + uint8_t val = 0; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_GPIO0_CTL, 1, &val); + val = level ? val & 0b11111000 : (val & 0b11111000) | 0b00000001; + _writeByte(AXP202_GPIO0_CTL, 1, &val); + return AXP_PASS; +} +int AXP20X_Class::setGPIO1Level(uint8_t level) +{ + uint8_t val = 0; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_GPIO1_CTL, 1, &val); + val = level ? val & 0b11111000 : (val & 0b11111000) | 0b00000001; + _writeByte(AXP202_GPIO1_CTL, 1, &val); + return AXP_PASS; +} + + + +int AXP20X_Class::readGpioStatus() +{ + uint8_t val = 0; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_GPIO012_SIGNAL, 1, &val); + _gpio[0] = val & BIT_MASK(4); + _gpio[1] = val & BIT_MASK(5); + _gpio[2] = val & BIT_MASK(6); + _readByte(AXP202_GPIO3_CTL, 1, &val); + _gpio[3] = val & 1; + return AXP_PASS; +} + +int AXP20X_Class::readGpio0Level() +{ + return _gpio[0]; +} + +int AXP20X_Class::readGpio1Level() +{ + return _gpio[1]; +} + +int AXP20X_Class::readGpio2Level() +{ + return _gpio[2]; +} + + +int AXP20X_Class::setGpio2Mode(uint8_t mode) +{ + uint8_t params[] = { + 0b11111000, + 0b11111001, + 0b11111010, + }; + if (!_init)return AXP_NOT_INIT; + if (mode > sizeof(params) / sizeof(params[0]))return AXP_INVALID; + uint8_t val = 0; + _readByte(AXP202_GPIO2_CTL, 1, &val); + val &= params[0]; + val |= params[mode]; + _writeByte(AXP202_GPIO2_CTL, 1, &val); + return AXP_PASS; +} + + + +int AXP20X_Class::setGpio3Mode(uint8_t mode) +{ + uint8_t val = 0; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_GPIO3_CTL, 1, &val); + if (mode == AXP202_GPIO3_DIGITAL_INPUT) { + val |= BIT_MASK(2); + } else if (mode == AXP202_GPIO3_OPEN_DRAIN_OUTPUT) { + val &= ~BIT_MASK(2); + } else { + return AXP_INVALID; + } + return AXP_PASS; +} + +int AXP20X_Class::setGpio3Level(uint8_t level) +{ + uint8_t val = 0; + if (!_init)return AXP_NOT_INIT; + _readByte(AXP202_GPIO3_CTL, 1, &val); + if (!(val & BIT_MASK(2))) { + return AXP_FAIL; + } + val = level ? val & (~BIT_MASK(1)) : val | BIT_MASK(1); + _writeByte(AXP202_GPIO3_CTL, 1, &val); +} + +int AXP20X_Class::_setGpioInterrupt(uint8_t *val, int mode, bool en) +{ + switch (mode) { + case RISING: + *val = en ? *val | BIT_MASK(7) : *val & (~BIT_MASK(7)); + break; + case FALLING: + *val = en ? *val | BIT_MASK(6) : *val & (~BIT_MASK(6)); + break; + default: + break; + } +} + +int AXP20X_Class::setGpioInterruptMode(uint8_t gpio, int mode, bool en) +{ + uint8_t val = 0; + if (!_init)return AXP_NOT_INIT; + switch (gpio) { + case AXP202_GPIO0: + _readByte(AXP202_GPIO0_CTL, 1, &val); + _setGpioInterrupt(&val, mode, en); + break; + case AXP202_GPIO1: + _readByte(AXP202_GPIO1_CTL, 1, &val); + _setGpioInterrupt(&val, mode, en); + break; + case AXP202_GPIO2: + _readByte(AXP202_GPIO2_CTL, 1, &val); + _setGpioInterrupt(&val, mode, en); + break; + case AXP202_GPIO3: + _readByte(AXP202_GPIO3_CTL, 1, &val); + _setGpioInterrupt(&val, mode, en); + break; + } +} + + +int AXP20X_Class::gpio0Setting(axp192_gpio0_mode_t mode) +{ + uint8_t rVal; + if (!_init)return AXP_NOT_INIT; + if (_chip_id == AXP192_CHIP_ID ) { + _readByte(AXP192_GPIO0_CTL, 1, &rVal); + rVal &= 0xF8; + rVal |= mode; + _writeByte(AXP192_GPIO0_CTL, 1, &rVal); + return AXP_PASS; + } + return AXP_FAIL; +} + + +int AXP20X_Class::gpio0SetVoltage(axp192_gpio_voltage_t vol) +{ + uint8_t rVal; + if (!_init)return AXP_NOT_INIT; + if (_chip_id == AXP192_CHIP_ID) { + _readByte(AXP192_GPIO0_VOL, 1, &rVal); + rVal &= 0x0F; + rVal |= (vol << 4); + _writeByte(AXP192_GPIO0_VOL, 1, &rVal); + return AXP_PASS; + } + return AXP_FAIL; +} + +uint16_t AXP20X_Class::gpio0GetVoltage() +{ + uint8_t rVal; + if (!_init)return AXP_NOT_INIT; + if (_chip_id == AXP192_CHIP_ID) { + _readByte(AXP192_GPIO0_VOL, 1, &rVal); + rVal &= 0xF0; + rVal >>= 4; + return rVal; + } + return 0; +} \ No newline at end of file diff --git a/lib/AXP202X/src/axp20x.h b/lib/AXP202X/src/axp20x.h new file mode 100644 index 00000000..e86a4714 --- /dev/null +++ b/lib/AXP202X/src/axp20x.h @@ -0,0 +1,766 @@ +///////////////////////////////////////////////////////////////// +/* +MIT License + +Copyright (c) 2019 lewis he + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +axp20x.h - Arduino library for X-Power AXP202 chip. +Created by Lewis he on April 1, 2019. +github:https://github.com/lewisxhe/AXP202X_Libraries +*/ +///////////////////////////////////////////////////////////////// +#pragma once + +#include +#include + +// #define AXP_DEBUG_PORT Serial +#ifdef AXP_DEBUG_PORT +#define AXP_DEBUG(fmt, ...) AXP_DEBUG_PORT.printf_P( (PGM_P)PSTR(fmt), ## __VA_ARGS__ ) +#else +#define AXP_DEBUG(...) +#endif + +#ifndef RISING +#define RISING 0x01 +#endif + +#ifndef FALLING +#define FALLING 0x02 +#endif + +//! Error Code +#define AXP_PASS 0 +#define AXP_FAIL -1 +#define AXP_INVALID -2 +#define AXP_NOT_INIT -3 + +//! Chip Address +#define AXP202_SLAVE_ADDRESS (0x35) +#define AXP192_SLAVE_ADDRESS (0x34) + +//! Chip ID +#define AXP202_CHIP_ID 0x41 +#define AXP192_CHIP_ID 0x03 + +//! REG MAP +#define AXP202_STATUS (0x00) +#define AXP202_MODE_CHGSTATUS (0x01) +#define AXP202_OTG_STATUS (0x02) +#define AXP202_IC_TYPE (0x03) +#define AXP202_DATA_BUFFER1 (0x04) +#define AXP202_DATA_BUFFER2 (0x05) +#define AXP202_DATA_BUFFER3 (0x06) +#define AXP202_DATA_BUFFER4 (0x07) +#define AXP202_DATA_BUFFER5 (0x08) +#define AXP202_DATA_BUFFER6 (0x09) +#define AXP202_DATA_BUFFER7 (0x0A) +#define AXP202_DATA_BUFFER8 (0x0B) +#define AXP202_DATA_BUFFER9 (0x0C) +#define AXP202_DATA_BUFFERA (0x0D) +#define AXP202_DATA_BUFFERB (0x0E) +#define AXP202_DATA_BUFFERC (0x0F) +#define AXP202_LDO234_DC23_CTL (0x12) +#define AXP202_DC2OUT_VOL (0x23) +#define AXP202_LDO3_DC2_DVM (0x25) +#define AXP202_DC3OUT_VOL (0x27) +#define AXP202_LDO24OUT_VOL (0x28) +#define AXP202_LDO3OUT_VOL (0x29) +#define AXP202_IPS_SET (0x30) +#define AXP202_VOFF_SET (0x31) +#define AXP202_OFF_CTL (0x32) +#define AXP202_CHARGE1 (0x33) +#define AXP202_CHARGE2 (0x34) +#define AXP202_BACKUP_CHG (0x35) +#define AXP202_POK_SET (0x36) +#define AXP202_DCDC_FREQSET (0x37) +#define AXP202_VLTF_CHGSET (0x38) +#define AXP202_VHTF_CHGSET (0x39) +#define AXP202_APS_WARNING1 (0x3A) +#define AXP202_APS_WARNING2 (0x3B) +#define AXP202_TLTF_DISCHGSET (0x3C) +#define AXP202_THTF_DISCHGSET (0x3D) +#define AXP202_DCDC_MODESET (0x80) +#define AXP202_ADC_EN1 (0x82) +#define AXP202_ADC_EN2 (0x83) +#define AXP202_ADC_SPEED (0x84) +#define AXP202_ADC_INPUTRANGE (0x85) +#define AXP202_ADC_IRQ_RETFSET (0x86) +#define AXP202_ADC_IRQ_FETFSET (0x87) +#define AXP202_TIMER_CTL (0x8A) +#define AXP202_VBUS_DET_SRP (0x8B) +#define AXP202_HOTOVER_CTL (0x8F) +#define AXP202_GPIO0_CTL (0x90) +#define AXP202_GPIO0_VOL (0x91) +#define AXP202_GPIO1_CTL (0x92) +#define AXP202_GPIO2_CTL (0x93) +#define AXP202_GPIO012_SIGNAL (0x94) +#define AXP202_GPIO3_CTL (0x95) +#define AXP202_INTEN1 (0x40) +#define AXP202_INTEN2 (0x41) +#define AXP202_INTEN3 (0x42) +#define AXP202_INTEN4 (0x43) +#define AXP202_INTEN5 (0x44) +#define AXP202_INTSTS1 (0x48) +#define AXP202_INTSTS2 (0x49) +#define AXP202_INTSTS3 (0x4A) +#define AXP202_INTSTS4 (0x4B) +#define AXP202_INTSTS5 (0x4C) + +//Irq control register +#define AXP192_INTEN1 (0x40) +#define AXP192_INTEN2 (0x41) +#define AXP192_INTEN3 (0x42) +#define AXP192_INTEN4 (0x43) +#define AXP192_INTEN5 (0x4A) +//Irq status register +#define AXP192_INTSTS1 (0x44) +#define AXP192_INTSTS2 (0x45) +#define AXP192_INTSTS3 (0x46) +#define AXP192_INTSTS4 (0x47) +#define AXP192_INTSTS5 (0x4D) + + +#define AXP192_DC1_VLOTAGE (0x26) +#define AXP192_LDO23OUT_VOL (0x28) +#define AXP192_GPIO0_CTL (0x90) +#define AXP192_GPIO0_VOL (0x91) + + +/* axp 20 adc data register */ +#define AXP202_BAT_AVERVOL_H8 (0x78) +#define AXP202_BAT_AVERVOL_L4 (0x79) +#define AXP202_BAT_AVERCHGCUR_H8 (0x7A) +#define AXP202_BAT_AVERCHGCUR_L4 (0x7B) +#define AXP202_BAT_VOL_H8 (0x50) +#define AXP202_BAT_VOL_L4 (0x51) +#define AXP202_ACIN_VOL_H8 (0x56) +#define AXP202_ACIN_VOL_L4 (0x57) +#define AXP202_ACIN_CUR_H8 (0x58) +#define AXP202_ACIN_CUR_L4 (0x59) +#define AXP202_VBUS_VOL_H8 (0x5A) +#define AXP202_VBUS_VOL_L4 (0x5B) +#define AXP202_VBUS_CUR_H8 (0x5C) +#define AXP202_VBUS_CUR_L4 (0x5D) +#define AXP202_INTERNAL_TEMP_H8 (0x5E) +#define AXP202_INTERNAL_TEMP_L4 (0x5F) +#define AXP202_TS_IN_H8 (0x62) +#define AXP202_TS_IN_L4 (0x63) +#define AXP202_GPIO0_VOL_ADC_H8 (0x64) +#define AXP202_GPIO0_VOL_ADC_L4 (0x65) +#define AXP202_GPIO1_VOL_ADC_H8 (0x66) +#define AXP202_GPIO1_VOL_ADC_L4 (0x67) + +#define AXP202_BAT_AVERDISCHGCUR_H8 (0x7C) +#define AXP202_BAT_AVERDISCHGCUR_L5 (0x7D) +#define AXP202_APS_AVERVOL_H8 (0x7E) +#define AXP202_APS_AVERVOL_L4 (0x7F) +#define AXP202_INT_BAT_CHGCUR_H8 (0xA0) +#define AXP202_INT_BAT_CHGCUR_L4 (0xA1) +#define AXP202_EXT_BAT_CHGCUR_H8 (0xA2) +#define AXP202_EXT_BAT_CHGCUR_L4 (0xA3) +#define AXP202_INT_BAT_DISCHGCUR_H8 (0xA4) +#define AXP202_INT_BAT_DISCHGCUR_L4 (0xA5) +#define AXP202_EXT_BAT_DISCHGCUR_H8 (0xA6) +#define AXP202_EXT_BAT_DISCHGCUR_L4 (0xA7) +#define AXP202_BAT_CHGCOULOMB3 (0xB0) +#define AXP202_BAT_CHGCOULOMB2 (0xB1) +#define AXP202_BAT_CHGCOULOMB1 (0xB2) +#define AXP202_BAT_CHGCOULOMB0 (0xB3) +#define AXP202_BAT_DISCHGCOULOMB3 (0xB4) +#define AXP202_BAT_DISCHGCOULOMB2 (0xB5) +#define AXP202_BAT_DISCHGCOULOMB1 (0xB6) +#define AXP202_BAT_DISCHGCOULOMB0 (0xB7) +#define AXP202_COULOMB_CTL (0xB8) +#define AXP202_BAT_POWERH8 (0x70) +#define AXP202_BAT_POWERM8 (0x71) +#define AXP202_BAT_POWERL8 (0x72) + +#define AXP202_VREF_TEM_CTRL (0xF3) +#define AXP202_BATT_PERCENTAGE (0xB9) + + +/* bit definitions for AXP events ,irq event */ +/* AXP202 */ +#define AXP202_IRQ_USBLO (1) +#define AXP202_IRQ_USBRE (2) +#define AXP202_IRQ_USBIN (3) +#define AXP202_IRQ_USBOV (4) +#define AXP202_IRQ_ACRE (5) +#define AXP202_IRQ_ACIN (6) +#define AXP202_IRQ_ACOV (7) + +#define AXP202_IRQ_TEMLO (8) +#define AXP202_IRQ_TEMOV (9) +#define AXP202_IRQ_CHAOV (10) +#define AXP202_IRQ_CHAST (11) +#define AXP202_IRQ_BATATOU (12) +#define AXP202_IRQ_BATATIN (13) +#define AXP202_IRQ_BATRE (14) +#define AXP202_IRQ_BATIN (15) + +#define AXP202_IRQ_POKLO (16) +#define AXP202_IRQ_POKSH (17) +#define AXP202_IRQ_LDO3LO (18) +#define AXP202_IRQ_DCDC3LO (19) +#define AXP202_IRQ_DCDC2LO (20) +#define AXP202_IRQ_CHACURLO (22) +#define AXP202_IRQ_ICTEMOV (23) + +#define AXP202_IRQ_EXTLOWARN2 (24) +#define AXP202_IRQ_EXTLOWARN1 (25) +#define AXP202_IRQ_SESSION_END (26) +#define AXP202_IRQ_SESS_AB_VALID (27) +#define AXP202_IRQ_VBUS_UN_VALID (28) +#define AXP202_IRQ_VBUS_VALID (29) +#define AXP202_IRQ_PDOWN_BY_NOE (30) +#define AXP202_IRQ_PUP_BY_NOE (31) + +#define AXP202_IRQ_GPIO0TG (32) +#define AXP202_IRQ_GPIO1TG (33) +#define AXP202_IRQ_GPIO2TG (34) +#define AXP202_IRQ_GPIO3TG (35) +#define AXP202_IRQ_PEKFE (37) +#define AXP202_IRQ_PEKRE (38) +#define AXP202_IRQ_TIMER (39) + + +//Signal Capture +#define AXP202_BATT_VOLTAGE_STEP (1.1F) +#define AXP202_BATT_DISCHARGE_CUR_STEP (0.5F) +#define AXP202_BATT_CHARGE_CUR_STEP (0.5F) +#define AXP202_ACIN_VOLTAGE_STEP (1.7F) +#define AXP202_ACIN_CUR_STEP (0.625F) +#define AXP202_VBUS_VOLTAGE_STEP (1.7F) +#define AXP202_VBUS_CUR_STEP (0.375F) +#define AXP202_INTENAL_TEMP_STEP (0.1F) +#define AXP202_APS_VOLTAGE_STEP (1.4F) +#define AXP202_TS_PIN_OUT_STEP (0.8F) +#define AXP202_GPIO0_STEP (0.5F) +#define AXP202_GPIO1_STEP (0.5F) + + + + +#define FORCED_OPEN_DCDC3(x) (x |= AXP202_DCDC3) +#define BIT_MASK(x) (1 << x) +#define IS_OPEN(reg,channel) (bool)(reg & BIT_MASK(channel)) + +#define AXP202_ON 1 +#define AXP202_OFF 0 + + +enum { + AXP202_EXTEN = 0, + AXP202_DCDC3 = 1, + AXP202_LDO2 = 2, + AXP202_LDO4 = 3, + AXP202_DCDC2 = 4, + AXP202_LDO3 = 6, + AXP202_OUTPUT_MAX, +}; + + +enum { + AXP192_DCDC1 = 0, + AXP192_DCDC3 = 1, + AXP192_LDO2 = 2, + AXP192_LDO3 = 3, + AXP192_DCDC2 = 4, + AXP192_EXTEN = 6, + AXP192_OUTPUT_MAX, +}; + + +typedef enum { + AXP202_STARTUP_TIME_128MS, + AXP202_STARTUP_TIME_3S, + AXP202_STARTUP_TIME_1S, + AXP202_STARTUP_TIME_2S, +} axp202_startup_time_t; + + +typedef enum { + AXP192_STARTUP_TIME_128MS, + AXP192_STARTUP_TIME_512MS, + AXP192_STARTUP_TIME_1S, + AXP192_STARTUP_TIME_2S, +} axp192_startup_time_t; + + + +typedef enum { + AXP_LONGPRESS_TIME_1S, + AXP_LONGPRESS_TIME_1S5, + AXP_LONGPRESS_TIME_2S, + AXP_LONGPRESS_TIME_2S5, +} axp_loonPress_time_t; + + +typedef enum { + AXP_POWER_OFF_TIME_4S, + AXP_POWER_OFF_TIME_65, + AXP_POWER_OFF_TIME_8S, + AXP_POWER_OFF_TIME_16S, +} axp_poweroff_time_t; + +//REG 33H: Charging control 1 Charging target-voltage setting +typedef enum { + AXP202_TARGET_VOL_4_1V, + AXP202_TARGET_VOL_4_15V, + AXP202_TARGET_VOL_4_2V, + AXP202_TARGET_VOL_4_36V +} axp_chargeing_vol_t; + +//REG 82H: ADC Enable 1 register Parameter +typedef enum { + AXP202_BATT_VOL_ADC1 = 1 << 7, + AXP202_BATT_CUR_ADC1 = 1 << 6, + AXP202_ACIN_VOL_ADC1 = 1 << 5, + AXP202_ACIN_CUR_ADC1 = 1 << 4, + AXP202_VBUS_VOL_ADC1 = 1 << 3, + AXP202_VBUS_CUR_ADC1 = 1 << 2, + AXP202_APS_VOL_ADC1 = 1 << 1, + AXP202_TS_PIN_ADC1 = 1 << 0 +} axp_adc1_func_t; + +// REG 83H: ADC Enable 2 register Parameter +typedef enum { + AXP202_TEMP_MONITORING_ADC2 = 1 << 7, + AXP202_GPIO1_FUNC_ADC2 = 1 << 3, + AXP202_GPIO0_FUNC_ADC2 = 1 << 2 +} axp_adc2_func_t; + +typedef enum { + AXP202_LDO3_MODE_LDO, + AXP202_LDO3_MODE_DCIN +} axp202_ldo3_mode_t; + + +typedef enum { + //IRQ1 + AXP202_VBUS_VHOLD_LOW_IRQ = 1 << 1, + AXP202_VBUS_REMOVED_IRQ = 1 << 2, + AXP202_VBUS_CONNECT_IRQ = 1 << 3, + AXP202_VBUS_OVER_VOL_IRQ = 1 << 4, + AXP202_ACIN_REMOVED_IRQ = 1 << 5, + AXP202_ACIN_CONNECT_IRQ = 1 << 6, + AXP202_ACIN_OVER_VOL_IRQ = 1 << 7, + //IRQ2 + AXP202_BATT_LOW_TEMP_IRQ = 1 << 8, + AXP202_BATT_OVER_TEMP_IRQ = 1 << 9, + AXP202_CHARGING_FINISHED_IRQ = 1 << 10, + AXP202_CHARGING_IRQ = 1 << 11, + AXP202_BATT_EXIT_ACTIVATE_IRQ = 1 << 12, + AXP202_BATT_ACTIVATE_IRQ = 1 << 13, + AXP202_BATT_REMOVED_IRQ = 1 << 14, + AXP202_BATT_CONNECT_IRQ = 1 << 15, + //IRQ3 + AXP202_PEK_LONGPRESS_IRQ = 1 << 16, + AXP202_PEK_SHORTPRESS_IRQ = 1 << 17, + AXP202_LDO3_LOW_VOL_IRQ = 1 << 18, + AXP202_DC3_LOW_VOL_IRQ = 1 << 19, + AXP202_DC2_LOW_VOL_IRQ = 1 << 20, + AXP202_CHARGE_LOW_CUR_IRQ = 1 << 21, + AXP202_CHIP_TEMP_HIGH_IRQ = 1 << 22, + + //IRQ4 + AXP202_APS_LOW_VOL_LEVEL2_IRQ = 1 << 24, + APX202_APS_LOW_VOL_LEVEL1_IRQ = 1 << 25, + AXP202_VBUS_SESSION_END_IRQ = 1 << 26, + AXP202_VBUS_SESSION_AB_IRQ = 1 << 27, + AXP202_VBUS_INVALID_IRQ = 1 << 28, + AXP202_VBUS_VAILD_IRQ = 1 << 29, + AXP202_NOE_OFF_IRQ = 1 << 30, + AXP202_NOE_ON_IRQ = 1 << 31, + AXP202_ALL_IRQ = 0xFFFF + +} axp_irq_t; + +typedef enum { + AXP202_LDO4_1250MV, + AXP202_LDO4_1300MV, + AXP202_LDO4_1400MV, + AXP202_LDO4_1500MV, + AXP202_LDO4_1600MV, + AXP202_LDO4_1700MV, + AXP202_LDO4_1800MV, + AXP202_LDO4_1900MV, + AXP202_LDO4_2000MV, + AXP202_LDO4_2500MV, + AXP202_LDO4_2700MV, + AXP202_LDO4_2800MV, + AXP202_LDO4_3000MV, + AXP202_LDO4_3100MV, + AXP202_LDO4_3200MV, + AXP202_LDO4_3300MV, + AXP202_LDO4_MAX, +} axp_ldo4_table_t; + +typedef enum { + AXP20X_LED_OFF, + AXP20X_LED_BLINK_1HZ, + AXP20X_LED_BLINK_4HZ, + AXP20X_LED_LOW_LEVEL, +} axp_chgled_mode_t; + + +typedef enum { + AXP202_GPIO_1V8, + AXP202_GPIO_2V5, + AXP202_GPIO_2V8, + AXP202_GPIO_3V0, + AXP202_GPIO_3V1, + AXP202_GPIO_3V3, + AXP202_GPIO_3V4, + AXP202_GPIO_3V5, +} axp202_gpio_voltage_t; + +typedef enum { + AXP202_GPIO2_OUTPUT_LOW, + AXP202_GPIO2_FLOATING, + AXP202_GPIO3_INPUT, +} axp202_gpio2_mode_t; + +typedef enum { + AXP202_GPIO3_DIGITAL_INPUT, + AXP202_GPIO3_OPEN_DRAIN_OUTPUT, +} axp202_gpio3_mode_t; + +typedef enum { + AXP202_GPIO3_OUTPUT_LOW, + AXP202_GPIO3_FLOATING, +} axp202_gpio3_output_t; + + +typedef enum { + AXP202_GPIO0, + AXP202_GPIO1, + AXP202_GPIO2, + AXP202_GPIO3, +} axp202_gpio_t; + + +typedef enum { + AXP_ADC_SAMPLING_RATE_25HZ = 0, + AXP_ADC_SAMPLING_RATE_50HZ = 1, + AXP_ADC_SAMPLING_RATE_100HZ = 2, + AXP_ADC_SAMPLING_RATE_200HZ = 3, +} axp_adc_sampling_rate_t; + + +typedef enum { + AXP192_GPIO0_NMOD_OUTPUT = 0, + AXP192_GPIO0_INPUT = 1, + AXP192_GPIO0_LDO_OUTPUT = 2, + AXP192_GPIO0_ADC_INPUT = 4, + AXP192_GPIO0_OUTPUT_LOW = 5, + AXP192_GPIO0_FLOATING = 7 +} axp192_gpio0_mode_t; + + +typedef enum { + AXP192_GPIO_1V8, + AXP192_GPIO_1V9, + AXP192_GPIO_2V0, + AXP192_GPIO_2V1, + AXP192_GPIO_2V2, + AXP192_GPIO_2V3, + AXP192_GPIO_2V4, + AXP192_GPIO_2V5, + AXP192_GPIO_2V6, + AXP192_GPIO_2V7, + AXP192_GPIO_2V8, + AXP192_GPIO_2V9, + AXP192_GPIO_3V0, + AXP192_GPIO_3V1, + AXP192_GPIO_3V2, + AXP192_GPIO_3V3, +} axp192_gpio_voltage_t; + + +class AXP20X_Class +{ +public: + int begin(TwoWire &port = Wire, uint8_t addr = AXP202_SLAVE_ADDRESS); + + // Power Output Control + int setPowerOutPut(uint8_t ch, bool en); + + bool isBatteryConnect(); + bool isChargeing(); + bool isLDO2Enable(); + bool isLDO3Enable(); + bool isLDO4Enable(); + bool isDCDC3Enable(); + bool isDCDC2Enable(); + bool isChargeingEnable(); + bool isVBUSPlug(); + + //Only axp192 chip + bool isDCDC1Enable(); + //Only axp192 chip + bool isExtenEnable(); + + //IRQ Status + bool isAcinOverVoltageIRQ(); + bool isAcinPlugInIRQ(); + bool isAcinRemoveIRQ(); + bool isVbusOverVoltageIRQ(); + bool isVbusPlugInIRQ(); + bool isVbusRemoveIRQ(); + bool isVbusLowVHOLDIRQ(); + + bool isBattPlugInIRQ(); + bool isBattRemoveIRQ(); + bool isBattEnterActivateIRQ(); + bool isBattExitActivateIRQ(); + bool isChargingIRQ(); + bool isChargingDoneIRQ(); + bool isBattTempLowIRQ(); + bool isBattTempHighIRQ(); + + bool isPEKShortPressIRQ(); + bool isPEKLongtPressIRQ(); + + //! Group4 ADC data + float getAcinVoltage(); + float getAcinCurrent(); + float getVbusVoltage(); + float getVbusCurrent(); + float getTemp(); + float getTSTemp(); + float getGPIO0Voltage(); + float getGPIO1Voltage(); + float getBattInpower(); + float getBattVoltage(); + float getBattChargeCurrent(); + float getBattDischargeCurrent(); + float getSysIPSOUTVoltage(); + uint32_t getBattChargeCoulomb(); + uint32_t getBattDischargeCoulomb(); + float getSettingChargeCurrent(); + + int setChargingTargetVoltage(axp_chargeing_vol_t param); + int enableChargeing(bool en); + + int adc1Enable(uint16_t params, bool en); + int adc2Enable(uint16_t params, bool en); + + /** + * param: axp202_startup_time_t or axp192_startup_time_t + */ + int setStartupTime(uint8_t param); + + /** + * param: axp_loonPress_time_t + */ + int setlongPressTime(uint8_t param); + + /** + * @param param: axp_poweroff_time_t + */ + int setShutdownTime(uint8_t param); + + + int setTimeOutShutdown(bool en); + + int shutdown(); + + /** + * params: axp_irq_t + */ + int enableIRQ(uint32_t params, bool en); + int readIRQ(); + void clearIRQ(); + + + int setDCDC1Voltage(uint16_t mv); //! Only AXP192 support + // return mv + uint16_t getDCDC1Voltage(); //! Only AXP192 support + + + // ----------------- + int setDCDC2Voltage(uint16_t mv); + int setDCDC3Voltage(uint16_t mv); + int setLDO2Voltage(uint16_t mv); + int setLDO3Voltage(uint16_t mv); + + + int setLDO4Voltage(axp_ldo4_table_t param); //! Only axp202 support + + // return mv + uint16_t getLDO2Voltage(); + uint16_t getLDO3Voltage(); + uint16_t getDCDC2Voltage(); + uint16_t getDCDC3Voltage(); + + + /** + * @param mode: axp_chgled_mode_t + */ + int setChgLEDMode(uint8_t mode); + + + /** + * @param mode: axp202_ldo3_mode_t + */ + int setLDO3Mode(uint8_t mode); //! Only AXP202 support + + int getBattPercentage(); + + int debugCharging(); + int debugStatus(); + int limitingOff(); + + int setAdcSamplingRate(axp_adc_sampling_rate_t rate); + uint8_t getAdcSamplingRate(); + float getCoulombData(); + + + int gpio0Setting(axp192_gpio0_mode_t mode); //! Only axp192 + int gpio0SetVoltage(axp192_gpio_voltage_t vol); + uint16_t gpio0GetVoltage(); + + //! The following features have not been tested + /** + * @brief setGPIO0Voltage + * @note + * @param mv: axp202_gpio_voltage_t enum + * @retval + */ + int setGPIO0Voltage(uint8_t mv); + + /** + * @brief setGPIO0Level + * @note + * @param level: 0 or 1 + * @retval + */ + int setGPIO0Level(uint8_t level); + + /** + * @brief setGPIO1Level + * @note + * @param level: 0 or 1 + * @retval + */ + int setGPIO1Level(uint8_t level); + + /** + * @brief readGpioStatus + * @note + * @retval + */ + int readGpioStatus(); + + int readGpio0Level(); + + int readGpio1Level(); + + int readGpio2Level(); + + int setGpio2Mode(uint8_t mode); + + /** + * @brief setGpio3Mode + * @note Set GPIO3 mode, can only be set to output low level, floating, can not output high level + * @param mode: axp202_gpio3_mode_t enum + * @retval + */ + int setGpio3Mode(uint8_t mode); + + /** + * @brief setGpio3Level + * @note Can only be set when GPIO3 is configured as output mode + * @param level: axp202_gpio3_output_t enum + * @retval + */ + int setGpio3Level(uint8_t level); + + + /** + * @brief setGpioInterruptMode + * @note Interrupt can only be set when GPIO is configured as input mode + * @param gpio: axp202_gpio_t enum + * @param mode: RISING or FALLING + * @param en: true or false + * @retval + */ + int setGpioInterruptMode(uint8_t gpio, int mode, bool en); + +private: + + uint16_t _getRegistH8L5(uint8_t regh8, uint8_t regl4) + { + uint8_t hv, lv; + _readByte(regh8, 1, &hv); + _readByte(regl4, 1, &lv); + return (hv << 5) | (lv & 0x1F); + } + + uint16_t _getRegistResult(uint8_t regh8, uint8_t regl4) + { + uint8_t hv, lv; + _readByte(regh8, 1, &hv); + _readByte(regl4, 1, &lv); + return (hv << 4) | (lv & 0xF); + } + + int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data) + { + if (nbytes == 0 || !data) return -1; + _i2cPort->beginTransmission(_address); + _i2cPort->write(reg); + _i2cPort->endTransmission(); + _i2cPort->requestFrom(_address, nbytes); + uint8_t index = 0; + while (_i2cPort->available()) + data[index++] = _i2cPort->read(); + return 0; + } + + int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data) + { + if (nbytes == 0 || !data) return -1; + _i2cPort->beginTransmission(_address); + _i2cPort->write(reg); + for (uint8_t i = 0; i < nbytes; i++) { + _i2cPort->write(data[i]); + } + _i2cPort->endTransmission(); + return 0; + } + + int _setGpioInterrupt(uint8_t *val, int mode, bool en); + static const uint8_t startupParams[]; + static const uint8_t longPressParams[]; + static const uint8_t shutdownParams[]; + static const uint8_t targetVolParams[]; + static uint8_t _outputReg; + + uint8_t _address; + bool _init = false; + TwoWire *_i2cPort; + uint8_t _irq[5]; + uint8_t _chip_id; + uint8_t _gpio[4]; +}; diff --git a/src/i2cscan.cpp b/src/i2cscan.cpp new file mode 100644 index 00000000..35898f0d --- /dev/null +++ b/src/i2cscan.cpp @@ -0,0 +1,101 @@ +// Basic config +#include "globals.h" +#include "i2cscan.h" + +// Local logging tag +static const char TAG[] = __FILE__; + +#define SSD1306_PRIMARY_ADDRESS (0x3D) +#define SSD1306_SECONDARY_ADDRESS (0x3C) +#define BME_PRIMARY_ADDRESS (0x77) +#define BME_SECONDARY_ADDRESS (0x76) +#define AXP192_PRIMARY_ADDRESS (0x34) +#define MCP_24AA02E64_PRIMARY_ADDRESS (0x50) + +int i2c_scan(void) { + + int i2c_ret, addr; + int devices = 0; + + ESP_LOGI(TAG, "Starting I2C bus scan..."); + + for (addr = 8; addr <= 119; addr++) { + + // scan i2c bus with no more to 100KHz + Wire.begin(SDA, SCL, 100000); + Wire.beginTransmission(addr); + Wire.write(addr); + i2c_ret = Wire.endTransmission(); + + if (i2c_ret == 0) { + devices++; + + switch (addr) { + + case SSD1306_PRIMARY_ADDRESS: + case SSD1306_SECONDARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: SSD1306 Display controller", addr); + break; + + case BME_PRIMARY_ADDRESS: + case BME_SECONDARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: Bosch BME MEMS", addr); + break; + + case AXP192_PRIMARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: AXP192 power management", addr); +#ifdef HAS_PMU + AXP192_init(); +#endif + break; + + case MCP_24AA02E64_PRIMARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: 24AA02E64 serial EEPROM", addr); + break; + + default: + ESP_LOGI(TAG, "0x%X: Unknown device", addr); + break; + } + } // switch + } // for loop + + ESP_LOGI(TAG, "I2C scan done, %u devices found.", devices); + + return devices; +} + +#ifdef HAS_PMU + +void AXP192_init(void) { + + AXP20X_Class axp; + + if (axp.begin(Wire, AXP192_PRIMARY_ADDRESS)) + ESP_LOGI(TAG, "AXP192 PMU initialization failed"); + else { + + axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); + axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); + axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); + axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); + + /* + axp.setChgLEDMode(LED_BLINK_4HZ); + axp.setDCDC1Voltage(3300); + + pinMode(PMU_IRQ, INPUT_PULLUP); + attachInterrupt(PMU_IRQ, [] { pmu_irq = true; }, FALLING); + + axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); + axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | + AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, + 1); + axp.clearIRQ(); + */ + + ESP_LOGI(TAG, "AXP192 PMU initialized."); + } +#endif // HAS_PMU +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index f0a34b14..0dc90395 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -169,6 +169,8 @@ void setup() { ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); #endif + i2c_scan(); + #endif // verbose // read (and initialize on first run) runtime settings from NVRAM From c653462f901f7f56f6bba4f3661994258c66bd03 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 2 Sep 2019 18:17:37 +0200 Subject: [PATCH 050/105] create hal/ttgobeam10.h --- src/hal/ttgobeam10.h | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/hal/ttgobeam10.h diff --git a/src/hal/ttgobeam10.h b/src/hal/ttgobeam10.h new file mode 100644 index 00000000..95820098 --- /dev/null +++ b/src/hal/ttgobeam10.h @@ -0,0 +1,45 @@ +// clang-format off +// upload_speed 921600 +// board ttgo-t-beam + +#ifndef _TTGOBEAM_H +#define _TTGOBEAM_H + +#include + +// Hardware related definitions for TTGO T-Beam board +// (only) for newer T-Beam version T22_V10 +// pinouts taken from https://github.com/lewisxhe/TTGO-T-Beam + +#define HAS_LORA 1 // comment out if device shall not send data via LoRa +#define CFG_sx1276_radio 1 // HPD13A LoRa SoC +#define BOARD_HAS_PSRAM // use extra 4MB external RAM +#define HAS_BUTTON GPIO_NUM_36 // on board button (next to reset) +#define HAS_PMU 1 // AXP192 power management chip +#define PMU_INT GPIO_NUM_36 // AXP192 interrupt + +#define HAS_LED NOT_A_PIN + +// GPS settings +#define HAS_GPS 1 // use on board GPS +#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_34, GPIO_NUM_12 // UBlox NEO 6M + +// enable only if device has these sensors, otherwise comment these lines +// BME680 sensor on I2C bus +//#define HAS_BME 1 // Enable BME sensors in general +//#define HAS_BME680 SDA, SCL +//#define BME680_ADDR BME680_I2C_ADDR_PRIMARY // !! connect SDIO of BME680 to GND !! + +// display (if connected) +#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C +#define MY_OLED_SDA SDA +#define MY_OLED_SCL SCL +#define MY_OLED_RST U8X8_PIN_NONE +//#define DISPLAY_FLIP 1 // use if display is rotated + +// user defined sensors (if connected) +//#define HAS_SENSORS 1 // comment out if device has user defined sensors + +//#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature + +#endif From 98a2edb8a7a78804db49448a74268356902bd0f0 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 2 Sep 2019 18:18:06 +0200 Subject: [PATCH 051/105] AXP192 support fixes --- src/battery.cpp | 4 ++++ src/i2cscan.cpp | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/battery.cpp b/src/battery.cpp index 3af874d9..39b78683 100644 --- a/src/battery.cpp +++ b/src/battery.cpp @@ -52,6 +52,10 @@ uint16_t read_voltage() { digitalWrite(EXT_POWER_SW, EXT_POWER_OFF); #endif +#ifdef HAS_PMU + voltage = axp.getBattVoltage(); +#endif + return (uint16_t)voltage; #else return 0; diff --git a/src/i2cscan.cpp b/src/i2cscan.cpp index 35898f0d..fb07d034 100644 --- a/src/i2cscan.cpp +++ b/src/i2cscan.cpp @@ -80,9 +80,10 @@ void AXP192_init(void) { axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); - + axp.setChgLEDMode(AXP20X_LED_OFF); + //axp.setChgLEDMode(LED_BLINK_4HZ); + /* - axp.setChgLEDMode(LED_BLINK_4HZ); axp.setDCDC1Voltage(3300); pinMode(PMU_IRQ, INPUT_PULLUP); From 094d08601042263903eb8f0cb112c78e04cfed70 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 2 Sep 2019 18:18:34 +0200 Subject: [PATCH 052/105] v1.8.01 --- platformio.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 0fddc0b8..9b3f27da 100644 --- a/platformio.ini +++ b/platformio.ini @@ -19,6 +19,7 @@ halfile = generic.h ;halfile = ttgov21new.h ;halfile = ttgofox.h ;halfile = ttgobeam.h +;halfile = ttgobeam10.h ;halfile = fipy.h ;halfile = lopy.h ;halfile = lopy4.h @@ -42,7 +43,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.8.0 +release_version = 1.8.01 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 From ad9bd3e63e45e73972b0db59cff04f63ef8d0321 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 2 Sep 2019 20:45:40 +0200 Subject: [PATCH 053/105] i2cscan fixes --- src/i2cscan.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/i2cscan.cpp b/src/i2cscan.cpp index fb07d034..c57d0604 100644 --- a/src/i2cscan.cpp +++ b/src/i2cscan.cpp @@ -11,6 +11,7 @@ static const char TAG[] = __FILE__; #define BME_SECONDARY_ADDRESS (0x76) #define AXP192_PRIMARY_ADDRESS (0x34) #define MCP_24AA02E64_PRIMARY_ADDRESS (0x50) +#define QUECTEL_GPS_PRIMARY_ADDRESS (0x10) int i2c_scan(void) { @@ -49,6 +50,10 @@ int i2c_scan(void) { #endif break; + case QUECTEL_GPS_PRIMARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: Quectel GPS", addr); + break; + case MCP_24AA02E64_PRIMARY_ADDRESS: ESP_LOGI(TAG, "0x%X: 24AA02E64 serial EEPROM", addr); break; @@ -80,23 +85,26 @@ void AXP192_init(void) { axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); - axp.setChgLEDMode(AXP20X_LED_OFF); - //axp.setChgLEDMode(LED_BLINK_4HZ); - - /* axp.setDCDC1Voltage(3300); - - pinMode(PMU_IRQ, INPUT_PULLUP); - attachInterrupt(PMU_IRQ, [] { pmu_irq = true; }, FALLING); - + axp.setChgLEDMode(AXP20X_LED_BLINK_1HZ); + //axp.setChgLEDMode(AXP20X_LED_OFF); axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); + +#ifdef PMU_INT + pinMode(PMU_INT, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(PMU_INT), + [] { + ESP_LOGI(TAG, "Power source changed"); + /* put your code here */ + }, + FALLING); axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, 1); axp.clearIRQ(); - */ +#endif // PMU_INT ESP_LOGI(TAG, "AXP192 PMU initialized."); } -#endif // HAS_PMU -} \ No newline at end of file +} +#endif // HAS_PMU \ No newline at end of file From c97f7be1a55e41bf4fa42dfe96b55cfcec1a40d8 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 6 Sep 2019 15:19:23 +0200 Subject: [PATCH 054/105] add AXP202 library to platformio --- lib/AXP202X/.gitignore | 2 - lib/AXP202X/LICENSE | 21 - lib/AXP202X/README.md | 9 - lib/AXP202X/keywords.txt | 163 ----- lib/AXP202X/library.properties | 10 - lib/AXP202X/src/axp20x.cpp | 1160 -------------------------------- lib/AXP202X/src/axp20x.h | 766 --------------------- platformio.ini | 3 +- 8 files changed, 2 insertions(+), 2132 deletions(-) delete mode 100644 lib/AXP202X/.gitignore delete mode 100644 lib/AXP202X/LICENSE delete mode 100644 lib/AXP202X/README.md delete mode 100644 lib/AXP202X/keywords.txt delete mode 100644 lib/AXP202X/library.properties delete mode 100644 lib/AXP202X/src/axp20x.cpp delete mode 100644 lib/AXP202X/src/axp20x.h diff --git a/lib/AXP202X/.gitignore b/lib/AXP202X/.gitignore deleted file mode 100644 index 6d0ee45d..00000000 --- a/lib/AXP202X/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.vscode -.DS_Store \ No newline at end of file diff --git a/lib/AXP202X/LICENSE b/lib/AXP202X/LICENSE deleted file mode 100644 index 3b7bfa9f..00000000 --- a/lib/AXP202X/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 lewis he - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/AXP202X/README.md b/lib/AXP202X/README.md deleted file mode 100644 index 8623bc5a..00000000 --- a/lib/AXP202X/README.md +++ /dev/null @@ -1,9 +0,0 @@ -AXP202X_Library -===================================== -- axp192 partial support, the function is not fully tested, please refer to the manual -- The `setPowerOutPut` function has forced DCDC3 to be turned on and cannot be controlled because T-Watch uses DCDC3 as the esp32 to power the main chip. If it is turned off, the hardware cannot be programmed. - - -TTGO invests time and resources to provide this open source code, please support TTGO and open source hardware by purchasing products from TTGO! - -Written by Lewis He for TTGO. MIT license, all text above must be included in any redistribution \ No newline at end of file diff --git a/lib/AXP202X/keywords.txt b/lib/AXP202X/keywords.txt deleted file mode 100644 index 55ffde3f..00000000 --- a/lib/AXP202X/keywords.txt +++ /dev/null @@ -1,163 +0,0 @@ -####################################### -# Syntax Coloring Map For X-Power AXP20X Library By lewis He -# github:https://github.com/lewisxhe -####################################### - -####################################### -# Datatypes (KEYWORD1) -####################################### -AXP20X_Class KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -begin KEYWORD2 -isChargeing KEYWORD2 -isLDO2Enable KEYWORD2 -isLDO3Enable KEYWORD2 -isLDO4Enable KEYWORD2 -isDCDC3Enable KEYWORD2 -isDCDC2Enable KEYWORD2 -isChargeingEnable KEYWORD2 -isAcinOverVoltageIRQ KEYWORD2 -isAcinPlugInIRQ KEYWORD2 -isAcinRemoveIRQ KEYWORD2 -isVbusOverVoltageIRQ KEYWORD2 -isVbusPlugInIRQ KEYWORD2 -isVbusRemoveIRQ KEYWORD2 -isVbusLowVHOLDIRQ KEYWORD2 -isBattPlugInIRQ KEYWORD2 -isBattRemoveIRQ KEYWORD2 -isBattEnterActivateIRQ KEYWORD2 -isBattExitActivateIRQ KEYWORD2 -isChargingIRQ KEYWORD2 -isChargingDoneIRQ KEYWORD2 -isBattTempLowIRQ KEYWORD2 -isBattTempHighIRQ KEYWORD2 -isPEKShortPressIRQ KEYWORD2 -isPEKLongtPressIRQ KEYWORD2 -getAcinVoltage KEYWORD2 -getAcinCurrent KEYWORD2 -getVbusVoltage KEYWORD2 -getVbusCurrent KEYWORD2 -getTemp KEYWORD2 -getTSTemp KEYWORD2 -getGPIO0Voltage KEYWORD2 -getGPIO1Voltage KEYWORD2 -getBattInpower KEYWORD2 -getBattVoltage KEYWORD2 -getBattChargeCurrent KEYWORD2 -getBattDischargeCurrent KEYWORD2 -getSysIPSOUTVoltage KEYWORD2 -getBattChargeCoulomb KEYWORD2 -getBattDischargeCoulomb KEYWORD2 -getSettingChargeCurrent KEYWORD2 -setChargingTargetVoltage KEYWORD2 -enableChargeing KEYWORD2 -adc1Enable KEYWORD2 -adc2Enable KEYWORD2 -setStartupTime KEYWORD2 -setlongPressTime KEYWORD2 -setShutdownTime KEYWORD2 -setTimeOutShutdown KEYWORD2 -enableIRQ KEYWORD2 -readIRQ KEYWORD2 -clearIRQ KEYWORD2 -setDCDC2Voltage KEYWORD2 -setDCDC3Voltage KEYWORD2 -setLDO2Voltage KEYWORD2 -setLDO3Voltage KEYWORD2 -setLDO4Voltage KEYWORD2 -getBattPercentage KEYWORD2 - -####################################### -# Instances (KEYWORD2) -####################################### - - -####################################### -# Constants (LITERAL1) -####################################### -AXP202_LDO4_1250MV LITERAL1 -AXP202_LDO4_1300MV LITERAL1 -AXP202_LDO4_1400MV LITERAL1 -AXP202_LDO4_1500MV LITERAL1 -AXP202_LDO4_1600MV LITERAL1 -AXP202_LDO4_1700MV LITERAL1 -AXP202_LDO4_1800MV LITERAL1 -AXP202_LDO4_1900MV LITERAL1 -AXP202_LDO4_2000MV LITERAL1 -AXP202_LDO4_2500MV LITERAL1 -AXP202_LDO4_2700MV LITERAL1 -AXP202_LDO4_2800MV LITERAL1 -AXP202_LDO4_3000MV LITERAL1 -AXP202_LDO4_3100MV LITERAL1 -AXP202_LDO4_3200MV LITERAL1 -AXP202_LDO4_3300MV LITERAL1 - -AXP202_VBUS_VHOLD_LOW_IRQ LITERAL1 -AXP202_VBUS_REMOVED_IRQ LITERAL1 -AXP202_VBUS_CONNECT_IRQ LITERAL1 -AXP202_VBUS_OVER_VOL_IRQ LITERAL1 -AXP202_ACIN_REMOVED_IRQ LITERAL1 -AXP202_ACIN_CONNECT_IRQ LITERAL1 -AXP202_ACIN_OVER_VOL_IRQ LITERAL1 -AXP202_BATT_LOW_TEMP_IRQ LITERAL1 -AXP202_BATT_OVER_TEMP_IRQ LITERAL1 -AXP202_CHARGING_FINISHED_IRQ LITERAL1 -AXP202_CHARGING_IRQ LITERAL1 -AXP202_BATT_EXIT_ACTIVATE_IRQ LITERAL1 -AXP202_BATT_ACTIVATE_IRQ LITERAL1 -AXP202_BATT_REMOVED_IRQ LITERAL1 -AXP202_BATT_CONNECT_IRQ LITERAL1 -AXP202_PEK_LONGPRESS_IRQ LITERAL1 -AXP202_PEL_SHORTPRESS_IRQ LITERAL1 -AXP202_LDO3_LOW_VOL_IRQ LITERAL1 -AXP202_DC3_LOW_VOL_IRQ LITERAL1 -AXP202_DC2_LOW_VOL_IRQ LITERAL1 -AXP202_CHARGE_LOW_CUR_IRQ LITERAL1 -AXP202_CHIP_TEMP_HIGH_IRQ LITERAL1 -AXP202_APS_LOW_VOL_LEVEL2_IRQ LITERAL1 -APX202_APS_LOW_VOL_LEVEL1_IRQ LITERAL1 -AXP202_VBUS_SESSION_END_IRQ LITERAL1 -AXP202_VBUS_SESSION_AB_IRQ LITERAL1 -AXP202_VBUS_INVALID_IRQ LITERAL1 -AXP202_VBUS_VAILD_IRQ LITERAL1 -AXP202_NOE_OFF_IRQ LITERAL1 -AXP202_NOE_ON_IRQ LITERAL1 - -AXP202_TEMP_MONITORING_ADC2 LITERAL1 -AXP202_GPIO1_FUNC_ADC2 LITERAL1 -AXP202_GPIO0_FUNC_ADC2 LITERAL1 - -AXP202_BATT_VOL_ADC1 LITERAL1 -AXP202_BATT_CUR_ADC1 LITERAL1 -AXP202_ACIN_VOL_ADC1 LITERAL1 -AXP202_ACIN_CUR_ADC1 LITERAL1 -AXP202_VBUS_VOL_ADC1 LITERAL1 -AXP202_VBUS_CUR_ADC1 LITERAL1 -AXP202_APS_VOL_ADC1 LITERAL1 -AXP202_TS_PIN_ADC1 LITERAL1 - -AXP202_TARGET_VOL_4_1V LITERAL1 -AXP202_TARGET_VOL_4_15V LITERAL1 -AXP202_TARGET_VOL_4_2V LITERAL1 -AXP202_TARGET_VOL_4_36V LITERAL1 -AXP202_STARTUP_TIME_128MS LITERAL1 -AXP202_STARTUP_TIME_3S LITERAL1 -AXP202_STARTUP_TIME_1S LITERAL1 -AXP202_STARTUP_TIME_2S LITERAL1 -AXP202_STARTUP_TIME LITERAL1 -AXP202_LONGPRESS_TIME LITERAL1 -AXP202_SHUTDOWN_EXCEEDS_TIME LITERAL1 -AXP202_PWROK_SIGNAL_DELAY LITERAL1 -AXP202_SHUTDOWN_TIME LITERAL1 - - -AXP202_EXTEN LITERAL1 -AXP202_DCDC3 LITERAL1 -AXP202_LDO2 LITERAL1 -AXP202_LDO4 LITERAL1 -AXP202_DCDC2 LITERAL1 -AXP202_LDO3 LITERAL1 \ No newline at end of file diff --git a/lib/AXP202X/library.properties b/lib/AXP202X/library.properties deleted file mode 100644 index 9824467d..00000000 --- a/lib/AXP202X/library.properties +++ /dev/null @@ -1,10 +0,0 @@ -name=AXP202X_Library -version=1.0.0 -author=Lewis He -maintainer=Lewis He -sentence=Arduino library for X-Power AXP202 chip -paragraph=Arduino library for X-Power AXP202 chip. Tested with ESP32 -category=Communication -url=https://github.com/lewisxhe/AXP202X_Library -architectures=* -architectures=esp32 \ No newline at end of file diff --git a/lib/AXP202X/src/axp20x.cpp b/lib/AXP202X/src/axp20x.cpp deleted file mode 100644 index 2293f2f6..00000000 --- a/lib/AXP202X/src/axp20x.cpp +++ /dev/null @@ -1,1160 +0,0 @@ -///////////////////////////////////////////////////////////////// -/* -MIT License - -Copyright (c) 2019 lewis he - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -axp20x.cpp - Arduino library for X-Power AXP202 chip. -Created by Lewis he on April 1, 2019. -github:https://github.com/lewisxhe/AXP202X_Libraries -*/ -///////////////////////////////////////////////////////////////// - -#include "axp20x.h" -#include - -const uint8_t AXP20X_Class::startupParams[] = { - 0b00000000, - 0b01000000, - 0b10000000, - 0b11000000 -}; - -const uint8_t AXP20X_Class::longPressParams[] = { - 0b00000000, - 0b00010000, - 0b00100000, - 0b00110000 -}; - -const uint8_t AXP20X_Class::shutdownParams[] = { - 0b00000000, - 0b00000001, - 0b00000010, - 0b00000011 -}; - -const uint8_t AXP20X_Class::targetVolParams[] = { - 0b00000000, - 0b00100000, - 0b01000000, - 0b01100000 -}; - - -// Power Output Control register -uint8_t AXP20X_Class::_outputReg; - -int AXP20X_Class::begin(TwoWire &port, uint8_t addr) -{ - _i2cPort = &port; //Grab which port the user wants us to use - _address = addr; - _readByte(AXP202_IC_TYPE, 1, &_chip_id); - AXP_DEBUG("chip id detect 0x%x\n", _chip_id); - if (_chip_id == AXP202_CHIP_ID || _chip_id == AXP192_CHIP_ID) { - AXP_DEBUG("Detect CHIP :%s\n", _chip_id == AXP202_CHIP_ID ? "AXP202" : "AXP192"); - _readByte(AXP202_LDO234_DC23_CTL, 1, &_outputReg); - AXP_DEBUG("OUTPUT Register 0x%x\n", _outputReg); - _init = true; - } - return _init ? AXP_PASS : AXP_FAIL; -} - -//Only axp192 chip -bool AXP20X_Class::isDCDC1Enable() -{ - if (_chip_id == AXP192_CHIP_ID) - return IS_OPEN(_outputReg, AXP192_DCDC1); - return false; -} -//Only axp192 chip -bool AXP20X_Class::isExtenEnable() -{ - if (_chip_id == AXP192_CHIP_ID) - return IS_OPEN(_outputReg, AXP192_EXTEN); - return false; -} - -bool AXP20X_Class::isLDO2Enable() -{ - //axp192 same axp202 ldo2 bit - return IS_OPEN(_outputReg, AXP202_LDO2); -} - -bool AXP20X_Class::isLDO3Enable() -{ - if (_chip_id == AXP192_CHIP_ID) - return IS_OPEN(_outputReg, AXP192_LDO3); - else if (_chip_id == AXP202_CHIP_ID) - return IS_OPEN(_outputReg, AXP202_LDO3); - return false; -} - -bool AXP20X_Class::isLDO4Enable() -{ - if (_chip_id == AXP202_CHIP_ID) - return IS_OPEN(_outputReg, AXP202_LDO4); - return false; -} - -bool AXP20X_Class::isDCDC2Enable() -{ - //axp192 same axp202 dc2 bit - return IS_OPEN(_outputReg, AXP202_DCDC2); -} - -bool AXP20X_Class::isDCDC3Enable() -{ - //axp192 same axp202 dc3 bit - return IS_OPEN(_outputReg, AXP202_DCDC3); -} - -int AXP20X_Class::setPowerOutPut(uint8_t ch, bool en) -{ - uint8_t data; - uint8_t val = 0; - if (!_init)return AXP_NOT_INIT; - - _readByte(AXP202_LDO234_DC23_CTL, 1, &data); - if (en) { - data |= (1 << ch); - } else { - data &= (~(1 << ch)); - } - - FORCED_OPEN_DCDC3(data); //! Must be forced open in T-Watch - - _writeByte(AXP202_LDO234_DC23_CTL, 1, &data); - delay(1); - _readByte(AXP202_LDO234_DC23_CTL, 1, &val); - if (data == val) { - _outputReg = val; - return AXP_PASS; - } - return AXP_FAIL; -} - -bool AXP20X_Class::isChargeing() -{ - uint8_t reg; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_MODE_CHGSTATUS, 1, ®); - return IS_OPEN(reg, 6); -} - -bool AXP20X_Class::isBatteryConnect() -{ - uint8_t reg; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_MODE_CHGSTATUS, 1, ®); - return IS_OPEN(reg, 5); -} - -float AXP20X_Class::getAcinVoltage() -{ - if (!_init)return AXP_NOT_INIT; - return _getRegistResult(AXP202_ACIN_VOL_H8, AXP202_ACIN_VOL_L4) * AXP202_ACIN_VOLTAGE_STEP; -} - -float AXP20X_Class::getAcinCurrent() -{ - if (!_init)return AXP_NOT_INIT; - float rslt; - uint8_t hv, lv; - return _getRegistResult(AXP202_ACIN_CUR_H8, AXP202_ACIN_CUR_L4) * AXP202_ACIN_CUR_STEP; -} - -float AXP20X_Class::getVbusVoltage() -{ - if (!_init)return AXP_NOT_INIT; - return _getRegistResult(AXP202_VBUS_VOL_H8, AXP202_VBUS_VOL_L4) * AXP202_VBUS_VOLTAGE_STEP; -} - -float AXP20X_Class::getVbusCurrent() -{ - if (!_init)return AXP_NOT_INIT; - return _getRegistResult(AXP202_VBUS_CUR_H8, AXP202_VBUS_CUR_L4) * AXP202_VBUS_CUR_STEP; -} - -float AXP20X_Class::getTemp() -{ - if (!_init)return AXP_NOT_INIT; - uint8_t hv, lv; - _readByte(AXP202_INTERNAL_TEMP_H8, 1, &hv); - _readByte(AXP202_INTERNAL_TEMP_L4, 1, &lv); - float rslt = hv << 8 | (lv & 0xF); - return rslt / 1000; -} - -float AXP20X_Class::getTSTemp() -{ - if (!_init)return AXP_NOT_INIT; - return _getRegistResult(AXP202_TS_IN_H8, AXP202_TS_IN_L4) * AXP202_TS_PIN_OUT_STEP; -} - -float AXP20X_Class::getGPIO0Voltage() -{ - if (!_init)return AXP_NOT_INIT; - return _getRegistResult(AXP202_GPIO0_VOL_ADC_H8, AXP202_GPIO0_VOL_ADC_L4) * AXP202_GPIO0_STEP; -} - -float AXP20X_Class::getGPIO1Voltage() -{ - if (!_init)return AXP_NOT_INIT; - return _getRegistResult(AXP202_GPIO1_VOL_ADC_H8, AXP202_GPIO1_VOL_ADC_L4) * AXP202_GPIO1_STEP; -} - -/* -Note: the battery power formula: -Pbat =2* register value * Voltage LSB * Current LSB / 1000. -(Voltage LSB is 1.1mV; Current LSB is 0.5mA, and unit of calculation result is mW.) -*/ -float AXP20X_Class::getBattInpower() -{ - float rslt; - uint8_t hv, mv, lv; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_BAT_POWERH8, 1, &hv); - _readByte(AXP202_BAT_POWERM8, 1, &mv); - _readByte(AXP202_BAT_POWERL8, 1, &lv); - rslt = (hv << 16) | (mv << 8) | lv; - rslt = 2 * rslt * 1.1 * 0.5 / 1000; - return rslt; -} - -float AXP20X_Class::getBattVoltage() -{ - if (!_init)return AXP_NOT_INIT; - return _getRegistResult(AXP202_BAT_AVERVOL_H8, AXP202_BAT_AVERVOL_L4) * AXP202_BATT_VOLTAGE_STEP; -} - -float AXP20X_Class::getBattChargeCurrent() -{ - if (!_init)return AXP_NOT_INIT; - switch (_chip_id) { - case AXP202_CHIP_ID: - return _getRegistResult(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L4) * AXP202_BATT_CHARGE_CUR_STEP; - case AXP192_CHIP_ID: - return _getRegistH8L5(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L4) * AXP202_BATT_CHARGE_CUR_STEP; - default: - break; - } -} - -float AXP20X_Class::getBattDischargeCurrent() -{ - float rslt; - uint8_t hv, lv; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_BAT_AVERDISCHGCUR_H8, 1, &hv); - _readByte(AXP202_BAT_AVERDISCHGCUR_L5, 1, &lv); - rslt = (hv << 5) | (lv & 0x1F); - return rslt * AXP202_BATT_DISCHARGE_CUR_STEP; -} - -float AXP20X_Class::getSysIPSOUTVoltage() -{ - float rslt; - uint8_t hv, lv; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_APS_AVERVOL_H8, 1, &hv); - _readByte(AXP202_APS_AVERVOL_L4, 1, &lv); - rslt = (hv << 4) | (lv & 0xF); - return rslt; -} - -/* -Coulomb calculation formula: -C= 65536 * current LSB *(charge coulomb counter value - discharge coulomb counter value) / -3600 / ADC sample rate. Refer to REG84H setting for ADC sample rate;the current LSB is -0.5mA;unit of the calculation result is mAh. ) -*/ -uint32_t AXP20X_Class::getBattChargeCoulomb() -{ - uint8_t buffer[4]; - if (!_init)return AXP_NOT_INIT; - _readByte(0xB1, 4, buffer); - return buffer[0] << 24 + buffer[1] << 16 + buffer[2] << 8 + buffer[3]; -} - -uint32_t AXP20X_Class::getBattDischargeCoulomb() -{ - uint8_t buffer[4]; - if (!_init)return AXP_NOT_INIT; - _readByte(0xB4, 4, buffer); - return buffer[0] << 24 + buffer[1] << 16 + buffer[2] << 8 + buffer[3]; -} - -float AXP20X_Class::getCoulombData() -{ - if (!_init)return AXP_NOT_INIT; - uint32_t charge = getBattChargeCoulomb(); - uint32_t discharge = getBattDischargeCoulomb(); - uint8_t rate = getAdcSamplingRate(); - float result = 65536.0 * 0.5 * (charge - discharge) / 3600.0 / rate; - return result; -} - -uint8_t AXP20X_Class::getAdcSamplingRate() -{ - //axp192 same axp202 aregister address 0x84 - if (!_init)return AXP_NOT_INIT; - uint8_t val; - _readByte(AXP202_ADC_SPEED, 1, &val); - return 25 * (int)pow(2, (val & 0xC0) >> 6); -} - -int AXP20X_Class::setAdcSamplingRate(axp_adc_sampling_rate_t rate) -{ - //axp192 same axp202 aregister address 0x84 - if (!_init)return AXP_NOT_INIT; - if (rate > AXP_ADC_SAMPLING_RATE_200HZ) return AXP_FAIL; - uint8_t val; - _readByte(AXP202_ADC_SPEED, 1, &val); - uint8_t rw = rate; - val &= 0x3F; - val |= (rw << 6); - _writeByte(AXP202_ADC_SPEED, 1, &val); - return AXP_PASS; -} - - -int AXP20X_Class::adc1Enable(uint16_t params, bool en) -{ - if (!_init)return AXP_NOT_INIT; - uint8_t val; - _readByte(AXP202_ADC_EN1, 1, &val); - if (en) - val |= params; - else - val &= ~(params); - _writeByte(AXP202_ADC_EN1, 1, &val); - - _readByte(AXP202_ADC_EN1, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::adc2Enable(uint16_t params, bool en) -{ - if (!_init)return AXP_NOT_INIT; - uint8_t val; - _readByte(AXP202_ADC_EN2, 1, &val); - if (en) - val |= params; - else - val &= ~(params); - _writeByte(AXP202_ADC_EN2, 1, &val); - return AXP_PASS; -} - - - -int AXP20X_Class::enableIRQ(uint32_t params, bool en) -{ - if (!_init)return AXP_NOT_INIT; - uint8_t val, val1; - if (params & 0xFF) { - val1 = params & 0xFF; - _readByte(AXP202_INTEN1, 1, &val); - if (en) - val |= val1; - else - val &= ~(val1); - AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN1, val); - _writeByte(AXP202_INTEN1, 1, &val); - } - if (params & 0xFF00) { - val1 = params >> 8; - _readByte(AXP202_INTEN2, 1, &val); - if (en) - val |= val1; - else - val &= ~(val1); - AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN2, val); - _writeByte(AXP202_INTEN2, 1, &val); - } - - if (params & 0xFF0000) { - val1 = params >> 16; - _readByte(AXP202_INTEN3, 1, &val); - if (en) - val |= val1; - else - val &= ~(val1); - AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN3, val); - _writeByte(AXP202_INTEN3, 1, &val); - } - - if (params & 0xFF000000) { - val1 = params >> 24; - _readByte(AXP202_INTEN4, 1, &val); - if (en) - val |= val1; - else - val &= ~(val1); - AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN4, val); - _writeByte(AXP202_INTEN4, 1, &val); - } - return AXP_PASS; -} - -int AXP20X_Class::readIRQ() -{ - if (!_init)return AXP_NOT_INIT; - switch (_chip_id) { - case AXP192_CHIP_ID: - for (int i = 0; i < 4; ++i) { - _readByte(AXP192_INTSTS1 + i, 1, &_irq[i]); - } - _readByte(AXP192_INTSTS5, 1, &_irq[4]); - return AXP_PASS; - - case AXP202_CHIP_ID: - for (int i = 0; i < 5; ++i) { - _readByte(AXP202_INTSTS1 + i, 1, &_irq[i]); - } - return AXP_PASS; - default: - return AXP_FAIL; - } -} - -void AXP20X_Class::clearIRQ() -{ - uint8_t val = 0xFF; - switch (_chip_id) { - case AXP192_CHIP_ID: - for (int i = 0; i < 3; i++) { - _writeByte(AXP192_INTSTS1 + i, 1, &val); - } - _writeByte(AXP192_INTSTS5, 1, &val); - break; - case AXP202_CHIP_ID: - for (int i = 0; i < 5; i++) { - _writeByte(AXP202_INTSTS1 + i, 1, &val); - } - break; - default: - break; - } - memset(_irq, 0, sizeof(_irq)); -} - - -bool AXP20X_Class::isAcinOverVoltageIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(7)); -} - -bool AXP20X_Class::isAcinPlugInIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(6)); -} - -bool AXP20X_Class::isAcinRemoveIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(5)); -} - -bool AXP20X_Class::isVbusOverVoltageIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(4)); -} - -bool AXP20X_Class::isVbusPlugInIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(3)); -} - -bool AXP20X_Class::isVbusRemoveIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(2)); -} - -bool AXP20X_Class::isVbusLowVHOLDIRQ() -{ - return (bool)(_irq[0] & BIT_MASK(1)); -} - -bool AXP20X_Class::isBattPlugInIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(7)); -} -bool AXP20X_Class::isBattRemoveIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(6)); -} -bool AXP20X_Class::isBattEnterActivateIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(5)); -} -bool AXP20X_Class::isBattExitActivateIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(4)); -} -bool AXP20X_Class::isChargingIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(3)); -} -bool AXP20X_Class::isChargingDoneIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(2)); -} -bool AXP20X_Class::isBattTempLowIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(1)); -} -bool AXP20X_Class::isBattTempHighIRQ() -{ - return (bool)(_irq[1] & BIT_MASK(0)); -} - -bool AXP20X_Class::isPEKShortPressIRQ() -{ - return (bool)(_irq[2] & BIT_MASK(1)); -} - -bool AXP20X_Class::isPEKLongtPressIRQ() -{ - return (bool)(_irq[2] & BIT_MASK(0)); -} - -bool AXP20X_Class::isVBUSPlug() -{ - if (!_init)return AXP_NOT_INIT; - uint8_t val; - _readByte(AXP202_STATUS, 1, &val); - return (bool)(_irq[2] & BIT_MASK(5)); -} - -int AXP20X_Class::setDCDC2Voltage(uint16_t mv) -{ - if (!_init)return AXP_NOT_INIT; - if (mv < 700) { - AXP_DEBUG("DCDC2:Below settable voltage:700mV~2275mV"); - mv = 700; - } - if (mv > 2275) { - AXP_DEBUG("DCDC2:Above settable voltage:700mV~2275mV"); - mv = 2275; - } - uint8_t val = (mv - 700) / 25; - _writeByte(AXP202_DC2OUT_VOL, 1, &val); - return AXP_PASS; -} - - - -uint16_t AXP20X_Class::getDCDC2Voltage() -{ - uint8_t val = 0; - _readByte(AXP202_DC2OUT_VOL, 1, &val); - return val * 25 + 700; -} - -uint16_t AXP20X_Class::getDCDC3Voltage() -{ - uint8_t val = 0; - _readByte(AXP202_DC3OUT_VOL, 1, &val); - return val * 25 + 700; -} - - -int AXP20X_Class::setDCDC3Voltage(uint16_t mv) -{ - if (!_init)return AXP_NOT_INIT; - if (mv < 700) { - AXP_DEBUG("DCDC3:Below settable voltage:700mV~3500mV"); - mv = 700; - } - if (mv > 3500) { - AXP_DEBUG("DCDC3:Above settable voltage:700mV~3500mV"); - mv = 3500; - } - uint8_t val = (mv - 700) / 25; - _writeByte(AXP202_DC3OUT_VOL, 1, &val); - return AXP_PASS; -} - - -int AXP20X_Class::setLDO2Voltage(uint16_t mv) -{ - uint8_t rVal, wVal; - if (!_init)return AXP_NOT_INIT; - if (mv < 1800) { - AXP_DEBUG("LDO2:Below settable voltage:1800mV~3300mV"); - mv = 1800; - } - if (mv > 3300) { - AXP_DEBUG("LDO2:Above settable voltage:1800mV~3300mV"); - mv = 3300; - } - wVal = (mv - 1800) / 100; - if (_chip_id == AXP202_CHIP_ID ) { - _readByte(AXP202_LDO24OUT_VOL, 1, &rVal); - rVal &= 0x0F; - rVal |= (wVal << 4); - _writeByte(AXP202_LDO24OUT_VOL, 1, &rVal); - return AXP_PASS; - } else if (_chip_id == AXP192_CHIP_ID) { - _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); - rVal &= 0x0F; - rVal |= (wVal << 4); - _writeByte(AXP192_LDO23OUT_VOL, 1, &rVal); - return AXP_PASS; - } - return AXP_FAIL; -} - - -uint16_t AXP20X_Class::getLDO2Voltage() -{ - uint8_t rVal; - if (_chip_id == AXP202_CHIP_ID ) { - _readByte(AXP202_LDO24OUT_VOL, 1, &rVal); - rVal &= 0xF0; - rVal >>= 4; - return rVal * 100 + 1800; - } else if (_chip_id == AXP192_CHIP_ID) { - _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); - AXP_DEBUG("get result:%x\n", rVal); - rVal &= 0xF0; - rVal >>= 4; - return rVal * 100 + 1800; - } - return 0; -} - -int AXP20X_Class::setLDO3Voltage(uint16_t mv) -{ - uint8_t rVal; - if (!_init)return AXP_NOT_INIT; - if (_chip_id == AXP202_CHIP_ID && mv < 700) { - AXP_DEBUG("LDO3:Below settable voltage:700mV~2275mV"); - mv = 700; - } else if (_chip_id == AXP192_CHIP_ID && mv < 1800) { - AXP_DEBUG("LDO3:Below settable voltage:1800mV~3300mV"); - mv = 1800; - } - - if (_chip_id == AXP202_CHIP_ID && mv > 2275) { - AXP_DEBUG("LDO3:Above settable voltage:700mV~2275mV"); - mv = 2275; - } else if (_chip_id == AXP192_CHIP_ID && mv > 3300) { - AXP_DEBUG("LDO3:Above settable voltage:1800mV~3300mV"); - mv = 3300; - } - - if (_chip_id == AXP202_CHIP_ID ) { - - _readByte(AXP202_LDO3OUT_VOL, 1, &rVal); - rVal &= 0x80; - rVal |= ((mv - 700) / 25); - _writeByte(AXP202_LDO3OUT_VOL, 1, &rVal); - return AXP_PASS; - - } else if (_chip_id == AXP192_CHIP_ID) { - - _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); - rVal &= 0xF0; - rVal |= ((mv - 1800) / 100); - _writeByte(AXP192_LDO23OUT_VOL, 1, &rVal); - return AXP_PASS; - } - return AXP_FAIL; -} - - -uint16_t AXP20X_Class::getLDO3Voltage() -{ - uint8_t rVal; - if (!_init)return AXP_NOT_INIT; - - if (_chip_id == AXP202_CHIP_ID ) { - - _readByte(AXP202_LDO3OUT_VOL, 1, &rVal); - if (rVal & 0x80) { - //! According to the hardware N_VBUSEN Pin selection - return getVbusVoltage() * 1000; - } else { - return (rVal & 0x7F) * 25 + 700; - } - } else if (_chip_id == AXP192_CHIP_ID) { - _readByte(AXP192_LDO23OUT_VOL, 1, &rVal); - rVal &= 0x0F; - return rVal * 100 + 1800; - } - return 0; -} - -//! Only axp202 support -int AXP20X_Class::setLDO4Voltage(axp_ldo4_table_t param) -{ - if (!_init)return AXP_NOT_INIT; - if (_chip_id != AXP202_CHIP_ID ) return AXP_FAIL; - if (param >= AXP202_LDO4_MAX)return AXP_INVALID; - uint8_t val; - _readByte(AXP202_LDO24OUT_VOL, 1, &val); - val &= 0xF0; - val |= param; - _writeByte(AXP202_LDO24OUT_VOL, 1, &val); - return AXP_PASS; -} - -//! Only AXP202 support -// 0 : LDO 1 : DCIN -int AXP20X_Class::setLDO3Mode(uint8_t mode) -{ - uint8_t val; - if (_chip_id != AXP202_CHIP_ID ) return AXP_FAIL; - _readByte(AXP202_LDO3OUT_VOL, 1, &val); - if (mode) { - val |= BIT_MASK(7); - } else { - val &= (~BIT_MASK(7)); - } - _writeByte(AXP202_LDO3OUT_VOL, 1, &val); - return AXP_PASS; - -} - -int AXP20X_Class::setStartupTime(uint8_t param) -{ - uint8_t val; - if (!_init)return AXP_NOT_INIT; - if (param > sizeof(startupParams) / sizeof(startupParams[0]))return AXP_INVALID; - _readByte(AXP202_POK_SET, 1, &val); - val &= (~0b11000000); - val |= startupParams[param]; - _writeByte(AXP202_POK_SET, 1, &val); -} - -int AXP20X_Class::setlongPressTime(uint8_t param) -{ - uint8_t val; - if (!_init)return AXP_NOT_INIT; - if (param > sizeof(longPressParams) / sizeof(longPressParams[0]))return AXP_INVALID; - _readByte(AXP202_POK_SET, 1, &val); - val &= (~0b00110000); - val |= longPressParams[param]; - _writeByte(AXP202_POK_SET, 1, &val); -} - -int AXP20X_Class::setShutdownTime(uint8_t param) -{ - uint8_t val; - if (!_init)return AXP_NOT_INIT; - if (param > sizeof(shutdownParams) / sizeof(shutdownParams[0]))return AXP_INVALID; - _readByte(AXP202_POK_SET, 1, &val); - val &= (~0b00000011); - val |= shutdownParams[param]; - _writeByte(AXP202_POK_SET, 1, &val); -} - -int AXP20X_Class::setTimeOutShutdown(bool en) -{ - uint8_t val; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_POK_SET, 1, &val); - if (en) - val |= (1 << 3); - else - val &= (~(1 << 3)); - _writeByte(AXP202_POK_SET, 1, &val); -} - - -int AXP20X_Class::shutdown() -{ - uint8_t val; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_OFF_CTL, 1, &val); - val |= (1 << 7); - _writeByte(AXP202_OFF_CTL, 1, &val); -} - - -float AXP20X_Class::getSettingChargeCurrent() -{ - uint8_t val; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_CHARGE1, 1, &val); - val &= 0b00000111; - float cur = 300.0 + val * 100.0; - AXP_DEBUG("Setting Charge current : %.2f mA\n", cur); - return cur; -} - -bool AXP20X_Class::isChargeingEnable() -{ - uint8_t val; - if (!_init)return false; - _readByte(AXP202_CHARGE1, 1, &val); - if (val & (1 << 7)) { - AXP_DEBUG("Charging enable is enable\n"); - val = true; - } else { - AXP_DEBUG("Charging enable is disable\n"); - val = false; - } - return val; -} - -int AXP20X_Class::enableChargeing(bool en) -{ - uint8_t val; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_CHARGE1, 1, &val); - val |= (1 << 7); - _writeByte(AXP202_CHARGE1, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setChargingTargetVoltage(axp_chargeing_vol_t param) -{ - uint8_t val; - if (!_init)return AXP_NOT_INIT; - if (param > sizeof(targetVolParams) / sizeof(targetVolParams[0]))return AXP_INVALID; - _readByte(AXP202_CHARGE1, 1, &val); - val &= ~(0b01100000); - val |= targetVolParams[param]; - _writeByte(AXP202_CHARGE1, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::getBattPercentage() -{ - if (!_init)return AXP_NOT_INIT; - uint8_t val; - _readByte(AXP202_BATT_PERCENTAGE, 1, &val); - if (!(val & BIT_MASK(7))) { - return val & (~BIT_MASK(7)); - } - return 0; -} - - - -int AXP20X_Class::setChgLEDMode(uint8_t mode) -{ - uint8_t val; - _readByte(AXP202_OFF_CTL, 1, &val); - val |= BIT_MASK(3); - switch (mode) { - case AXP20X_LED_OFF: - val &= 0b11001111; - _writeByte(AXP202_OFF_CTL, 1, &val); - break; - case AXP20X_LED_BLINK_1HZ: - val &= 0b11001111; - val |= 0b00010000; - _writeByte(AXP202_OFF_CTL, 1, &val); - break; - case AXP20X_LED_BLINK_4HZ: - val &= 0b11001111; - val |= 0b00100000; - _writeByte(AXP202_OFF_CTL, 1, &val); - break; - case AXP20X_LED_LOW_LEVEL: - val &= 0b11001111; - val |= 0b00110000; - _writeByte(AXP202_OFF_CTL, 1, &val); - break; - default: - break; - } - return AXP_PASS; -} - -int AXP20X_Class::debugCharging() -{ - uint8_t val; - _readByte(AXP202_CHARGE1, 1, &val); - AXP_DEBUG("SRC REG:0x%x\n", val); - if (val & (1 << 7)) { - AXP_DEBUG("Charging enable is enable\n"); - } else { - AXP_DEBUG("Charging enable is disable\n"); - } - AXP_DEBUG("Charging target-voltage : 0x%x\n", ((val & 0b01100000) >> 5 ) & 0b11); - if (val & (1 << 4)) { - AXP_DEBUG("end when the charge current is lower than 15%% of the set value\n"); - } else { - AXP_DEBUG(" end when the charge current is lower than 10%% of the set value\n"); - } - val &= 0b00000111; - float cur = 300.0 + val * 100.0; - AXP_DEBUG("Charge current : %.2f mA\n", cur); -} - - -int AXP20X_Class::debugStatus() -{ - if (!_init)return AXP_NOT_INIT; - uint8_t val, val1, val2; - _readByte(AXP202_STATUS, 1, &val); - _readByte(AXP202_MODE_CHGSTATUS, 1, &val1); - _readByte(AXP202_IPS_SET, 1, &val2); - AXP_DEBUG("AXP202_STATUS: AXP202_MODE_CHGSTATUS AXP202_IPS_SET\n"); - AXP_DEBUG("0x%x\t\t\t 0x%x\t\t\t 0x%x\n", val, val1, val2); -} - - -int AXP20X_Class::limitingOff() -{ - if (!_init)return AXP_NOT_INIT; - uint8_t val; - _readByte(AXP202_IPS_SET, 1, &val); - if (_chip_id == AXP202_CHIP_ID) { - val |= 0x03; - } else { - val &= ~(1 << 1); - } - _writeByte(AXP202_IPS_SET, 1, &val); - return AXP_PASS; -} - -// Only AXP129 chip -int AXP20X_Class::setDCDC1Voltage(uint16_t mv) -{ - if (!_init)return AXP_NOT_INIT; - if (_chip_id != AXP192_CHIP_ID) return AXP_FAIL; - if (mv < 700) { - AXP_DEBUG("DCDC1:Below settable voltage:700mV~3500mV"); - mv = 700; - } - if (mv > 3500) { - AXP_DEBUG("DCDC1:Above settable voltage:700mV~3500mV"); - mv = 3500; - } - uint8_t val = (mv - 700) / 25; - _writeByte(AXP192_DC1_VLOTAGE, 1, &val); - return AXP_PASS; -} - -// Only AXP129 chip -uint16_t AXP20X_Class::getDCDC1Voltage() -{ - if (_chip_id != AXP192_CHIP_ID) return AXP_FAIL; - uint8_t val = 0; - _readByte(AXP192_DC1_VLOTAGE, 1, &val); - return val * 25 + 700; -} - - -int AXP20X_Class::setGPIO0Voltage(uint8_t param) -{ - uint8_t params[] = { - 0b11111000, - 0b11111001, - 0b11111010, - 0b11111011, - 0b11111100, - 0b11111101, - 0b11111110, - 0b11111111, - }; - if (!_init)return AXP_NOT_INIT; - if (param > sizeof(params) / sizeof(params[0]))return AXP_INVALID; - uint8_t val = 0; - _readByte(AXP202_GPIO0_VOL, 1, &val); - val &= 0b11111000; - val |= params[param]; - _writeByte(AXP202_GPIO0_VOL, 1, &val); - return AXP_PASS; -} - -int AXP20X_Class::setGPIO0Level(uint8_t level) -{ - uint8_t val = 0; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_GPIO0_CTL, 1, &val); - val = level ? val & 0b11111000 : (val & 0b11111000) | 0b00000001; - _writeByte(AXP202_GPIO0_CTL, 1, &val); - return AXP_PASS; -} -int AXP20X_Class::setGPIO1Level(uint8_t level) -{ - uint8_t val = 0; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_GPIO1_CTL, 1, &val); - val = level ? val & 0b11111000 : (val & 0b11111000) | 0b00000001; - _writeByte(AXP202_GPIO1_CTL, 1, &val); - return AXP_PASS; -} - - - -int AXP20X_Class::readGpioStatus() -{ - uint8_t val = 0; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_GPIO012_SIGNAL, 1, &val); - _gpio[0] = val & BIT_MASK(4); - _gpio[1] = val & BIT_MASK(5); - _gpio[2] = val & BIT_MASK(6); - _readByte(AXP202_GPIO3_CTL, 1, &val); - _gpio[3] = val & 1; - return AXP_PASS; -} - -int AXP20X_Class::readGpio0Level() -{ - return _gpio[0]; -} - -int AXP20X_Class::readGpio1Level() -{ - return _gpio[1]; -} - -int AXP20X_Class::readGpio2Level() -{ - return _gpio[2]; -} - - -int AXP20X_Class::setGpio2Mode(uint8_t mode) -{ - uint8_t params[] = { - 0b11111000, - 0b11111001, - 0b11111010, - }; - if (!_init)return AXP_NOT_INIT; - if (mode > sizeof(params) / sizeof(params[0]))return AXP_INVALID; - uint8_t val = 0; - _readByte(AXP202_GPIO2_CTL, 1, &val); - val &= params[0]; - val |= params[mode]; - _writeByte(AXP202_GPIO2_CTL, 1, &val); - return AXP_PASS; -} - - - -int AXP20X_Class::setGpio3Mode(uint8_t mode) -{ - uint8_t val = 0; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_GPIO3_CTL, 1, &val); - if (mode == AXP202_GPIO3_DIGITAL_INPUT) { - val |= BIT_MASK(2); - } else if (mode == AXP202_GPIO3_OPEN_DRAIN_OUTPUT) { - val &= ~BIT_MASK(2); - } else { - return AXP_INVALID; - } - return AXP_PASS; -} - -int AXP20X_Class::setGpio3Level(uint8_t level) -{ - uint8_t val = 0; - if (!_init)return AXP_NOT_INIT; - _readByte(AXP202_GPIO3_CTL, 1, &val); - if (!(val & BIT_MASK(2))) { - return AXP_FAIL; - } - val = level ? val & (~BIT_MASK(1)) : val | BIT_MASK(1); - _writeByte(AXP202_GPIO3_CTL, 1, &val); -} - -int AXP20X_Class::_setGpioInterrupt(uint8_t *val, int mode, bool en) -{ - switch (mode) { - case RISING: - *val = en ? *val | BIT_MASK(7) : *val & (~BIT_MASK(7)); - break; - case FALLING: - *val = en ? *val | BIT_MASK(6) : *val & (~BIT_MASK(6)); - break; - default: - break; - } -} - -int AXP20X_Class::setGpioInterruptMode(uint8_t gpio, int mode, bool en) -{ - uint8_t val = 0; - if (!_init)return AXP_NOT_INIT; - switch (gpio) { - case AXP202_GPIO0: - _readByte(AXP202_GPIO0_CTL, 1, &val); - _setGpioInterrupt(&val, mode, en); - break; - case AXP202_GPIO1: - _readByte(AXP202_GPIO1_CTL, 1, &val); - _setGpioInterrupt(&val, mode, en); - break; - case AXP202_GPIO2: - _readByte(AXP202_GPIO2_CTL, 1, &val); - _setGpioInterrupt(&val, mode, en); - break; - case AXP202_GPIO3: - _readByte(AXP202_GPIO3_CTL, 1, &val); - _setGpioInterrupt(&val, mode, en); - break; - } -} - - -int AXP20X_Class::gpio0Setting(axp192_gpio0_mode_t mode) -{ - uint8_t rVal; - if (!_init)return AXP_NOT_INIT; - if (_chip_id == AXP192_CHIP_ID ) { - _readByte(AXP192_GPIO0_CTL, 1, &rVal); - rVal &= 0xF8; - rVal |= mode; - _writeByte(AXP192_GPIO0_CTL, 1, &rVal); - return AXP_PASS; - } - return AXP_FAIL; -} - - -int AXP20X_Class::gpio0SetVoltage(axp192_gpio_voltage_t vol) -{ - uint8_t rVal; - if (!_init)return AXP_NOT_INIT; - if (_chip_id == AXP192_CHIP_ID) { - _readByte(AXP192_GPIO0_VOL, 1, &rVal); - rVal &= 0x0F; - rVal |= (vol << 4); - _writeByte(AXP192_GPIO0_VOL, 1, &rVal); - return AXP_PASS; - } - return AXP_FAIL; -} - -uint16_t AXP20X_Class::gpio0GetVoltage() -{ - uint8_t rVal; - if (!_init)return AXP_NOT_INIT; - if (_chip_id == AXP192_CHIP_ID) { - _readByte(AXP192_GPIO0_VOL, 1, &rVal); - rVal &= 0xF0; - rVal >>= 4; - return rVal; - } - return 0; -} \ No newline at end of file diff --git a/lib/AXP202X/src/axp20x.h b/lib/AXP202X/src/axp20x.h deleted file mode 100644 index e86a4714..00000000 --- a/lib/AXP202X/src/axp20x.h +++ /dev/null @@ -1,766 +0,0 @@ -///////////////////////////////////////////////////////////////// -/* -MIT License - -Copyright (c) 2019 lewis he - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -axp20x.h - Arduino library for X-Power AXP202 chip. -Created by Lewis he on April 1, 2019. -github:https://github.com/lewisxhe/AXP202X_Libraries -*/ -///////////////////////////////////////////////////////////////// -#pragma once - -#include -#include - -// #define AXP_DEBUG_PORT Serial -#ifdef AXP_DEBUG_PORT -#define AXP_DEBUG(fmt, ...) AXP_DEBUG_PORT.printf_P( (PGM_P)PSTR(fmt), ## __VA_ARGS__ ) -#else -#define AXP_DEBUG(...) -#endif - -#ifndef RISING -#define RISING 0x01 -#endif - -#ifndef FALLING -#define FALLING 0x02 -#endif - -//! Error Code -#define AXP_PASS 0 -#define AXP_FAIL -1 -#define AXP_INVALID -2 -#define AXP_NOT_INIT -3 - -//! Chip Address -#define AXP202_SLAVE_ADDRESS (0x35) -#define AXP192_SLAVE_ADDRESS (0x34) - -//! Chip ID -#define AXP202_CHIP_ID 0x41 -#define AXP192_CHIP_ID 0x03 - -//! REG MAP -#define AXP202_STATUS (0x00) -#define AXP202_MODE_CHGSTATUS (0x01) -#define AXP202_OTG_STATUS (0x02) -#define AXP202_IC_TYPE (0x03) -#define AXP202_DATA_BUFFER1 (0x04) -#define AXP202_DATA_BUFFER2 (0x05) -#define AXP202_DATA_BUFFER3 (0x06) -#define AXP202_DATA_BUFFER4 (0x07) -#define AXP202_DATA_BUFFER5 (0x08) -#define AXP202_DATA_BUFFER6 (0x09) -#define AXP202_DATA_BUFFER7 (0x0A) -#define AXP202_DATA_BUFFER8 (0x0B) -#define AXP202_DATA_BUFFER9 (0x0C) -#define AXP202_DATA_BUFFERA (0x0D) -#define AXP202_DATA_BUFFERB (0x0E) -#define AXP202_DATA_BUFFERC (0x0F) -#define AXP202_LDO234_DC23_CTL (0x12) -#define AXP202_DC2OUT_VOL (0x23) -#define AXP202_LDO3_DC2_DVM (0x25) -#define AXP202_DC3OUT_VOL (0x27) -#define AXP202_LDO24OUT_VOL (0x28) -#define AXP202_LDO3OUT_VOL (0x29) -#define AXP202_IPS_SET (0x30) -#define AXP202_VOFF_SET (0x31) -#define AXP202_OFF_CTL (0x32) -#define AXP202_CHARGE1 (0x33) -#define AXP202_CHARGE2 (0x34) -#define AXP202_BACKUP_CHG (0x35) -#define AXP202_POK_SET (0x36) -#define AXP202_DCDC_FREQSET (0x37) -#define AXP202_VLTF_CHGSET (0x38) -#define AXP202_VHTF_CHGSET (0x39) -#define AXP202_APS_WARNING1 (0x3A) -#define AXP202_APS_WARNING2 (0x3B) -#define AXP202_TLTF_DISCHGSET (0x3C) -#define AXP202_THTF_DISCHGSET (0x3D) -#define AXP202_DCDC_MODESET (0x80) -#define AXP202_ADC_EN1 (0x82) -#define AXP202_ADC_EN2 (0x83) -#define AXP202_ADC_SPEED (0x84) -#define AXP202_ADC_INPUTRANGE (0x85) -#define AXP202_ADC_IRQ_RETFSET (0x86) -#define AXP202_ADC_IRQ_FETFSET (0x87) -#define AXP202_TIMER_CTL (0x8A) -#define AXP202_VBUS_DET_SRP (0x8B) -#define AXP202_HOTOVER_CTL (0x8F) -#define AXP202_GPIO0_CTL (0x90) -#define AXP202_GPIO0_VOL (0x91) -#define AXP202_GPIO1_CTL (0x92) -#define AXP202_GPIO2_CTL (0x93) -#define AXP202_GPIO012_SIGNAL (0x94) -#define AXP202_GPIO3_CTL (0x95) -#define AXP202_INTEN1 (0x40) -#define AXP202_INTEN2 (0x41) -#define AXP202_INTEN3 (0x42) -#define AXP202_INTEN4 (0x43) -#define AXP202_INTEN5 (0x44) -#define AXP202_INTSTS1 (0x48) -#define AXP202_INTSTS2 (0x49) -#define AXP202_INTSTS3 (0x4A) -#define AXP202_INTSTS4 (0x4B) -#define AXP202_INTSTS5 (0x4C) - -//Irq control register -#define AXP192_INTEN1 (0x40) -#define AXP192_INTEN2 (0x41) -#define AXP192_INTEN3 (0x42) -#define AXP192_INTEN4 (0x43) -#define AXP192_INTEN5 (0x4A) -//Irq status register -#define AXP192_INTSTS1 (0x44) -#define AXP192_INTSTS2 (0x45) -#define AXP192_INTSTS3 (0x46) -#define AXP192_INTSTS4 (0x47) -#define AXP192_INTSTS5 (0x4D) - - -#define AXP192_DC1_VLOTAGE (0x26) -#define AXP192_LDO23OUT_VOL (0x28) -#define AXP192_GPIO0_CTL (0x90) -#define AXP192_GPIO0_VOL (0x91) - - -/* axp 20 adc data register */ -#define AXP202_BAT_AVERVOL_H8 (0x78) -#define AXP202_BAT_AVERVOL_L4 (0x79) -#define AXP202_BAT_AVERCHGCUR_H8 (0x7A) -#define AXP202_BAT_AVERCHGCUR_L4 (0x7B) -#define AXP202_BAT_VOL_H8 (0x50) -#define AXP202_BAT_VOL_L4 (0x51) -#define AXP202_ACIN_VOL_H8 (0x56) -#define AXP202_ACIN_VOL_L4 (0x57) -#define AXP202_ACIN_CUR_H8 (0x58) -#define AXP202_ACIN_CUR_L4 (0x59) -#define AXP202_VBUS_VOL_H8 (0x5A) -#define AXP202_VBUS_VOL_L4 (0x5B) -#define AXP202_VBUS_CUR_H8 (0x5C) -#define AXP202_VBUS_CUR_L4 (0x5D) -#define AXP202_INTERNAL_TEMP_H8 (0x5E) -#define AXP202_INTERNAL_TEMP_L4 (0x5F) -#define AXP202_TS_IN_H8 (0x62) -#define AXP202_TS_IN_L4 (0x63) -#define AXP202_GPIO0_VOL_ADC_H8 (0x64) -#define AXP202_GPIO0_VOL_ADC_L4 (0x65) -#define AXP202_GPIO1_VOL_ADC_H8 (0x66) -#define AXP202_GPIO1_VOL_ADC_L4 (0x67) - -#define AXP202_BAT_AVERDISCHGCUR_H8 (0x7C) -#define AXP202_BAT_AVERDISCHGCUR_L5 (0x7D) -#define AXP202_APS_AVERVOL_H8 (0x7E) -#define AXP202_APS_AVERVOL_L4 (0x7F) -#define AXP202_INT_BAT_CHGCUR_H8 (0xA0) -#define AXP202_INT_BAT_CHGCUR_L4 (0xA1) -#define AXP202_EXT_BAT_CHGCUR_H8 (0xA2) -#define AXP202_EXT_BAT_CHGCUR_L4 (0xA3) -#define AXP202_INT_BAT_DISCHGCUR_H8 (0xA4) -#define AXP202_INT_BAT_DISCHGCUR_L4 (0xA5) -#define AXP202_EXT_BAT_DISCHGCUR_H8 (0xA6) -#define AXP202_EXT_BAT_DISCHGCUR_L4 (0xA7) -#define AXP202_BAT_CHGCOULOMB3 (0xB0) -#define AXP202_BAT_CHGCOULOMB2 (0xB1) -#define AXP202_BAT_CHGCOULOMB1 (0xB2) -#define AXP202_BAT_CHGCOULOMB0 (0xB3) -#define AXP202_BAT_DISCHGCOULOMB3 (0xB4) -#define AXP202_BAT_DISCHGCOULOMB2 (0xB5) -#define AXP202_BAT_DISCHGCOULOMB1 (0xB6) -#define AXP202_BAT_DISCHGCOULOMB0 (0xB7) -#define AXP202_COULOMB_CTL (0xB8) -#define AXP202_BAT_POWERH8 (0x70) -#define AXP202_BAT_POWERM8 (0x71) -#define AXP202_BAT_POWERL8 (0x72) - -#define AXP202_VREF_TEM_CTRL (0xF3) -#define AXP202_BATT_PERCENTAGE (0xB9) - - -/* bit definitions for AXP events ,irq event */ -/* AXP202 */ -#define AXP202_IRQ_USBLO (1) -#define AXP202_IRQ_USBRE (2) -#define AXP202_IRQ_USBIN (3) -#define AXP202_IRQ_USBOV (4) -#define AXP202_IRQ_ACRE (5) -#define AXP202_IRQ_ACIN (6) -#define AXP202_IRQ_ACOV (7) - -#define AXP202_IRQ_TEMLO (8) -#define AXP202_IRQ_TEMOV (9) -#define AXP202_IRQ_CHAOV (10) -#define AXP202_IRQ_CHAST (11) -#define AXP202_IRQ_BATATOU (12) -#define AXP202_IRQ_BATATIN (13) -#define AXP202_IRQ_BATRE (14) -#define AXP202_IRQ_BATIN (15) - -#define AXP202_IRQ_POKLO (16) -#define AXP202_IRQ_POKSH (17) -#define AXP202_IRQ_LDO3LO (18) -#define AXP202_IRQ_DCDC3LO (19) -#define AXP202_IRQ_DCDC2LO (20) -#define AXP202_IRQ_CHACURLO (22) -#define AXP202_IRQ_ICTEMOV (23) - -#define AXP202_IRQ_EXTLOWARN2 (24) -#define AXP202_IRQ_EXTLOWARN1 (25) -#define AXP202_IRQ_SESSION_END (26) -#define AXP202_IRQ_SESS_AB_VALID (27) -#define AXP202_IRQ_VBUS_UN_VALID (28) -#define AXP202_IRQ_VBUS_VALID (29) -#define AXP202_IRQ_PDOWN_BY_NOE (30) -#define AXP202_IRQ_PUP_BY_NOE (31) - -#define AXP202_IRQ_GPIO0TG (32) -#define AXP202_IRQ_GPIO1TG (33) -#define AXP202_IRQ_GPIO2TG (34) -#define AXP202_IRQ_GPIO3TG (35) -#define AXP202_IRQ_PEKFE (37) -#define AXP202_IRQ_PEKRE (38) -#define AXP202_IRQ_TIMER (39) - - -//Signal Capture -#define AXP202_BATT_VOLTAGE_STEP (1.1F) -#define AXP202_BATT_DISCHARGE_CUR_STEP (0.5F) -#define AXP202_BATT_CHARGE_CUR_STEP (0.5F) -#define AXP202_ACIN_VOLTAGE_STEP (1.7F) -#define AXP202_ACIN_CUR_STEP (0.625F) -#define AXP202_VBUS_VOLTAGE_STEP (1.7F) -#define AXP202_VBUS_CUR_STEP (0.375F) -#define AXP202_INTENAL_TEMP_STEP (0.1F) -#define AXP202_APS_VOLTAGE_STEP (1.4F) -#define AXP202_TS_PIN_OUT_STEP (0.8F) -#define AXP202_GPIO0_STEP (0.5F) -#define AXP202_GPIO1_STEP (0.5F) - - - - -#define FORCED_OPEN_DCDC3(x) (x |= AXP202_DCDC3) -#define BIT_MASK(x) (1 << x) -#define IS_OPEN(reg,channel) (bool)(reg & BIT_MASK(channel)) - -#define AXP202_ON 1 -#define AXP202_OFF 0 - - -enum { - AXP202_EXTEN = 0, - AXP202_DCDC3 = 1, - AXP202_LDO2 = 2, - AXP202_LDO4 = 3, - AXP202_DCDC2 = 4, - AXP202_LDO3 = 6, - AXP202_OUTPUT_MAX, -}; - - -enum { - AXP192_DCDC1 = 0, - AXP192_DCDC3 = 1, - AXP192_LDO2 = 2, - AXP192_LDO3 = 3, - AXP192_DCDC2 = 4, - AXP192_EXTEN = 6, - AXP192_OUTPUT_MAX, -}; - - -typedef enum { - AXP202_STARTUP_TIME_128MS, - AXP202_STARTUP_TIME_3S, - AXP202_STARTUP_TIME_1S, - AXP202_STARTUP_TIME_2S, -} axp202_startup_time_t; - - -typedef enum { - AXP192_STARTUP_TIME_128MS, - AXP192_STARTUP_TIME_512MS, - AXP192_STARTUP_TIME_1S, - AXP192_STARTUP_TIME_2S, -} axp192_startup_time_t; - - - -typedef enum { - AXP_LONGPRESS_TIME_1S, - AXP_LONGPRESS_TIME_1S5, - AXP_LONGPRESS_TIME_2S, - AXP_LONGPRESS_TIME_2S5, -} axp_loonPress_time_t; - - -typedef enum { - AXP_POWER_OFF_TIME_4S, - AXP_POWER_OFF_TIME_65, - AXP_POWER_OFF_TIME_8S, - AXP_POWER_OFF_TIME_16S, -} axp_poweroff_time_t; - -//REG 33H: Charging control 1 Charging target-voltage setting -typedef enum { - AXP202_TARGET_VOL_4_1V, - AXP202_TARGET_VOL_4_15V, - AXP202_TARGET_VOL_4_2V, - AXP202_TARGET_VOL_4_36V -} axp_chargeing_vol_t; - -//REG 82H: ADC Enable 1 register Parameter -typedef enum { - AXP202_BATT_VOL_ADC1 = 1 << 7, - AXP202_BATT_CUR_ADC1 = 1 << 6, - AXP202_ACIN_VOL_ADC1 = 1 << 5, - AXP202_ACIN_CUR_ADC1 = 1 << 4, - AXP202_VBUS_VOL_ADC1 = 1 << 3, - AXP202_VBUS_CUR_ADC1 = 1 << 2, - AXP202_APS_VOL_ADC1 = 1 << 1, - AXP202_TS_PIN_ADC1 = 1 << 0 -} axp_adc1_func_t; - -// REG 83H: ADC Enable 2 register Parameter -typedef enum { - AXP202_TEMP_MONITORING_ADC2 = 1 << 7, - AXP202_GPIO1_FUNC_ADC2 = 1 << 3, - AXP202_GPIO0_FUNC_ADC2 = 1 << 2 -} axp_adc2_func_t; - -typedef enum { - AXP202_LDO3_MODE_LDO, - AXP202_LDO3_MODE_DCIN -} axp202_ldo3_mode_t; - - -typedef enum { - //IRQ1 - AXP202_VBUS_VHOLD_LOW_IRQ = 1 << 1, - AXP202_VBUS_REMOVED_IRQ = 1 << 2, - AXP202_VBUS_CONNECT_IRQ = 1 << 3, - AXP202_VBUS_OVER_VOL_IRQ = 1 << 4, - AXP202_ACIN_REMOVED_IRQ = 1 << 5, - AXP202_ACIN_CONNECT_IRQ = 1 << 6, - AXP202_ACIN_OVER_VOL_IRQ = 1 << 7, - //IRQ2 - AXP202_BATT_LOW_TEMP_IRQ = 1 << 8, - AXP202_BATT_OVER_TEMP_IRQ = 1 << 9, - AXP202_CHARGING_FINISHED_IRQ = 1 << 10, - AXP202_CHARGING_IRQ = 1 << 11, - AXP202_BATT_EXIT_ACTIVATE_IRQ = 1 << 12, - AXP202_BATT_ACTIVATE_IRQ = 1 << 13, - AXP202_BATT_REMOVED_IRQ = 1 << 14, - AXP202_BATT_CONNECT_IRQ = 1 << 15, - //IRQ3 - AXP202_PEK_LONGPRESS_IRQ = 1 << 16, - AXP202_PEK_SHORTPRESS_IRQ = 1 << 17, - AXP202_LDO3_LOW_VOL_IRQ = 1 << 18, - AXP202_DC3_LOW_VOL_IRQ = 1 << 19, - AXP202_DC2_LOW_VOL_IRQ = 1 << 20, - AXP202_CHARGE_LOW_CUR_IRQ = 1 << 21, - AXP202_CHIP_TEMP_HIGH_IRQ = 1 << 22, - - //IRQ4 - AXP202_APS_LOW_VOL_LEVEL2_IRQ = 1 << 24, - APX202_APS_LOW_VOL_LEVEL1_IRQ = 1 << 25, - AXP202_VBUS_SESSION_END_IRQ = 1 << 26, - AXP202_VBUS_SESSION_AB_IRQ = 1 << 27, - AXP202_VBUS_INVALID_IRQ = 1 << 28, - AXP202_VBUS_VAILD_IRQ = 1 << 29, - AXP202_NOE_OFF_IRQ = 1 << 30, - AXP202_NOE_ON_IRQ = 1 << 31, - AXP202_ALL_IRQ = 0xFFFF - -} axp_irq_t; - -typedef enum { - AXP202_LDO4_1250MV, - AXP202_LDO4_1300MV, - AXP202_LDO4_1400MV, - AXP202_LDO4_1500MV, - AXP202_LDO4_1600MV, - AXP202_LDO4_1700MV, - AXP202_LDO4_1800MV, - AXP202_LDO4_1900MV, - AXP202_LDO4_2000MV, - AXP202_LDO4_2500MV, - AXP202_LDO4_2700MV, - AXP202_LDO4_2800MV, - AXP202_LDO4_3000MV, - AXP202_LDO4_3100MV, - AXP202_LDO4_3200MV, - AXP202_LDO4_3300MV, - AXP202_LDO4_MAX, -} axp_ldo4_table_t; - -typedef enum { - AXP20X_LED_OFF, - AXP20X_LED_BLINK_1HZ, - AXP20X_LED_BLINK_4HZ, - AXP20X_LED_LOW_LEVEL, -} axp_chgled_mode_t; - - -typedef enum { - AXP202_GPIO_1V8, - AXP202_GPIO_2V5, - AXP202_GPIO_2V8, - AXP202_GPIO_3V0, - AXP202_GPIO_3V1, - AXP202_GPIO_3V3, - AXP202_GPIO_3V4, - AXP202_GPIO_3V5, -} axp202_gpio_voltage_t; - -typedef enum { - AXP202_GPIO2_OUTPUT_LOW, - AXP202_GPIO2_FLOATING, - AXP202_GPIO3_INPUT, -} axp202_gpio2_mode_t; - -typedef enum { - AXP202_GPIO3_DIGITAL_INPUT, - AXP202_GPIO3_OPEN_DRAIN_OUTPUT, -} axp202_gpio3_mode_t; - -typedef enum { - AXP202_GPIO3_OUTPUT_LOW, - AXP202_GPIO3_FLOATING, -} axp202_gpio3_output_t; - - -typedef enum { - AXP202_GPIO0, - AXP202_GPIO1, - AXP202_GPIO2, - AXP202_GPIO3, -} axp202_gpio_t; - - -typedef enum { - AXP_ADC_SAMPLING_RATE_25HZ = 0, - AXP_ADC_SAMPLING_RATE_50HZ = 1, - AXP_ADC_SAMPLING_RATE_100HZ = 2, - AXP_ADC_SAMPLING_RATE_200HZ = 3, -} axp_adc_sampling_rate_t; - - -typedef enum { - AXP192_GPIO0_NMOD_OUTPUT = 0, - AXP192_GPIO0_INPUT = 1, - AXP192_GPIO0_LDO_OUTPUT = 2, - AXP192_GPIO0_ADC_INPUT = 4, - AXP192_GPIO0_OUTPUT_LOW = 5, - AXP192_GPIO0_FLOATING = 7 -} axp192_gpio0_mode_t; - - -typedef enum { - AXP192_GPIO_1V8, - AXP192_GPIO_1V9, - AXP192_GPIO_2V0, - AXP192_GPIO_2V1, - AXP192_GPIO_2V2, - AXP192_GPIO_2V3, - AXP192_GPIO_2V4, - AXP192_GPIO_2V5, - AXP192_GPIO_2V6, - AXP192_GPIO_2V7, - AXP192_GPIO_2V8, - AXP192_GPIO_2V9, - AXP192_GPIO_3V0, - AXP192_GPIO_3V1, - AXP192_GPIO_3V2, - AXP192_GPIO_3V3, -} axp192_gpio_voltage_t; - - -class AXP20X_Class -{ -public: - int begin(TwoWire &port = Wire, uint8_t addr = AXP202_SLAVE_ADDRESS); - - // Power Output Control - int setPowerOutPut(uint8_t ch, bool en); - - bool isBatteryConnect(); - bool isChargeing(); - bool isLDO2Enable(); - bool isLDO3Enable(); - bool isLDO4Enable(); - bool isDCDC3Enable(); - bool isDCDC2Enable(); - bool isChargeingEnable(); - bool isVBUSPlug(); - - //Only axp192 chip - bool isDCDC1Enable(); - //Only axp192 chip - bool isExtenEnable(); - - //IRQ Status - bool isAcinOverVoltageIRQ(); - bool isAcinPlugInIRQ(); - bool isAcinRemoveIRQ(); - bool isVbusOverVoltageIRQ(); - bool isVbusPlugInIRQ(); - bool isVbusRemoveIRQ(); - bool isVbusLowVHOLDIRQ(); - - bool isBattPlugInIRQ(); - bool isBattRemoveIRQ(); - bool isBattEnterActivateIRQ(); - bool isBattExitActivateIRQ(); - bool isChargingIRQ(); - bool isChargingDoneIRQ(); - bool isBattTempLowIRQ(); - bool isBattTempHighIRQ(); - - bool isPEKShortPressIRQ(); - bool isPEKLongtPressIRQ(); - - //! Group4 ADC data - float getAcinVoltage(); - float getAcinCurrent(); - float getVbusVoltage(); - float getVbusCurrent(); - float getTemp(); - float getTSTemp(); - float getGPIO0Voltage(); - float getGPIO1Voltage(); - float getBattInpower(); - float getBattVoltage(); - float getBattChargeCurrent(); - float getBattDischargeCurrent(); - float getSysIPSOUTVoltage(); - uint32_t getBattChargeCoulomb(); - uint32_t getBattDischargeCoulomb(); - float getSettingChargeCurrent(); - - int setChargingTargetVoltage(axp_chargeing_vol_t param); - int enableChargeing(bool en); - - int adc1Enable(uint16_t params, bool en); - int adc2Enable(uint16_t params, bool en); - - /** - * param: axp202_startup_time_t or axp192_startup_time_t - */ - int setStartupTime(uint8_t param); - - /** - * param: axp_loonPress_time_t - */ - int setlongPressTime(uint8_t param); - - /** - * @param param: axp_poweroff_time_t - */ - int setShutdownTime(uint8_t param); - - - int setTimeOutShutdown(bool en); - - int shutdown(); - - /** - * params: axp_irq_t - */ - int enableIRQ(uint32_t params, bool en); - int readIRQ(); - void clearIRQ(); - - - int setDCDC1Voltage(uint16_t mv); //! Only AXP192 support - // return mv - uint16_t getDCDC1Voltage(); //! Only AXP192 support - - - // ----------------- - int setDCDC2Voltage(uint16_t mv); - int setDCDC3Voltage(uint16_t mv); - int setLDO2Voltage(uint16_t mv); - int setLDO3Voltage(uint16_t mv); - - - int setLDO4Voltage(axp_ldo4_table_t param); //! Only axp202 support - - // return mv - uint16_t getLDO2Voltage(); - uint16_t getLDO3Voltage(); - uint16_t getDCDC2Voltage(); - uint16_t getDCDC3Voltage(); - - - /** - * @param mode: axp_chgled_mode_t - */ - int setChgLEDMode(uint8_t mode); - - - /** - * @param mode: axp202_ldo3_mode_t - */ - int setLDO3Mode(uint8_t mode); //! Only AXP202 support - - int getBattPercentage(); - - int debugCharging(); - int debugStatus(); - int limitingOff(); - - int setAdcSamplingRate(axp_adc_sampling_rate_t rate); - uint8_t getAdcSamplingRate(); - float getCoulombData(); - - - int gpio0Setting(axp192_gpio0_mode_t mode); //! Only axp192 - int gpio0SetVoltage(axp192_gpio_voltage_t vol); - uint16_t gpio0GetVoltage(); - - //! The following features have not been tested - /** - * @brief setGPIO0Voltage - * @note - * @param mv: axp202_gpio_voltage_t enum - * @retval - */ - int setGPIO0Voltage(uint8_t mv); - - /** - * @brief setGPIO0Level - * @note - * @param level: 0 or 1 - * @retval - */ - int setGPIO0Level(uint8_t level); - - /** - * @brief setGPIO1Level - * @note - * @param level: 0 or 1 - * @retval - */ - int setGPIO1Level(uint8_t level); - - /** - * @brief readGpioStatus - * @note - * @retval - */ - int readGpioStatus(); - - int readGpio0Level(); - - int readGpio1Level(); - - int readGpio2Level(); - - int setGpio2Mode(uint8_t mode); - - /** - * @brief setGpio3Mode - * @note Set GPIO3 mode, can only be set to output low level, floating, can not output high level - * @param mode: axp202_gpio3_mode_t enum - * @retval - */ - int setGpio3Mode(uint8_t mode); - - /** - * @brief setGpio3Level - * @note Can only be set when GPIO3 is configured as output mode - * @param level: axp202_gpio3_output_t enum - * @retval - */ - int setGpio3Level(uint8_t level); - - - /** - * @brief setGpioInterruptMode - * @note Interrupt can only be set when GPIO is configured as input mode - * @param gpio: axp202_gpio_t enum - * @param mode: RISING or FALLING - * @param en: true or false - * @retval - */ - int setGpioInterruptMode(uint8_t gpio, int mode, bool en); - -private: - - uint16_t _getRegistH8L5(uint8_t regh8, uint8_t regl4) - { - uint8_t hv, lv; - _readByte(regh8, 1, &hv); - _readByte(regl4, 1, &lv); - return (hv << 5) | (lv & 0x1F); - } - - uint16_t _getRegistResult(uint8_t regh8, uint8_t regl4) - { - uint8_t hv, lv; - _readByte(regh8, 1, &hv); - _readByte(regl4, 1, &lv); - return (hv << 4) | (lv & 0xF); - } - - int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data) - { - if (nbytes == 0 || !data) return -1; - _i2cPort->beginTransmission(_address); - _i2cPort->write(reg); - _i2cPort->endTransmission(); - _i2cPort->requestFrom(_address, nbytes); - uint8_t index = 0; - while (_i2cPort->available()) - data[index++] = _i2cPort->read(); - return 0; - } - - int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data) - { - if (nbytes == 0 || !data) return -1; - _i2cPort->beginTransmission(_address); - _i2cPort->write(reg); - for (uint8_t i = 0; i < nbytes; i++) { - _i2cPort->write(data[i]); - } - _i2cPort->endTransmission(); - return 0; - } - - int _setGpioInterrupt(uint8_t *val, int mode, bool en); - static const uint8_t startupParams[]; - static const uint8_t longPressParams[]; - static const uint8_t shutdownParams[]; - static const uint8_t targetVolParams[]; - static uint8_t _outputReg; - - uint8_t _address; - bool _init = false; - TwoWire *_i2cPort; - uint8_t _irq[5]; - uint8_t _chip_id; - uint8_t _gpio[4]; -}; diff --git a/platformio.ini b/platformio.ini index 9b3f27da..ebc5a958 100644 --- a/platformio.ini +++ b/platformio.ini @@ -43,7 +43,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.8.01 +release_version = 1.8.02 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 @@ -73,6 +73,7 @@ lib_deps_basic = 76@>=1.2.2 ;Timezone by Jack Christensen 274@>=2.3.3 ;RTC by Michael Miller SimpleButton + AXP202X_Library@^1.0.0 lib_deps_all = ${common.lib_deps_basic} ${common.lib_deps_lora} From dccd6d695c18dfd227f7bb66ba562768a73d10b4 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 6 Sep 2019 15:20:03 +0200 Subject: [PATCH 055/105] lorawan.cpp: add lmic_send result codes --- src/lorawan.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index fcba037a..9c3e5664 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -373,7 +373,7 @@ void lora_send(void *pvParameters) { while (1) { - // wait until we are joined if we are not + // postpone until we are joined if we are not while (!LMIC.devaddr) { vTaskDelay(pdMS_TO_TICKS(500)); } @@ -387,23 +387,27 @@ void lora_send(void *pvParameters) { // attempt to transmit payload else { - switch (LMIC_sendWithCallback( + switch (LMIC_sendWithCallback_strict( SendBuffer.MessagePort, SendBuffer.Message, SendBuffer.MessageSize, (cfg.countermode & 0x02), myTxCallback, NULL)) { - case 0: + case LMIC_ERROR_SUCCESS: ESP_LOGI(TAG, "%d byte(s) sent to LORA", SendBuffer.MessageSize); break; - case -1: // LMIC already has a tx message pending - // ESP_LOGD(TAG, "LMIC busy, message re-enqueued"); + case LMIC_ERROR_TX_BUSY: // LMIC already has a tx message pending + case LMIC_ERROR_TX_FAILED: // message was not sent + // ESP_LOGD(TAG, "LMIC busy, message re-enqueued"); // very noisy vTaskDelay(pdMS_TO_TICKS(1000 + random(500))); // wait a while - lora_enqueuedata(&SendBuffer); // re-enqueue the undeliverd message + lora_enqueuedata(&SendBuffer); // re-enqueue the undelivered message break; - case -2: // message size exceeds LMIC buffer size - ESP_LOGW(TAG, "Message size exceeds LMIC buffer, message deleted"); + case LMIC_ERROR_TX_TOO_LARGE: // message size exceeds LMIC buffer size + case LMIC_ERROR_TX_NOT_FEASIBLE: // message too large for current datarate + ESP_LOGI(TAG, + "Message too large to send, message not sent and deleted"); + // we need some kind of error handling here -> to be done break; - default: // unknown LMIC return code - ESP_LOGE(TAG, "Unknown LMIC error, message deleted"); + default: // other LMIC return code + ESP_LOGE(TAG, "LMIC error, message not sent and deleted"); } // switch } @@ -569,6 +573,7 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, ESP_LOGI(TAG, "Received empty message on port %u", port); // list MAC messages, if any + /* uint8_t nMac = pMsg - &LMIC.frame[0]; if (port != MACPORT) --nMac; @@ -578,6 +583,11 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, // whe need to strip some protocol overhead from LMIC.frame to unwrap the // MAC command mac_decode(LMIC.frame, nMac); + */ + + if (LMIC.pendMacLen) { + ESP_LOGI(TAG, "Received %u byte MAC message", LMIC.pendMacLen); + mac_decode(LMIC.pendMacData, LMIC.pendMacLen); } switch (port) { From 76a79940b3222bbf60efd08f27e23ec7c1f8bf29 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 14:52:18 +0200 Subject: [PATCH 056/105] MAC command up/down evaluation --- include/lorawan.h | 3 ++- src/lorawan.cpp | 52 +++++++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/include/lorawan.h b/include/lorawan.h index 9094c132..74a67c04 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -47,7 +47,8 @@ void lora_queuereset(void); void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, size_t nMsg); void myTxCallback(void *pUserData, int fSuccess); -void mac_decode(const uint8_t cmd[], const uint8_t cmdlength); +void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[], + const uint8_t tablesize); #if (TIME_SYNC_LORAWAN) void user_request_network_time_callback(void *pVoidUserUTCTime, diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 9c3e5664..9ad8675a 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -24,8 +24,7 @@ TaskHandle_t lmicTask = NULL, lorasendTask = NULL; // table of LORAWAN MAC messages sent by the network to the device // format: opcode, cmdname (max 19 chars), #bytes params // source: LoRaWAN 1.1 Specification (October 11, 2017) - -static mac_t table[] = { +static const mac_t MACdn_table[] = { {0x01, "ResetConf", 1}, {0x02, "LinkCheckAns", 2}, {0x03, "LinkADRReq", 4}, {0x04, "DutyCycleReq", 1}, {0x05, "RXParamSetupReq", 4}, {0x06, "DevStatusReq", 0}, @@ -35,8 +34,15 @@ static mac_t table[] = { {0x0D, "DeviceTimeAns", 5}, {0x0E, "ForceRejoinReq", 2}, {0x0F, "RejoinParamSetupReq", 1}}; -static const uint8_t cmdtablesize = - sizeof(table) / sizeof(table[0]); // number of commands in MAC table +// table of LORAWAN MAC messages sent by the device to the network +static const mac_t MACup_table[] = { + {0x01, "ResetInd", 1}, {0x02, "LinkCheckReq", 0}, + {0x03, "LinkADRAns", 1}, {0x04, "DutyCycleAns", 0}, + {0x05, "RXParamSetupAns", 1}, {0x06, "DevStatusAns", 2}, + {0x07, "NewChannelAns", 1}, {0x08, "RxTimingSetupAns", 0}, + {0x09, "TxParamSetupAns", 0}, {0x0A, "DlChannelAns", 1}, + {0x0B, "RekeyInd", 1}, {0x0C, "ADRParamSetupAns", 0}, + {0x0D, "DeviceTimeReq", 0}, {0x0F, "RejoinParamSetupAns", 1}}; class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t { @@ -568,26 +574,26 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, // display type of received data if (nMsg) - ESP_LOGI(TAG, "Received %u bytes of payload on port %u", nMsg, port); + ESP_LOGI(TAG, "Received %u byte(s) of payload on port %u", nMsg, port); else if (port) ESP_LOGI(TAG, "Received empty message on port %u", port); // list MAC messages, if any - /* uint8_t nMac = pMsg - &LMIC.frame[0]; if (port != MACPORT) --nMac; if (nMac) { - ESP_LOGI(TAG, "Received %u byte MAC message", nMac); + ESP_LOGI(TAG, "%u byte(s) downlink MAC commands", nMac); // NOT WORKING YET - // whe need to strip some protocol overhead from LMIC.frame to unwrap the - // MAC command - mac_decode(LMIC.frame, nMac); - */ + // whe need to unwrap the MAC command from LMIC.frame here + // mac_decode(LMIC.frame, nMac, MACdn_table, sizeof(MACdn_table) / + // sizeof(MACdn_table[0])); + } if (LMIC.pendMacLen) { - ESP_LOGI(TAG, "Received %u byte MAC message", LMIC.pendMacLen); - mac_decode(LMIC.pendMacData, LMIC.pendMacLen); + ESP_LOGI(TAG, "%u byte(s) uplink MAC commands", LMIC.pendMacLen); + mac_decode(LMIC.pendMacData, LMIC.pendMacLen, MACup_table, + sizeof(MACup_table) / sizeof(MACup_table[0])); } switch (port) { @@ -623,32 +629,34 @@ void myTxCallback(void *pUserData, int fSuccess) { } // decode LORAWAN MAC message -void mac_decode(const uint8_t cmd[], const uint8_t cmdlength) { +void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[], + const uint8_t tablesize) { - if (!cmdlength) + if (!cmdlen) return; - uint8_t foundcmd[cmdlength], cursor = 0; + uint8_t foundcmd[cmdlen], cursor = 0; - while (cursor < cmdlength) { + while (cursor < cmdlen) { + + int i = tablesize; // number of commands in table - int i = cmdtablesize; while (i--) { if (cmd[cursor] == table[i].opcode) { // lookup command in opcode table cursor++; // strip 1 byte opcode - if ((cursor + table[i].params) <= cmdlength) { + if ((cursor + table[i].params) <= cmdlen) { memmove(foundcmd, cmd + cursor, table[i].params); // strip opcode from cmd array cursor += table[i].params; - ESP_LOGD(TAG, "Network command %s", table[i].cmdname); + ESP_LOGD(TAG, "MAC command %s", table[i].cmdname); } else - ESP_LOGD(TAG, "MAC message 0x%02X with missing parameter(s)", + ESP_LOGD(TAG, "MAC command 0x%02X with missing parameter(s)", table[i].opcode); break; // command found -> exit table lookup loop } // end of command validation } // end of command table lookup loop if (i < 0) { // command not found -> skip it - ESP_LOGD(TAG, "Unknown MAC message 0x%02X", cmd[cursor]); + ESP_LOGD(TAG, "Unknown MAC command 0x%02X", cmd[cursor]); cursor++; } } // command parsing loop From 15389516f52a8bee8a8d169dc0965dbc23c4bdaf Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 15:02:43 +0200 Subject: [PATCH 057/105] added setting for wifi power save off --- src/wifiscan.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 12ec9c82..6951ad6a 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -71,6 +71,7 @@ void wifi_sniffer_init(void) { ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL)); + ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); // no modem power saving ESP_ERROR_CHECK(esp_wifi_start()); // channel switch throws error without ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter)); // set frame filter ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler)); From 506b1f4f7e7b8155dbb49ac036e8cff33132c49d Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 17:00:00 +0200 Subject: [PATCH 058/105] remove clock error setting, using interrupt timing --- src/lmic_config.h | 2 +- src/lorawan.cpp | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/lmic_config.h b/src/lmic_config.h index 0f1f426b..06a4da4c 100644 --- a/src/lmic_config.h +++ b/src/lmic_config.h @@ -37,7 +37,7 @@ // so consuming more power. You may sharpen (reduce) this value if you are // limited on battery. // ATTN: VALUES > 7 WILL CAUSE RECEPTION AND JOIN PROBLEMS WITH HIGH SF RATES -#define CLOCK_ERROR_PROCENTAGE 7 +//#define CLOCK_ERROR_PROCENTAGE 7 // Set this to 1 to enable some basic debug output (using printf) about // RF settings used during transmission and reception. Set to 2 to diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 9ad8675a..1e8c641f 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -541,11 +541,13 @@ void lmictask(void *pvParameters) { os_init(); // initialize lmic run-time environment LMIC_reset(); // initialize lmic MAC LMIC_setLinkCheckMode(0); - // This tells LMIC to make the receive windows bigger, in case your clock is - // faster or slower. This causes the transceiver to be earlier switched on, - // so consuming more power. You may sharpen (reduce) CLOCK_ERROR_PERCENTAGE - // in src/lmic_config.h if you are limited on battery. +// This tells LMIC to make the receive windows bigger, in case your clock is +// faster or slower. This causes the transceiver to be earlier switched on, +// so consuming more power. You may sharpen (reduce) CLOCK_ERROR_PERCENTAGE +// in src/lmic_config.h if you are limited on battery. +#ifdef CLOCK_ERROR_PROCENTAGE LMIC_setClockError(MAX_CLOCK_ERROR * CLOCK_ERROR_PROCENTAGE / 100); +#endif // Set the data rate to Spreading Factor 7. This is the fastest supported // rate for 125 kHz channels, and it minimizes air time and battery power. // Set the transmission power to 14 dBi (25 mW). From 0dea735bfb8335bd8d3d8ad697f0a9327f3a9444 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 18:02:27 +0200 Subject: [PATCH 059/105] lmic_config.h sanitized --- src/lmic_config.h | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/lmic_config.h b/src/lmic_config.h index 06a4da4c..788a07e1 100644 --- a/src/lmic_config.h +++ b/src/lmic_config.h @@ -2,19 +2,16 @@ // COUNTRY SETTINGS // --> please check with you local regulations for ISM band frequency use! -// -// CFG_eu868 EU 863-870 MHz -// CFG_us915 US 902-928 MHz -// CFG_au921 Australia 915-928 MHz -// CFG_as923 Asia 923 MHz -// CFG_in866 India 865-867 MHz -#define CFG_eu868 1 -//#define CFG_us915 1 -//#define CFG_in866 1 -//#define CFG_au921 1 -//#define CFG_as923 1 -//#define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP /* for as923-JP */ +#define CFG_eu868 1 // Europe (high band) +//#define CFG_eu433 1 // Europe (low band) +//#define CFG_us915 1 // USA, Canada and South America +//#define CFG_in866 1 // India +//#define CFG_au921 1 // Australia +//#define CFG_as923 1 // Asia +//#define CFG_cn783 1 // China (high band) +//#define CFG_cn490 1 // China (low band) +//#define CFG_kr920 1 // Korea // LMIC LORAWAN STACK SETTINGS // --> adapt to your device only if necessary @@ -26,12 +23,6 @@ // time sync via LoRaWAN network, note: not supported by TTNv2 // #define LMIC_ENABLE_DeviceTimeReq 1 -// 16 μs per tick -// LMIC requires ticks to be 15.5μs - 100 μs long -#define US_PER_OSTICK_EXPONENT 4 -#define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT) -#define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK) - // This tells LMIC to make the receive windows bigger, in case your clock is // faster or slower. This causes the transceiver to be earlier switched on, // so consuming more power. You may sharpen (reduce) this value if you are @@ -51,6 +42,11 @@ // current implementation only works on AVR, though. //#define LMIC_PRINTF_TO Serial +// Change the SPI clock speed if you encounter errors +// communicating with the radio. +// The standard range is 125kHz-8MHz, but some boards can go faster. +//#define LMIC_SPI_FREQ 1E6 + // Any runtime assertion failures are printed to this serial port (or // any other Print object). If this is unset, any failures just silently // halt execution. @@ -92,7 +88,7 @@ // implementation is optimized for speed on 32-bit processors using // fairly big lookup tables, but it takes up big amounts of flash on the // AVR architecture. -//#define USE_ORIGINAL_AES +#define USE_ORIGINAL_AES // // This selects the AES implementation written by Ideetroon for their // own LoRaWAN library. It also uses lookup tables, but smaller @@ -100,4 +96,4 @@ // also about twice as slow as the original). // #define USE_IDEETRON_AES // -#define USE_MBEDTLS_AES +//#define USE_MBEDTLS_AES From 738543b5299521109e23522ce51767e0386f210f Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 19:12:23 +0200 Subject: [PATCH 060/105] i2scan.cpp bugfix bus select --- src/i2cscan.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/i2cscan.cpp b/src/i2cscan.cpp index c57d0604..ea7e83ce 100644 --- a/src/i2cscan.cpp +++ b/src/i2cscan.cpp @@ -22,8 +22,12 @@ int i2c_scan(void) { for (addr = 8; addr <= 119; addr++) { - // scan i2c bus with no more to 100KHz +// scan i2c bus with no more to 100KHz +#ifdef HAS_DISPLAY + Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 100000); +#else Wire.begin(SDA, SCL, 100000); +#endif Wire.beginTransmission(addr); Wire.write(addr); i2c_ret = Wire.endTransmission(); @@ -87,7 +91,7 @@ void AXP192_init(void) { axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); axp.setDCDC1Voltage(3300); axp.setChgLEDMode(AXP20X_LED_BLINK_1HZ); - //axp.setChgLEDMode(AXP20X_LED_OFF); + // axp.setChgLEDMode(AXP20X_LED_OFF); axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); #ifdef PMU_INT From a1b7c102d026103b5cb4e6251d473d2257d6cada Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 19:52:25 +0200 Subject: [PATCH 061/105] power.cpp added, i2cscan adapted --- include/i2cscan.h | 12 +++++++---- include/main.h | 9 ++++---- include/power.h | 13 ++++++++++++ src/i2cscan.cpp | 52 +---------------------------------------------- src/main.cpp | 18 +++++++++------- src/power.cpp | 42 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 80 insertions(+), 66 deletions(-) create mode 100644 include/power.h create mode 100644 src/power.cpp diff --git a/include/i2cscan.h b/include/i2cscan.h index b834b34f..38487e76 100644 --- a/include/i2cscan.h +++ b/include/i2cscan.h @@ -2,11 +2,15 @@ #define _I2CSCAN_H #include -#ifdef HAS_PMU -#include "axp20x.h" -#endif + +#define SSD1306_PRIMARY_ADDRESS (0x3D) +#define SSD1306_SECONDARY_ADDRESS (0x3C) +#define BME_PRIMARY_ADDRESS (0x77) +#define BME_SECONDARY_ADDRESS (0x76) +#define AXP192_PRIMARY_ADDRESS (0x34) +#define MCP_24AA02E64_PRIMARY_ADDRESS (0x50) +#define QUECTEL_GPS_PRIMARY_ADDRESS (0x10) int i2c_scan(void); -void AXP192_init(void); #endif \ No newline at end of file diff --git a/include/main.h b/include/main.h index ddc49d5d..4b5617cb 100644 --- a/include/main.h +++ b/include/main.h @@ -1,12 +1,13 @@ #ifndef _MAIN_H #define _MAIN_H -#include // needed for reading ESP32 chip attributes -#include // needed for Wifi event handler +#include // needed for reading ESP32 chip attributes +#include // needed for Wifi event handler #include // needed for timers -#include // needed for showing coex sw version +#include // needed for showing coex sw version #include "globals.h" +#include "power.h" #include "i2cscan.h" #include "blescan.h" #include "wifiscan.h" @@ -17,7 +18,7 @@ #include "irqhandler.h" #include "led.h" #include "spislave.h" -#if(HAS_LORA) +#if (HAS_LORA) #include "lorawan.h" #endif #include "timekeeper.h" diff --git a/include/power.h b/include/power.h new file mode 100644 index 00000000..f557edb4 --- /dev/null +++ b/include/power.h @@ -0,0 +1,13 @@ +#ifndef _POWER_H +#define _POWER_H + +#include +#include "i2cscan.h" + +#ifdef HAS_PMU +#include +#endif + +void AXP192_init(void); + +#endif \ No newline at end of file diff --git a/src/i2cscan.cpp b/src/i2cscan.cpp index ea7e83ce..e3deb9f0 100644 --- a/src/i2cscan.cpp +++ b/src/i2cscan.cpp @@ -5,14 +5,6 @@ // Local logging tag static const char TAG[] = __FILE__; -#define SSD1306_PRIMARY_ADDRESS (0x3D) -#define SSD1306_SECONDARY_ADDRESS (0x3C) -#define BME_PRIMARY_ADDRESS (0x77) -#define BME_SECONDARY_ADDRESS (0x76) -#define AXP192_PRIMARY_ADDRESS (0x34) -#define MCP_24AA02E64_PRIMARY_ADDRESS (0x50) -#define QUECTEL_GPS_PRIMARY_ADDRESS (0x10) - int i2c_scan(void) { int i2c_ret, addr; @@ -49,9 +41,6 @@ int i2c_scan(void) { case AXP192_PRIMARY_ADDRESS: ESP_LOGI(TAG, "0x%X: AXP192 power management", addr); -#ifdef HAS_PMU - AXP192_init(); -#endif break; case QUECTEL_GPS_PRIMARY_ADDRESS: @@ -72,43 +61,4 @@ int i2c_scan(void) { ESP_LOGI(TAG, "I2C scan done, %u devices found.", devices); return devices; -} - -#ifdef HAS_PMU - -void AXP192_init(void) { - - AXP20X_Class axp; - - if (axp.begin(Wire, AXP192_PRIMARY_ADDRESS)) - ESP_LOGI(TAG, "AXP192 PMU initialization failed"); - else { - - axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); - axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); - axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); - axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); - axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); - axp.setDCDC1Voltage(3300); - axp.setChgLEDMode(AXP20X_LED_BLINK_1HZ); - // axp.setChgLEDMode(AXP20X_LED_OFF); - axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); - -#ifdef PMU_INT - pinMode(PMU_INT, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(PMU_INT), - [] { - ESP_LOGI(TAG, "Power source changed"); - /* put your code here */ - }, - FALLING); - axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | - AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, - 1); - axp.clearIRQ(); -#endif // PMU_INT - - ESP_LOGI(TAG, "AXP192 PMU initialized."); - } -} -#endif // HAS_PMU \ No newline at end of file +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 0dc90395..3a466e68 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -169,6 +169,17 @@ void setup() { ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); #endif +// setup power on boards with power management logic +#ifdef EXT_POWER_SW + pinMode(EXT_POWER_SW, OUTPUT); + digitalWrite(EXT_POWER_SW, EXT_POWER_ON); + strcat_P(features, " VEXT"); +#endif +#ifdef HAS_PMU + AXP192_init(); + strcat_P(features, " PMU"); +#endif + i2c_scan(); #endif // verbose @@ -189,13 +200,6 @@ void setup() { strcat_P(features, " PSRAM"); #endif -// set external power mode -#ifdef EXT_POWER_SW - pinMode(EXT_POWER_SW, OUTPUT); - digitalWrite(EXT_POWER_SW, EXT_POWER_ON); - strcat_P(features, " VEXT"); -#endif - #ifdef BAT_MEASURE_EN pinMode(BAT_MEASURE_EN, OUTPUT); #endif diff --git a/src/power.cpp b/src/power.cpp new file mode 100644 index 00000000..3a492256 --- /dev/null +++ b/src/power.cpp @@ -0,0 +1,42 @@ +// Basic config +#include "globals.h" +#include "power.h" + +#ifdef HAS_PMU + +void AXP192_init(void) { + + AXP20X_Class axp; + + if (axp.begin(Wire, AXP192_PRIMARY_ADDRESS)) + ESP_LOGI(TAG, "AXP192 PMU initialization failed"); + else { + + axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); + axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); + axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); + axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); + axp.setDCDC1Voltage(3300); + axp.setChgLEDMode(AXP20X_LED_BLINK_1HZ); + // axp.setChgLEDMode(AXP20X_LED_OFF); + axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); + +#ifdef PMU_INT + pinMode(PMU_INT, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(PMU_INT), + [] { + ESP_LOGI(TAG, "Power source changed"); + /* put your code here */ + }, + FALLING); + axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | + AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, + 1); + axp.clearIRQ(); +#endif // PMU_INT + + ESP_LOGI(TAG, "AXP192 PMU initialized."); + } +} +#endif // HAS_PMU \ No newline at end of file From 56f1ed4b8e3d1599cdc62d60c1075c601889d9f5 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 7 Sep 2019 23:10:53 +0200 Subject: [PATCH 062/105] battery & power code sanitization --- include/battery.h | 14 ------- include/globals.h | 5 +-- include/ota.h | 1 - include/power.h | 8 ++++ src/battery.cpp | 73 ----------------------------------- src/cyclic.cpp | 2 +- src/display.cpp | 2 +- src/main.cpp | 2 +- src/ota.cpp | 2 +- src/power.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++++-- 10 files changed, 107 insertions(+), 100 deletions(-) delete mode 100644 include/battery.h delete mode 100644 src/battery.cpp diff --git a/include/battery.h b/include/battery.h deleted file mode 100644 index b4a83676..00000000 --- a/include/battery.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _BATTERY_H -#define _BATTERY_H - -#include -#include - -#define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate -#define NO_OF_SAMPLES 64 // we do some multisampling to get better values - -uint16_t read_voltage(void); -void calibrate_voltage(void); -bool batt_sufficient(void); - -#endif diff --git a/include/globals.h b/include/globals.h index a112e481..67ec93d2 100644 --- a/include/globals.h +++ b/include/globals.h @@ -121,6 +121,7 @@ extern time_t userUTCTime; #include "led.h" #include "payload.h" #include "blescan.h" +#include "power.h" #if (HAS_GPS) #include "gpsread.h" @@ -142,10 +143,6 @@ extern time_t userUTCTime; #include "button.h" #endif -#ifdef BAT_MEASURE_ADC -#include "battery.h" -#endif - #ifdef HAS_ANTENNA_SWITCH #include "antenna.h" #endif diff --git a/include/ota.h b/include/ota.h index 41ab5767..59bf876c 100644 --- a/include/ota.h +++ b/include/ota.h @@ -4,7 +4,6 @@ #ifdef USE_OTA #include "globals.h" -#include "battery.h" #include #include #include diff --git a/include/power.h b/include/power.h index f557edb4..849ea3b1 100644 --- a/include/power.h +++ b/include/power.h @@ -2,12 +2,20 @@ #define _POWER_H #include +#include +#include #include "i2cscan.h" +#define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate +#define NO_OF_SAMPLES 64 // we do some multisampling to get better values + #ifdef HAS_PMU #include #endif void AXP192_init(void); +uint16_t read_voltage(void); +void calibrate_voltage(void); +uint8_t getBattLevel (void); #endif \ No newline at end of file diff --git a/src/battery.cpp b/src/battery.cpp deleted file mode 100644 index 39b78683..00000000 --- a/src/battery.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "globals.h" - -// Local logging tag -static const char TAG[] = __FILE__; - -#ifdef BAT_MEASURE_ADC -esp_adc_cal_characteristics_t *adc_characs = - (esp_adc_cal_characteristics_t *)calloc( - 1, sizeof(esp_adc_cal_characteristics_t)); - -static const adc1_channel_t adc_channel = BAT_MEASURE_ADC; -static const adc_atten_t atten = ADC_ATTEN_DB_11; -static const adc_unit_t unit = ADC_UNIT_1; -#endif - -void calibrate_voltage(void) { -#ifdef BAT_MEASURE_ADC - // configure ADC - ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12)); - ESP_ERROR_CHECK(adc1_config_channel_atten(adc_channel, atten)); - // calibrate ADC - esp_adc_cal_value_t val_type = esp_adc_cal_characterize( - unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_characs); - // show ADC characterization base - if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) { - ESP_LOGI(TAG, - "ADC characterization based on Two Point values stored in eFuse"); - } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) { - ESP_LOGI(TAG, - "ADC characterization based on reference voltage stored in eFuse"); - } else { - ESP_LOGI(TAG, "ADC characterization based on default reference voltage"); - } -#endif -} - -uint16_t read_voltage() { -#ifdef BAT_MEASURE_ADC - // multisample ADC - uint32_t adc_reading = 0; - for (int i = 0; i < NO_OF_SAMPLES; i++) { - adc_reading += adc1_get_raw(adc_channel); - } - adc_reading /= NO_OF_SAMPLES; - // Convert ADC reading to voltage in mV - uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_characs); -#ifdef BAT_VOLTAGE_DIVIDER - voltage *= BAT_VOLTAGE_DIVIDER; -#endif - -#ifdef BAT_MEASURE_EN // turn ext. power off - digitalWrite(EXT_POWER_SW, EXT_POWER_OFF); -#endif - -#ifdef HAS_PMU - voltage = axp.getBattVoltage(); -#endif - - return (uint16_t)voltage; -#else - return 0; -#endif -} - -bool batt_sufficient() { -#ifdef BAT_MEASURE_ADC - uint16_t volts = read_voltage(); - return ((volts < 1000) || - (volts > OTA_MIN_BATT)); // no battery or battery sufficient -#else - return true; -#endif -} \ No newline at end of file diff --git a/src/cyclic.cpp b/src/cyclic.cpp index a4ba6703..0b51d88b 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -54,7 +54,7 @@ void doHousekeeping() { #endif // read battery voltage into global variable -#ifdef BAT_MEASURE_ADC +#if (defined BAT_MEASURE_ADC || defined HAS_PMU) batt_voltage = read_voltage(); ESP_LOGI(TAG, "Voltage: %dmV", batt_voltage); #endif diff --git a/src/display.cpp b/src/display.cpp index d6cb3d3e..e6d17301 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -188,7 +188,7 @@ void draw_page(time_t t, uint8_t page) { case 0: // update Battery status (line 2) -#ifdef BAT_MEASURE_ADC +#if (defined BAT_MEASURE_ADC || defined HAS_PMU) u8x8.setCursor(0, 2); u8x8.printf("B:%.2fV", batt_voltage / 1000.0); #endif diff --git a/src/main.cpp b/src/main.cpp index 3a466e68..2c5fc606 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -248,7 +248,7 @@ void setup() { #endif // initialize battery status -#ifdef BAT_MEASURE_ADC +#if (defined BAT_MEASURE_ADC || defined HAS_PMU) strcat_P(features, " BATT"); calibrate_voltage(); batt_voltage = read_voltage(); diff --git a/src/ota.cpp b/src/ota.cpp index fc1662bc..1a1e9052 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -41,7 +41,7 @@ inline String getHeaderValue(String header, String headerName) { void start_ota_update() { // check battery status if we can before doing ota - if (!batt_sufficient()) { + if (getBattLevel() == MCMD_DEVS_BATT_MIN) { ESP_LOGE(TAG, "Battery voltage %dmV too low for OTA", batt_voltage); return; } diff --git a/src/power.cpp b/src/power.cpp index 3a492256..5797da26 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -2,12 +2,15 @@ #include "globals.h" #include "power.h" +// Local logging tag +static const char TAG[] = __FILE__; + #ifdef HAS_PMU +AXP20X_Class axp; + void AXP192_init(void) { - - AXP20X_Class axp; - + if (axp.begin(Wire, AXP192_PRIMARY_ADDRESS)) ESP_LOGI(TAG, "AXP192 PMU initialization failed"); else { @@ -39,4 +42,91 @@ void AXP192_init(void) { ESP_LOGI(TAG, "AXP192 PMU initialized."); } } -#endif // HAS_PMU \ No newline at end of file +#endif // HAS_PMU + +#ifdef BAT_MEASURE_ADC +esp_adc_cal_characteristics_t *adc_characs = + (esp_adc_cal_characteristics_t *)calloc( + 1, sizeof(esp_adc_cal_characteristics_t)); + +static const adc1_channel_t adc_channel = BAT_MEASURE_ADC; +static const adc_atten_t atten = ADC_ATTEN_DB_11; +static const adc_unit_t unit = ADC_UNIT_1; +#endif + +void calibrate_voltage(void) { +#ifdef BAT_MEASURE_ADC + // configure ADC + ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12)); + ESP_ERROR_CHECK(adc1_config_channel_atten(adc_channel, atten)); + // calibrate ADC + esp_adc_cal_value_t val_type = esp_adc_cal_characterize( + unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_characs); + // show ADC characterization base + if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) { + ESP_LOGI(TAG, + "ADC characterization based on Two Point values stored in eFuse"); + } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) { + ESP_LOGI(TAG, + "ADC characterization based on reference voltage stored in eFuse"); + } else { + ESP_LOGI(TAG, "ADC characterization based on default reference voltage"); + } +#endif +} + + +uint8_t getBattLevel() { + /* + return values: + MCMD_DEVS_EXT_POWER = 0x00, // external power supply + MCMD_DEVS_BATT_MIN = 0x01, // min battery value + MCMD_DEVS_BATT_MAX = 0xFE, // max battery value + MCMD_DEVS_BATT_NOINFO = 0xFF, // unknown battery level + */ +#if (defined HAS_PMU || defined BAT_MEASURE_ADC) + uint16_t voltage = read_voltage(); + + switch (voltage) { + case 0: + return MCMD_DEVS_BATT_NOINFO; + case 0xffff: + return MCMD_DEVS_EXT_POWER; + default: + return (voltage > OTA_MIN_BATT ? MCMD_DEVS_BATT_MAX : MCMD_DEVS_BATT_MIN); + } +#else // we don't have any info on battery level + return MCMD_DEVS_BATT_NOINFO; +#endif +} // getBattLevel() + +// u1_t os_getBattLevel(void) { return getBattLevel(); }; + + +uint16_t read_voltage() { + + uint16_t voltage = 0; + +#ifdef HAS_PMU + voltage = axp.isVBUSPlug() ? 0xffff : axp.getBattVoltage(); +#else + +#ifdef BAT_MEASURE_ADC + // multisample ADC + uint32_t adc_reading = 0; + for (int i = 0; i < NO_OF_SAMPLES; i++) { + adc_reading += adc1_get_raw(adc_channel); + } + adc_reading /= NO_OF_SAMPLES; + // Convert ADC reading to voltage in mV + voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_characs); +#endif + +#ifdef BAT_VOLTAGE_DIVIDER + voltage *= BAT_VOLTAGE_DIVIDER; +#endif + +#endif // HAS_PMU + + return voltage; +} \ No newline at end of file From bbc259255210b445a200938d39a20d6edf93f169 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 8 Sep 2019 12:32:22 +0200 Subject: [PATCH 063/105] wifi_start removed again --- src/wifiscan.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 6951ad6a..3695508f 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -72,7 +72,6 @@ void wifi_sniffer_init(void) { esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL)); ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); // no modem power saving - ESP_ERROR_CHECK(esp_wifi_start()); // channel switch throws error without ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter)); // set frame filter ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler)); ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode From 81f1bc5c7048e8c821267868632e52f886c132e7 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 8 Sep 2019 12:55:27 +0200 Subject: [PATCH 064/105] Heltecv2 battery monitor --- src/hal/heltecv2.h | 5 +++-- src/power.cpp | 28 +++++++++++++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/hal/heltecv2.h b/src/hal/heltecv2.h index 3f6bf743..cc7de4d1 100644 --- a/src/hal/heltecv2.h +++ b/src/hal/heltecv2.h @@ -20,8 +20,9 @@ #define HAS_LED LED_BUILTIN // white LED on board #define HAS_BUTTON KEY_BUILTIN // button "PROG" on board -//#define BAT_MEASURE_ADC ADC2_GPIO13_CHANNEL // battery probe GPIO pin -//#define BAT_VOLTAGE_DIVIDER 4 // voltage divider 220k/100k on board +#define BAT_MEASURE_ADC ADC2_GPIO13_CHANNEL // battery probe GPIO pin +#define BAT_MEASURE_ADC_UNIT 2 // ADC 2 +#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 220k/100k on board #define EXT_POWER_SW Vext // switches battery power, Vext control 0 = on / 1 = off #define EXT_POWER_ON 0 //#define EXT_POWER_OFF 1 diff --git a/src/power.cpp b/src/power.cpp index 5797da26..ad366d8b 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -10,7 +10,7 @@ static const char TAG[] = __FILE__; AXP20X_Class axp; void AXP192_init(void) { - + if (axp.begin(Wire, AXP192_PRIMARY_ADDRESS)) ESP_LOGI(TAG, "AXP192 PMU initialization failed"); else { @@ -49,16 +49,26 @@ esp_adc_cal_characteristics_t *adc_characs = (esp_adc_cal_characteristics_t *)calloc( 1, sizeof(esp_adc_cal_characteristics_t)); +#ifndef BAT_MEASURE_ADC_UNIT // ADC1 static const adc1_channel_t adc_channel = BAT_MEASURE_ADC; +#else // ADC2 +static const adc2_channel_t adc_channel = BAT_MEASURE_ADC; +#endif static const adc_atten_t atten = ADC_ATTEN_DB_11; static const adc_unit_t unit = ADC_UNIT_1; -#endif + +#endif // BAT_MEASURE_ADC void calibrate_voltage(void) { #ifdef BAT_MEASURE_ADC - // configure ADC +// configure ADC +#ifndef BAT_MEASURE_ADC_UNIT // ADC1 ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12)); ESP_ERROR_CHECK(adc1_config_channel_atten(adc_channel, atten)); +#else // ADC2 + // ESP_ERROR_CHECK(adc2_config_width(ADC_WIDTH_BIT_12)); + ESP_ERROR_CHECK(adc2_config_channel_atten(adc_channel, atten)); +#endif // calibrate ADC esp_adc_cal_value_t val_type = esp_adc_cal_characterize( unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_characs); @@ -75,7 +85,6 @@ void calibrate_voltage(void) { #endif } - uint8_t getBattLevel() { /* return values: @@ -102,7 +111,6 @@ uint8_t getBattLevel() { // u1_t os_getBattLevel(void) { return getBattLevel(); }; - uint16_t read_voltage() { uint16_t voltage = 0; @@ -114,17 +122,23 @@ uint16_t read_voltage() { #ifdef BAT_MEASURE_ADC // multisample ADC uint32_t adc_reading = 0; + int adc_buf = 0; for (int i = 0; i < NO_OF_SAMPLES; i++) { +#ifndef BAT_MEASURE_ADC_UNIT // ADC1 adc_reading += adc1_get_raw(adc_channel); +#else // ADC2 + ESP_ERROR_CHECK(adc2_get_raw(adc_channel, ADC_WIDTH_BIT_12, &adc_buf)); + adc_reading += adc_buf; +#endif } adc_reading /= NO_OF_SAMPLES; // Convert ADC reading to voltage in mV voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_characs); -#endif +#endif // BAT_MEASURE_ADC #ifdef BAT_VOLTAGE_DIVIDER voltage *= BAT_VOLTAGE_DIVIDER; -#endif +#endif // BAT_VOLTAGE_DIVIDER #endif // HAS_PMU From 5ca4d2f721bc262b37c6478e603a692c478ca084 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 9 Sep 2019 11:18:37 +0200 Subject: [PATCH 065/105] TTGO T-Beam v10 PMU init bugfix --- src/i2cscan.cpp | 7 +------ src/main.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/i2cscan.cpp b/src/i2cscan.cpp index e3deb9f0..7ce0f6b0 100644 --- a/src/i2cscan.cpp +++ b/src/i2cscan.cpp @@ -14,12 +14,7 @@ int i2c_scan(void) { for (addr = 8; addr <= 119; addr++) { -// scan i2c bus with no more to 100KHz -#ifdef HAS_DISPLAY - Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 100000); -#else - Wire.begin(SDA, SCL, 100000); -#endif + // scan i2c bus with no more to 100KHz Wire.beginTransmission(addr); Wire.write(addr); i2c_ret = Wire.endTransmission(); diff --git a/src/main.cpp b/src/main.cpp index 2c5fc606..2937f793 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -169,6 +169,13 @@ void setup() { ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); #endif +// open i2c bus +#ifdef HAS_DISPLAY + Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 100000); +#else + Wire.begin(SDA, SCL, 100000); +#endif + // setup power on boards with power management logic #ifdef EXT_POWER_SW pinMode(EXT_POWER_SW, OUTPUT); @@ -180,6 +187,7 @@ void setup() { strcat_P(features, " PMU"); #endif + // scan i2c bus for devices i2c_scan(); #endif // verbose From 6dbbf14ef86b3ea07e91cddab0e46d8b769273dc Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 9 Sep 2019 12:06:23 +0200 Subject: [PATCH 066/105] i2cscan & PMU i2c mutexing --- src/i2cscan.cpp | 71 ++++++++++++++++++++++++--------------------- src/power.cpp | 76 ++++++++++++++++++++++++++++++------------------- 2 files changed, 86 insertions(+), 61 deletions(-) diff --git a/src/i2cscan.cpp b/src/i2cscan.cpp index 7ce0f6b0..c80c2af7 100644 --- a/src/i2cscan.cpp +++ b/src/i2cscan.cpp @@ -12,48 +12,55 @@ int i2c_scan(void) { ESP_LOGI(TAG, "Starting I2C bus scan..."); - for (addr = 8; addr <= 119; addr++) { + // block i2c bus access + if (I2C_MUTEX_LOCK()) { - // scan i2c bus with no more to 100KHz - Wire.beginTransmission(addr); - Wire.write(addr); - i2c_ret = Wire.endTransmission(); + for (addr = 8; addr <= 119; addr++) { - if (i2c_ret == 0) { - devices++; + // scan i2c bus with no more to 100KHz + Wire.beginTransmission(addr); + Wire.write(addr); + i2c_ret = Wire.endTransmission(); - switch (addr) { + if (i2c_ret == 0) { + devices++; - case SSD1306_PRIMARY_ADDRESS: - case SSD1306_SECONDARY_ADDRESS: - ESP_LOGI(TAG, "0x%X: SSD1306 Display controller", addr); - break; + switch (addr) { - case BME_PRIMARY_ADDRESS: - case BME_SECONDARY_ADDRESS: - ESP_LOGI(TAG, "0x%X: Bosch BME MEMS", addr); - break; + case SSD1306_PRIMARY_ADDRESS: + case SSD1306_SECONDARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: SSD1306 Display controller", addr); + break; - case AXP192_PRIMARY_ADDRESS: - ESP_LOGI(TAG, "0x%X: AXP192 power management", addr); - break; + case BME_PRIMARY_ADDRESS: + case BME_SECONDARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: Bosch BME MEMS", addr); + break; - case QUECTEL_GPS_PRIMARY_ADDRESS: - ESP_LOGI(TAG, "0x%X: Quectel GPS", addr); - break; + case AXP192_PRIMARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: AXP192 power management", addr); + break; - case MCP_24AA02E64_PRIMARY_ADDRESS: - ESP_LOGI(TAG, "0x%X: 24AA02E64 serial EEPROM", addr); - break; + case QUECTEL_GPS_PRIMARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: Quectel GPS", addr); + break; - default: - ESP_LOGI(TAG, "0x%X: Unknown device", addr); - break; - } - } // switch - } // for loop + case MCP_24AA02E64_PRIMARY_ADDRESS: + ESP_LOGI(TAG, "0x%X: 24AA02E64 serial EEPROM", addr); + break; - ESP_LOGI(TAG, "I2C scan done, %u devices found.", devices); + default: + ESP_LOGI(TAG, "0x%X: Unknown device", addr); + break; + } + } // switch + } // for loop + + ESP_LOGI(TAG, "I2C scan done, %u devices found.", devices); + + I2C_MUTEX_UNLOCK(); // release i2c bus access + } else + ESP_LOGE(TAG, "I2c bus busy - scan error"); return devices; } \ No newline at end of file diff --git a/src/power.cpp b/src/power.cpp index ad366d8b..5c0d93cb 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -7,40 +7,58 @@ static const char TAG[] = __FILE__; #ifdef HAS_PMU -AXP20X_Class axp; +AXP20X_Class pmu; void AXP192_init(void) { - if (axp.begin(Wire, AXP192_PRIMARY_ADDRESS)) - ESP_LOGI(TAG, "AXP192 PMU initialization failed"); - else { + // block i2c bus access + if (I2C_MUTEX_LOCK()) { - axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); - axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); - axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON); - axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON); - axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); - axp.setDCDC1Voltage(3300); - axp.setChgLEDMode(AXP20X_LED_BLINK_1HZ); - // axp.setChgLEDMode(AXP20X_LED_OFF); - axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1); + if (pmu.begin(Wire, AXP192_PRIMARY_ADDRESS)) + ESP_LOGI(TAG, "AXP192 PMU initialization failed"); + else { -#ifdef PMU_INT - pinMode(PMU_INT, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(PMU_INT), - [] { - ESP_LOGI(TAG, "Power source changed"); - /* put your code here */ - }, - FALLING); - axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | - AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, - 1); - axp.clearIRQ(); -#endif // PMU_INT + pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); + pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); + pmu.setPowerOutPut(AXP192_DCDC2, AXP202_ON); + pmu.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); + pmu.setDCDC1Voltage(3300); + pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL); + pmu.adc1Enable(AXP202_BATT_CUR_ADC1, 1); - ESP_LOGI(TAG, "AXP192 PMU initialized."); - } + /* + + // I2C access of AXP202X library currently is not mutexable + // so we need to disable AXP interrupts + + #ifdef PMU_INT + pinMode(PMU_INT, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(PMU_INT), + [] { + ESP_LOGI(TAG, "Power source changed"); + // put your code here + }, + FALLING); + pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | + AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, + 1); + pmu.clearIRQ(); + #endif // PMU_INT + */ + + ESP_LOGI(TAG, "AXP192 PMU initialized."); + if (pmu.isBatteryConnect()) + if (pmu.isChargeing()) + ESP_LOGI(TAG, "Running on battery, charging."); + else + ESP_LOGI(TAG, "Running on battery, not charging."); + else if (pmu.isVBUSPlug()) + ESP_LOGI(TAG, "Running on USB power."); + } + I2C_MUTEX_UNLOCK(); // release i2c bus access + } else + ESP_LOGE(TAG, "I2c bus busy - PMU initialization error"); } #endif // HAS_PMU @@ -116,7 +134,7 @@ uint16_t read_voltage() { uint16_t voltage = 0; #ifdef HAS_PMU - voltage = axp.isVBUSPlug() ? 0xffff : axp.getBattVoltage(); + voltage = pmu.isVBUSPlug() ? 0xffff : pmu.getBattVoltage(); #else #ifdef BAT_MEASURE_ADC From 3f97a5cad6567a8749b90bc1765488598df60433 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 9 Sep 2019 20:02:21 +0200 Subject: [PATCH 067/105] TTGO T-Beam V10 power (AXP192 PMU) fixes --- src/payload.cpp | 2 +- src/power.cpp | 43 ++++++++++++++++++++++--------------------- src/rcommand.cpp | 12 ++++-------- src/senddata.cpp | 5 +++-- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/payload.cpp b/src/payload.cpp index 8afd0b3b..5d167fa1 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -371,7 +371,7 @@ void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, float celsius, uint32_t mem, uint8_t reset1, uint8_t reset2) { uint16_t temp = celsius * 10; uint16_t volt = voltage / 10; -#ifdef BAT_MEASURE_ADC +#if (defined BAT_MEASURE_ADC || defined HAS_PMU) #if (PAYLOAD_ENCODER == 3) buffer[cursor++] = LPP_BATT_CHANNEL; #endif diff --git a/src/power.cpp b/src/power.cpp index 5c0d93cb..89aac6ae 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -28,33 +28,34 @@ void AXP192_init(void) { pmu.adc1Enable(AXP202_BATT_CUR_ADC1, 1); /* + // I2C access of AXP202X library currently is not mutexable + // so we need to disable AXP interrupts + - // I2C access of AXP202X library currently is not mutexable - // so we need to disable AXP interrupts - - #ifdef PMU_INT - pinMode(PMU_INT, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(PMU_INT), - [] { - ESP_LOGI(TAG, "Power source changed"); - // put your code here - }, - FALLING); - pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | - AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, - 1); - pmu.clearIRQ(); - #endif // PMU_INT - */ + #ifdef PMU_INT + pinMode(PMU_INT, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(PMU_INT), + [] { + ESP_LOGI(TAG, "Power source changed"); + // put your code here + }, + FALLING); + pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | + AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, + 1); + pmu.clearIRQ(); + #endif // PMU_INT + */ ESP_LOGI(TAG, "AXP192 PMU initialized."); + if (pmu.isBatteryConnect()) if (pmu.isChargeing()) - ESP_LOGI(TAG, "Running on battery, charging."); + ESP_LOGI(TAG, "Battery deteced, charging."); else - ESP_LOGI(TAG, "Running on battery, not charging."); - else if (pmu.isVBUSPlug()) - ESP_LOGI(TAG, "Running on USB power."); + ESP_LOGI(TAG, "Battery deteced, not charging."); + else + ESP_LOGI(TAG, "No Battery deteced."); } I2C_MUTEX_UNLOCK(); // release i2c bus access } else diff --git a/src/rcommand.cpp b/src/rcommand.cpp index a5cca590..a74aa770 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -263,14 +263,10 @@ void get_config(uint8_t val[]) { void get_status(uint8_t val[]) { ESP_LOGI(TAG, "Remote command: get device status"); -#ifdef BAT_MEASURE_ADC - uint16_t voltage = read_voltage(); -#else - uint16_t voltage = 0; -#endif payload.reset(); - payload.addStatus(voltage, uptime() / 1000, temperatureRead(), getFreeRAM(), - rtc_get_reset_reason(0), rtc_get_reset_reason(1)); + payload.addStatus(read_voltage(), uptime() / 1000, temperatureRead(), + getFreeRAM(), rtc_get_reset_reason(0), + rtc_get_reset_reason(1)); SendPayload(STATUSPORT, prio_high); }; @@ -300,7 +296,7 @@ void get_bme(uint8_t val[]) { void get_batt(uint8_t val[]) { ESP_LOGI(TAG, "Remote command: get battery voltage"); -#ifdef BAT_MEASURE_ADC +#if (defined BAT_MEASURE_ADC || defined HAS_PMU) payload.reset(); payload.addVoltage(read_voltage()); SendPayload(BATTPORT, prio_normal); diff --git a/src/senddata.cpp b/src/senddata.cpp index 5e209faf..76d412e2 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -10,7 +10,8 @@ void sendcycle() { // put data to send in RTos Queues used for transmit over channels Lora and SPI void SendPayload(uint8_t port, sendprio_t prio) { - MessageBuffer_t SendBuffer; // contains MessageSize, MessagePort, MessagePrio, Message[] + MessageBuffer_t + SendBuffer; // contains MessageSize, MessagePort, MessagePrio, Message[] SendBuffer.MessageSize = payload.getSize(); SendBuffer.MessagePrio = prio; @@ -117,7 +118,7 @@ void sendData() { break; #endif -#ifdef BAT_MEASURE_ADC +#if (defined BAT_MEASURE_ADC || defined HAS_PMU) case BATT_DATA: payload.reset(); payload.addVoltage(read_voltage()); From edc510adf2f211f088bd0d5eb3d2487a9b517ce2 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 9 Sep 2019 20:33:29 +0200 Subject: [PATCH 068/105] ttgobeam10.h updated --- src/hal/ttgobeam10.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/hal/ttgobeam10.h b/src/hal/ttgobeam10.h index 95820098..4d00034d 100644 --- a/src/hal/ttgobeam10.h +++ b/src/hal/ttgobeam10.h @@ -14,15 +14,16 @@ #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define BOARD_HAS_PSRAM // use extra 4MB external RAM -#define HAS_BUTTON GPIO_NUM_36 // on board button (next to reset) +#define HAS_BUTTON GPIO_NUM_38 // middle on board button #define HAS_PMU 1 // AXP192 power management chip -#define PMU_INT GPIO_NUM_36 // AXP192 interrupt +#define PMU_INT GPIO_NUM_35 // AXP192 interrupt #define HAS_LED NOT_A_PIN // GPS settings #define HAS_GPS 1 // use on board GPS #define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_34, GPIO_NUM_12 // UBlox NEO 6M +#define GPS_INT GPIO_NUM_37 // 30ns accurary timepulse generated by NEO 6M Pin #3 // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus @@ -31,10 +32,10 @@ //#define BME680_ADDR BME680_I2C_ADDR_PRIMARY // !! connect SDIO of BME680 to GND !! // display (if connected) -#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C -#define MY_OLED_SDA SDA -#define MY_OLED_SCL SCL -#define MY_OLED_RST U8X8_PIN_NONE +//#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C +//#define MY_OLED_SDA SDA +//#define MY_OLED_SCL SCL +//#define MY_OLED_RST U8X8_PIN_NONE //#define DISPLAY_FLIP 1 // use if display is rotated // user defined sensors (if connected) From 50c6ba2837af2d296a16adfc73245a060b1bac7e Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 9 Sep 2019 21:45:19 +0200 Subject: [PATCH 069/105] T-Beam V10 (AXP192 PMU) enhanced power functions --- include/irqhandler.h | 6 ++++ include/power.h | 5 +++- src/irqhandler.cpp | 18 ++++++++++++ src/power.cpp | 65 ++++++++++++++++++++++++++++++++------------ 4 files changed, 75 insertions(+), 19 deletions(-) diff --git a/include/irqhandler.h b/include/irqhandler.h index 08d6bd8c..193e32d5 100644 --- a/include/irqhandler.h +++ b/include/irqhandler.h @@ -10,12 +10,14 @@ #define UNMASK_IRQ 0x040 #define BME_IRQ 0x080 #define MATRIX_DISPLAY_IRQ 0x100 +#define PMU_IRQ 0x200 #include "globals.h" #include "cyclic.h" #include "senddata.h" #include "timekeeper.h" #include "bmesensor.h" +#include "power.h" void irqHandler(void *pvParameters); void mask_user_IRQ(); @@ -33,5 +35,9 @@ void IRAM_ATTR MatrixDisplayIRQ(); void IRAM_ATTR ButtonIRQ(); #endif +#ifdef HAS_PMU +void IRAM_ATTR PMUIRQ(); +#endif + #endif \ No newline at end of file diff --git a/include/power.h b/include/power.h index 849ea3b1..ab738253 100644 --- a/include/power.h +++ b/include/power.h @@ -11,11 +11,14 @@ #ifdef HAS_PMU #include +extern AXP20X_Class pmu; // Make axp instance globally availabe +void pover_event_IRQ(void); #endif void AXP192_init(void); uint16_t read_voltage(void); void calibrate_voltage(void); -uint8_t getBattLevel (void); +uint8_t getBattLevel(void); + #endif \ No newline at end of file diff --git a/src/irqhandler.cpp b/src/irqhandler.cpp index db4201a1..74bcd29f 100644 --- a/src/irqhandler.cpp +++ b/src/irqhandler.cpp @@ -63,6 +63,12 @@ void irqHandler(void *pvParameters) { } #endif +// do we have a power event? +#if (HAS_PMU) + if (InterruptStatus & PMU_IRQ) + pover_event_IRQ(); +#endif + // is time to send the payload? if (InterruptStatus & SENDCYCLE_IRQ) sendData(); @@ -106,6 +112,18 @@ void IRAM_ATTR ButtonIRQ() { } #endif +#ifdef HAS_PMU +void IRAM_ATTR PMUIRQ() { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + xTaskNotifyFromISR(irqHandlerTask, PMU_IRQ, eSetBits, + &xHigherPriorityTaskWoken); + + if (xHigherPriorityTaskWoken) + portYIELD_FROM_ISR(); +} +#endif + void mask_user_IRQ() { xTaskNotify(irqHandlerTask, MASK_IRQ, eSetBits); } void unmask_user_IRQ() { xTaskNotify(irqHandlerTask, UNMASK_IRQ, eSetBits); } \ No newline at end of file diff --git a/src/power.cpp b/src/power.cpp index 89aac6ae..ae1ce802 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -9,6 +9,43 @@ static const char TAG[] = __FILE__; AXP20X_Class pmu; +void pover_event_IRQ(void) { + // block i2c bus access + if (I2C_MUTEX_LOCK()) { + pmu.readIRQ(); + // put your power event handler code here + + if (pmu.isVbusOverVoltageIRQ()) + ESP_LOGI(TAG, "USB voltage too high."); + if (pmu.isVbusPlugInIRQ()) + ESP_LOGI(TAG, "USB plugged."); + if (pmu.isVbusRemoveIRQ()) + ESP_LOGI(TAG, "USB unplugged."); + + if (pmu.isBattPlugInIRQ()) + ESP_LOGI(TAG, "Battery is connected."); + if (pmu.isBattRemoveIRQ()) + ESP_LOGI(TAG, "Battery was removed."); + if (pmu.isChargingIRQ()) + ESP_LOGI(TAG, "Battery is charging."); + if (pmu.isChargingDoneIRQ()) + ESP_LOGI(TAG, "Battery charging done."); + if (pmu.isBattTempLowIRQ()) + ESP_LOGI(TAG, "Battery high temperature."); + if (pmu.isBattTempHighIRQ()) + ESP_LOGI(TAG, "Battery low temperature."); + + if (pmu.isPEKShortPressIRQ()) + ESP_LOGI(TAG, "Power Button short pressed."); + if (pmu.isPEKLongtPressIRQ()) + ESP_LOGI(TAG, "Power Button long pressed."); + + pmu.clearIRQ(); + I2C_MUTEX_UNLOCK(); // release i2c bus access + } else + ESP_LOGI(TAG, "Unknown PMU event."); +} + void AXP192_init(void) { // block i2c bus access @@ -27,25 +64,17 @@ void AXP192_init(void) { pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL); pmu.adc1Enable(AXP202_BATT_CUR_ADC1, 1); - /* - // I2C access of AXP202X library currently is not mutexable - // so we need to disable AXP interrupts - + // I2C access of AXP202X library currently is not mutexable + // so we need to disable AXP interrupts - #ifdef PMU_INT - pinMode(PMU_INT, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(PMU_INT), - [] { - ESP_LOGI(TAG, "Power source changed"); - // put your code here - }, - FALLING); - pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | - AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, - 1); - pmu.clearIRQ(); - #endif // PMU_INT - */ +#ifdef PMU_INT + pinMode(PMU_INT, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(PMU_INT), PMUIRQ, FALLING); + pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | + AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, + 1); + pmu.clearIRQ(); +#endif // PMU_INT ESP_LOGI(TAG, "AXP192 PMU initialized."); From ff6fce0a1d68b778fd425f652b04375af55f6cc5 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 9 Sep 2019 23:00:06 +0200 Subject: [PATCH 070/105] T-BEAM v1.0 ON/OFF button function added --- include/power.h | 3 +-- src/power.cpp | 40 ++++++++++++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/include/power.h b/include/power.h index ab738253..c856abcd 100644 --- a/include/power.h +++ b/include/power.h @@ -11,8 +11,8 @@ #ifdef HAS_PMU #include -extern AXP20X_Class pmu; // Make axp instance globally availabe void pover_event_IRQ(void); +void AXP192_power(bool on); #endif void AXP192_init(void); @@ -20,5 +20,4 @@ uint16_t read_voltage(void); void calibrate_voltage(void); uint8_t getBattLevel(void); - #endif \ No newline at end of file diff --git a/src/power.cpp b/src/power.cpp index ae1ce802..b85f58c7 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -35,10 +35,19 @@ void pover_event_IRQ(void) { if (pmu.isBattTempHighIRQ()) ESP_LOGI(TAG, "Battery low temperature."); - if (pmu.isPEKShortPressIRQ()) + // wake up + if (pmu.isPEKShortPressIRQ()) { ESP_LOGI(TAG, "Power Button short pressed."); - if (pmu.isPEKLongtPressIRQ()) + AXP192_power(true); + } + // enter sleep mode + if (pmu.isPEKLongtPressIRQ()) { ESP_LOGI(TAG, "Power Button long pressed."); + AXP192_power(false); + delay(20); + esp_sleep_enable_ext1_wakeup(GPIO_SEL_38, ESP_EXT1_WAKEUP_ALL_LOW); + esp_deep_sleep_start(); + } pmu.clearIRQ(); I2C_MUTEX_UNLOCK(); // release i2c bus access @@ -46,6 +55,25 @@ void pover_event_IRQ(void) { ESP_LOGI(TAG, "Unknown PMU event."); } +void AXP192_power(bool on) { + + if (on) { + pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); + pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); + pmu.setPowerOutPut(AXP192_DCDC2, AXP202_ON); + pmu.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); + pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL); + } else { + pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); + pmu.setPowerOutPut(AXP192_EXTEN, AXP202_OFF); + pmu.setPowerOutPut(AXP192_DCDC2, AXP202_OFF); + pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF); + pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF); + pmu.setChgLEDMode(AXP20X_LED_OFF); + } +} + void AXP192_init(void) { // block i2c bus access @@ -55,14 +83,10 @@ void AXP192_init(void) { ESP_LOGI(TAG, "AXP192 PMU initialization failed"); else { - pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); - pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); - pmu.setPowerOutPut(AXP192_DCDC2, AXP202_ON); - pmu.setPowerOutPut(AXP192_EXTEN, AXP202_ON); - pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); + // switch power on pmu.setDCDC1Voltage(3300); - pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL); pmu.adc1Enable(AXP202_BATT_CUR_ADC1, 1); + AXP192_power(true); // I2C access of AXP202X library currently is not mutexable // so we need to disable AXP interrupts From 677ce0046ee30cac78d99ff65968386199ada3ed Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Thu, 12 Sep 2019 11:08:42 +0200 Subject: [PATCH 071/105] v1.8.031: pin down lmic version due to join issue --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index ebc5a958..8278a620 100644 --- a/platformio.ini +++ b/platformio.ini @@ -43,7 +43,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.8.02 +release_version = 1.8.031 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 @@ -56,7 +56,7 @@ monitor_speed = 115200 upload_speed = 115200 lib_deps_lora = ;MCCI LoRaWAN LMIC library@2.3.2 - https://github.com/mcci-catena/arduino-lmic.git + https://github.com/mcci-catena/arduino-lmic.git#76f7bd5 lib_deps_display = U8g2@>=2.26.13 lib_deps_matrix_display = From 32628431415fbf8e427bcadd86cbb4ff4743a0a1 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 16 Sep 2019 18:16:53 +0200 Subject: [PATCH 072/105] main.cpp add comment for PMU IRQ --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index 2937f793..8c5a9b93 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -58,6 +58,7 @@ fired by hardware DisplayIRQ -> esp32 timer 0 -> irqHandlerTask (Core 1) CLOCKIRQ -> esp32 timer 1 -> ClockTask (Core 1) ButtonIRQ -> external gpio -> irqHandlerTask (Core 1) +PMUIRQ -> PMU chip gpio -> irqHandlerTask (Core 1) fired by software (Ticker.h) TIMESYNC_IRQ -> timeSync() -> irqHandlerTask (Core 1) From 3250a27e83bd97a65e5693d5237faf7b52e64c42 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Tue, 17 Sep 2019 14:32:22 +0200 Subject: [PATCH 073/105] LMIC task priority raised 2 -> 5 --- src/lorawan.cpp | 2 +- src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 1e8c641f..5d8359d5 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -437,7 +437,7 @@ esp_err_t lora_stack_init() { "lmictask", // name of task 4096, // stack size of task (void *)1, // parameter of the task - 2, // priority of the task + 5, // priority of the task &lmicTask, // task handle 1); // CPU core diff --git a/src/main.cpp b/src/main.cpp index 8c5a9b93..c6eb2867 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,9 +31,9 @@ ledloop 0 3 blinks LEDs spiloop 0 2 reads/writes data on spi interface IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer +lmictask 1 5 MCCI LMiC LORAWAN stack clockloop 1 4 generates realtime telegrams for external clock timesync_req 1 3 processes realtime time sync requests -lmictask 1 2 MCCI LMiC LORAWAN stack irqhandler 1 1 display, timesync, gps, etc. triggered by timers gpsloop 1 1 reads data from GPS via serial or i2c lorasendtask 1 1 feed data from lora sendqueue to lmcic From b3d5a0bbf171e552c825519ec927e3fddf2358c7 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Tue, 17 Sep 2019 14:34:48 +0200 Subject: [PATCH 074/105] esp_wifi_start() added (need for ESP v3.2.3) --- src/wifiscan.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 3695508f..b22fe5f2 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -72,6 +72,7 @@ void wifi_sniffer_init(void) { esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL)); ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); // no modem power saving + ESP_ERROR_CHECK(esp_wifi_start()); // must be started to be able to switch ch ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter)); // set frame filter ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler)); ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode From 25e64e0ffdac4d52443141d96a35dfdfafa8c33a Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Tue, 17 Sep 2019 15:05:35 +0200 Subject: [PATCH 075/105] v1.8.1 dev --- platformio.ini | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platformio.ini b/platformio.ini index 8278a620..9bd1d6da 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,16 +34,16 @@ halfile = generic.h [platformio] ; upload firmware to board with usb cable -default_envs = usb +;default_envs = usb ; upload firmware to a jfrog bintray repository ;default_envs = ota ; use latest versions of libraries -;default_envs = dev +default_envs = dev description = Paxcounter is a device for metering passenger flows in realtime. It counts how many mobile devices are around. [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.8.031 +release_version = 1.8.1 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 @@ -56,7 +56,7 @@ monitor_speed = 115200 upload_speed = 115200 lib_deps_lora = ;MCCI LoRaWAN LMIC library@2.3.2 - https://github.com/mcci-catena/arduino-lmic.git#76f7bd5 + https://github.com/mcci-catena/arduino-lmic.git lib_deps_display = U8g2@>=2.26.13 lib_deps_matrix_display = @@ -116,7 +116,7 @@ upload_protocol = custom upload_protocol = esptool [env:dev] -upload_protocol = custom +upload_protocol = esptool build_type = debug platform = https://github.com/platformio/platform-espressif32.git#develop platform_packages = From cf6bb5c992ae0c7245576b7bb5f35459eef36093 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 18 Sep 2019 16:24:25 +0200 Subject: [PATCH 076/105] Heltecv2 battery monitoring disabled --- src/hal/heltecv2.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/hal/heltecv2.h b/src/hal/heltecv2.h index cc7de4d1..adb74981 100644 --- a/src/hal/heltecv2.h +++ b/src/hal/heltecv2.h @@ -20,9 +20,13 @@ #define HAS_LED LED_BUILTIN // white LED on board #define HAS_BUTTON KEY_BUILTIN // button "PROG" on board -#define BAT_MEASURE_ADC ADC2_GPIO13_CHANNEL // battery probe GPIO pin -#define BAT_MEASURE_ADC_UNIT 2 // ADC 2 -#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 220k/100k on board +// caveat: activating ADC2 conflicts with Wifi in current arduino-esp32 +// see https://github.com/espressif/arduino-esp32/issues/3222 +// thus we must waiver of battery monitoring +//#define BAT_MEASURE_ADC ADC2_GPIO13_CHANNEL // battery probe GPIO pin +//#define BAT_MEASURE_ADC_UNIT 2 // ADC 2 +//#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 220k/100k on board + #define EXT_POWER_SW Vext // switches battery power, Vext control 0 = on / 1 = off #define EXT_POWER_ON 0 //#define EXT_POWER_OFF 1 From 1af4eb11a432517930581c293a4ae82dd5af104b Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 18 Sep 2019 16:27:09 +0200 Subject: [PATCH 077/105] fix partition selection bug (#438) --- build.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/build.py b/build.py index 28319853..c4f3ccc3 100644 --- a/build.py +++ b/build.py @@ -7,15 +7,15 @@ import os.path import requests from os.path import basename from platformio import util +from SCons.Script import DefaultEnvironment try: import configparser except ImportError: import ConfigParser as configparser -Import("env") - # get platformio environment variables +env = DefaultEnvironment() config = configparser.ConfigParser() config.read("platformio.ini") @@ -66,7 +66,15 @@ myboard = mykeys["board"] myuploadspeed = mykeys["upload_speed"] env.Replace(BOARD=myboard) env.Replace(UPLOAD_SPEED=myuploadspeed) + +# re-set partition table +mypartitiontable = config.get("env", "board_build.partitions") +board = env.BoardConfig(myboard) +board.manifest['build']['partitions'] = mypartitiontable + +# display target print('\033[94m' + "TARGET BOARD: " + myboard + " @ " + myuploadspeed + "bps" + '\033[0m') +print('\033[94m' + "Partition table: " + mypartitiontable + '\033[0m') # parse ota key file with open(otakeyfile) as myfile: From ad77aa351ffb93054d6c0514f82fde7787ceb800 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 18 Sep 2019 16:30:09 +0200 Subject: [PATCH 078/105] v1.8.11 --- platformio.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index 9bd1d6da..18caaddc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,16 +34,16 @@ halfile = generic.h [platformio] ; upload firmware to board with usb cable -;default_envs = usb +default_envs = usb ; upload firmware to a jfrog bintray repository ;default_envs = ota ; use latest versions of libraries -default_envs = dev +;default_envs = dev description = Paxcounter is a device for metering passenger flows in realtime. It counts how many mobile devices are around. [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.8.1 +release_version = 1.8.11 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 From ec3873f921c160b16d081dfd60fb47c587443ef3 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 18 Sep 2019 18:56:41 +0200 Subject: [PATCH 079/105] v1.8.2 --- platformio.ini | 4 ++-- src/hal/ttgobeam.h | 7 +++---- src/hal/ttgobeam10.h | 1 - 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/platformio.ini b/platformio.ini index 18caaddc..1c7bb04e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -43,7 +43,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.8.11 +release_version = 1.8.2 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 @@ -51,7 +51,7 @@ extra_scripts = pre:build.py otakeyfile = ota.conf lorakeyfile = loraconf.h lmicconfigfile = lmic_config.h -platform_espressif32 = espressif32@1.9.0 +platform_espressif32 = espressif32@1.10.0 monitor_speed = 115200 upload_speed = 115200 lib_deps_lora = diff --git a/src/hal/ttgobeam.h b/src/hal/ttgobeam.h index 41fd0ef0..f8be7ee0 100644 --- a/src/hal/ttgobeam.h +++ b/src/hal/ttgobeam.h @@ -17,7 +17,6 @@ #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1276_radio 1 // HPD13A LoRa SoC -#define BOARD_HAS_PSRAM // use extra 4MB external RAM #define HAS_BUTTON GPIO_NUM_39 // on board button (next to reset) #define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 #define BAT_VOLTAGE_DIVIDER 2 // voltage divider 100k/100k on board @@ -29,9 +28,9 @@ // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus -//#define HAS_BME 1 // Enable BME sensors in general -//#define HAS_BME680 SDA, SCL -//#define BME680_ADDR BME680_I2C_ADDR_PRIMARY // !! connect SDIO of BME680 to GND !! +#define HAS_BME 1 // Enable BME sensors in general +#define HAS_BME680 SDA, SCL +#define BME680_ADDR BME680_I2C_ADDR_PRIMARY // !! connect SDIO of BME680 to GND !! // display (if connected) #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C diff --git a/src/hal/ttgobeam10.h b/src/hal/ttgobeam10.h index 4d00034d..dffe7c61 100644 --- a/src/hal/ttgobeam10.h +++ b/src/hal/ttgobeam10.h @@ -13,7 +13,6 @@ #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1276_radio 1 // HPD13A LoRa SoC -#define BOARD_HAS_PSRAM // use extra 4MB external RAM #define HAS_BUTTON GPIO_NUM_38 // middle on board button #define HAS_PMU 1 // AXP192 power management chip #define PMU_INT GPIO_NUM_35 // AXP192 interrupt From c8531ca466115f599544fc090c288d0746f11697 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 18 Sep 2019 22:38:39 +0200 Subject: [PATCH 080/105] TTGO Beam v10 (AXP192) battery monitor enhanced --- include/power.h | 1 + src/cyclic.cpp | 13 ++++++++++--- src/power.cpp | 30 +++++++++++++++++------------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/include/power.h b/include/power.h index c856abcd..3622f643 100644 --- a/include/power.h +++ b/include/power.h @@ -16,6 +16,7 @@ void AXP192_power(bool on); #endif void AXP192_init(void); +void AXP192_displaypower(void); uint16_t read_voltage(void); void calibrate_voltage(void); uint8_t getBattLevel(void); diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 0b51d88b..1cdd9b14 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -31,11 +31,12 @@ void doHousekeeping() { ESP_LOGD(TAG, "LMiCtask %d bytes left | Taskstate = %d", uxTaskGetStackHighWaterMark(lmicTask), eTaskGetState(lmicTask)); ESP_LOGD(TAG, "Lorasendtask %d bytes left | Taskstate = %d", - uxTaskGetStackHighWaterMark(lorasendTask), eTaskGetState(lorasendTask)); + uxTaskGetStackHighWaterMark(lorasendTask), + eTaskGetState(lorasendTask)); #endif #if (HAS_GPS) - ESP_LOGD(TAG, "Gpsloop %d bytes left | Taskstate = %d", - uxTaskGetStackHighWaterMark(GpsTask), eTaskGetState(GpsTask)); + ESP_LOGD(TAG, "Gpsloop %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(GpsTask), eTaskGetState(GpsTask)); #endif #ifdef HAS_SPI ESP_LOGD(TAG, "spiloop %d bytes left | Taskstate = %d", @@ -57,6 +58,12 @@ void doHousekeeping() { #if (defined BAT_MEASURE_ADC || defined HAS_PMU) batt_voltage = read_voltage(); ESP_LOGI(TAG, "Voltage: %dmV", batt_voltage); +#ifdef HAS_PMU + if (I2C_MUTEX_LOCK()) { + AXP192_displaypower(); + I2C_MUTEX_UNLOCK(); + } +#endif // HAS_PMU #endif // display BME680/280 sensor data diff --git a/src/power.cpp b/src/power.cpp index b85f58c7..5dccf6d0 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -16,9 +16,10 @@ void pover_event_IRQ(void) { // put your power event handler code here if (pmu.isVbusOverVoltageIRQ()) - ESP_LOGI(TAG, "USB voltage too high."); + ESP_LOGI(TAG, "USB voltage %.1fV too high.", pmu.getVbusVoltage()); if (pmu.isVbusPlugInIRQ()) - ESP_LOGI(TAG, "USB plugged."); + ESP_LOGI(TAG, "USB plugged, %.0fmAh @ %.1fV", pmu.getVbusCurrent(), + pmu.getVbusVoltage()); if (pmu.isVbusRemoveIRQ()) ESP_LOGI(TAG, "USB unplugged."); @@ -27,7 +28,7 @@ void pover_event_IRQ(void) { if (pmu.isBattRemoveIRQ()) ESP_LOGI(TAG, "Battery was removed."); if (pmu.isChargingIRQ()) - ESP_LOGI(TAG, "Battery is charging."); + ESP_LOGI(TAG, "Battery charging."); if (pmu.isChargingDoneIRQ()) ESP_LOGI(TAG, "Battery charging done."); if (pmu.isBattTempLowIRQ()) @@ -74,6 +75,17 @@ void AXP192_power(bool on) { } } +void AXP192_displaypower(void) { + if (pmu.isBatteryConnect()) + if (pmu.isChargeing()) + ESP_LOGI(TAG, "Battery charging @ %.0fmAh", pmu.getBattChargeCurrent()); + else + ESP_LOGI(TAG, "Battery discharging @ %0.fmAh", + pmu.getBattDischargeCurrent()); + else + ESP_LOGI(TAG, "No Battery"); +} + void AXP192_init(void) { // block i2c bus access @@ -89,8 +101,7 @@ void AXP192_init(void) { AXP192_power(true); // I2C access of AXP202X library currently is not mutexable - // so we need to disable AXP interrupts - + // so we better should disable AXP interrupts... ? #ifdef PMU_INT pinMode(PMU_INT, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(PMU_INT), PMUIRQ, FALLING); @@ -101,14 +112,7 @@ void AXP192_init(void) { #endif // PMU_INT ESP_LOGI(TAG, "AXP192 PMU initialized."); - - if (pmu.isBatteryConnect()) - if (pmu.isChargeing()) - ESP_LOGI(TAG, "Battery deteced, charging."); - else - ESP_LOGI(TAG, "Battery deteced, not charging."); - else - ESP_LOGI(TAG, "No Battery deteced."); + AXP192_displaypower(); } I2C_MUTEX_UNLOCK(); // release i2c bus access } else From 79e54774f18a7e33df611bd7e56c7d25f1c8e334 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Thu, 19 Sep 2019 16:13:48 +0200 Subject: [PATCH 081/105] lorawan.cpp: disable setLinkCheckMode & setDrTxpow --- src/lorawan.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 5d8359d5..91424594 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -540,7 +540,8 @@ void lmictask(void *pvParameters) { os_init(); // initialize lmic run-time environment LMIC_reset(); // initialize lmic MAC - LMIC_setLinkCheckMode(0); + // LMIC_setLinkCheckMode(0); + // This tells LMIC to make the receive windows bigger, in case your clock is // faster or slower. This causes the transceiver to be earlier switched on, // so consuming more power. You may sharpen (reduce) CLOCK_ERROR_PERCENTAGE @@ -548,13 +549,6 @@ void lmictask(void *pvParameters) { #ifdef CLOCK_ERROR_PROCENTAGE LMIC_setClockError(MAX_CLOCK_ERROR * CLOCK_ERROR_PROCENTAGE / 100); #endif - // Set the data rate to Spreading Factor 7. This is the fastest supported - // rate for 125 kHz channels, and it minimizes air time and battery power. - // Set the transmission power to 14 dBi (25 mW). - LMIC_setDrTxpow(DR_SF7, 14); - // register a callback for downlink messages. We aren't trying to write - // reentrant code, so pUserData is NULL. - LMIC_registerRxMessageCb(myRxCallback, NULL); #if defined(CFG_US915) || defined(CFG_au921) // in the US, with TTN, it saves join time if we start on subband 1 @@ -564,6 +558,15 @@ void lmictask(void *pvParameters) { LMIC_selectSubBand(1); #endif + // Set the data rate to Spreading Factor 7. This is the fastest supported + // rate for 125 kHz channels, and it minimizes air time and battery power. + // Set the transmission power to 14 dBi (25 mW). + // LMIC_setDrTxpow(DR_SF7, 14); + + // register a callback for downlink messages. We aren't trying to write + // reentrant code, so pUserData is NULL. + LMIC_registerRxMessageCb(myRxCallback, NULL); + while (1) { os_runloop_once(); // execute lmic scheduled jobs and events delay(2); // yield to CPU From 50ff7977d6601f83b2a9525c3f00538181ff3d6f Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Thu, 19 Sep 2019 17:06:09 +0200 Subject: [PATCH 082/105] AXP192 Battery monitoring display enhanced --- src/cyclic.cpp | 7 +++++-- src/power.cpp | 14 ++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 1cdd9b14..d728d1bc 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -57,13 +57,16 @@ void doHousekeeping() { // read battery voltage into global variable #if (defined BAT_MEASURE_ADC || defined HAS_PMU) batt_voltage = read_voltage(); - ESP_LOGI(TAG, "Voltage: %dmV", batt_voltage); + if (batt_voltage = 0xffff) + ESP_LOGI(TAG, "Battery: external power"); + else + ESP_LOGI(TAG, "Battery: %dmV", batt_voltage); #ifdef HAS_PMU if (I2C_MUTEX_LOCK()) { AXP192_displaypower(); I2C_MUTEX_UNLOCK(); } -#endif // HAS_PMU +#endif #endif // display BME680/280 sensor data diff --git a/src/power.cpp b/src/power.cpp index 5dccf6d0..2cb0e1ff 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -78,12 +78,18 @@ void AXP192_power(bool on) { void AXP192_displaypower(void) { if (pmu.isBatteryConnect()) if (pmu.isChargeing()) - ESP_LOGI(TAG, "Battery charging @ %.0fmAh", pmu.getBattChargeCurrent()); + ESP_LOGI(TAG, "Battery charging %.0fmAh @ Temp %.1f°C", + pmu.getBattChargeCurrent(), pmu.getTSTemp()); else - ESP_LOGI(TAG, "Battery discharging @ %0.fmAh", - pmu.getBattDischargeCurrent()); + ESP_LOGI(TAG, "Battery not charging, Temp %.1f°C", pmu.getTSTemp()); else ESP_LOGI(TAG, "No Battery"); + + if (pmu.isVBUSPlug()) + ESP_LOGI(TAG, "USB present, %.0fmAh @ %.1fV", pmu.getVbusCurrent(), + pmu.getVbusVoltage()); + else + ESP_LOGI(TAG, "USB not present"); } void AXP192_init(void) { @@ -111,7 +117,7 @@ void AXP192_init(void) { pmu.clearIRQ(); #endif // PMU_INT - ESP_LOGI(TAG, "AXP192 PMU initialized."); + ESP_LOGI(TAG, "AXP192 PMU initialized, chip Temp %.1f°C", pmu.getTemp()); AXP192_displaypower(); } I2C_MUTEX_UNLOCK(); // release i2c bus access From af0fd577d36a87f846ce8f6533c2d5c986d4d620 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Thu, 19 Sep 2019 17:06:37 +0200 Subject: [PATCH 083/105] lorawan.cpp code sanitizations --- src/lorawan.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 91424594..bfcd7c75 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -234,13 +234,10 @@ void onEvent(ev_t ev) { sprintf(display_line6, " "); // clear previous lmic status // set data rate adaptation according to saved setting LMIC_setAdrMode(cfg.adrmode); - // set cyclic lmic link check to off if no ADR because is not supported by - // ttn (but enabled by lmic after join) - LMIC_setLinkCheckMode(cfg.adrmode); - // Set data rate and transmit power (note: txpower seems to be ignored by - // the library) - switch_lora(cfg.lorasf, cfg.txpower); - // show effective LoRa parameters after join + // set data rate and transmit power if we have no ADR + if (!cfg.adrmode) + switch_lora(cfg.lorasf, cfg.txpower); + // show current devaddr ESP_LOGI(TAG, "DEVaddr=%08X", LMIC.devaddr); break; @@ -540,7 +537,7 @@ void lmictask(void *pvParameters) { os_init(); // initialize lmic run-time environment LMIC_reset(); // initialize lmic MAC - // LMIC_setLinkCheckMode(0); + LMIC_setLinkCheckMode(0); // This tells LMIC to make the receive windows bigger, in case your clock is // faster or slower. This causes the transceiver to be earlier switched on, @@ -550,7 +547,8 @@ void lmictask(void *pvParameters) { LMIC_setClockError(MAX_CLOCK_ERROR * CLOCK_ERROR_PROCENTAGE / 100); #endif -#if defined(CFG_US915) || defined(CFG_au921) +//#if defined(CFG_US915) || defined(CFG_au921) +#if CFG_LMIC_US_like // in the US, with TTN, it saves join time if we start on subband 1 // (channels 8-15). This will get overridden after the join by parameters // from the network. If working with other networks or in other regions, @@ -561,7 +559,7 @@ void lmictask(void *pvParameters) { // Set the data rate to Spreading Factor 7. This is the fastest supported // rate for 125 kHz channels, and it minimizes air time and battery power. // Set the transmission power to 14 dBi (25 mW). - // LMIC_setDrTxpow(DR_SF7, 14); + LMIC_setDrTxpow(DR_SF7, 14); // register a callback for downlink messages. We aren't trying to write // reentrant code, so pUserData is NULL. From d9c61535597bcc1583068a232998f3d514d526f4 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 09:04:24 +0200 Subject: [PATCH 084/105] bugfix getBattLevel() (issue #444) --- include/lorawan.h | 1 + include/power.h | 2 +- src/lorawan.cpp | 26 ++++++++++++++++++++++++++ src/ota.cpp | 2 +- src/power.cpp | 30 +++++++----------------------- 5 files changed, 36 insertions(+), 25 deletions(-) diff --git a/include/lorawan.h b/include/lorawan.h index 74a67c04..5c5c67cb 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -49,6 +49,7 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, void myTxCallback(void *pUserData, int fSuccess); void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[], const uint8_t tablesize); +uint8_t getBattLevel(void); #if (TIME_SYNC_LORAWAN) void user_request_network_time_callback(void *pVoidUserUTCTime, diff --git a/include/power.h b/include/power.h index 3622f643..c27daa6c 100644 --- a/include/power.h +++ b/include/power.h @@ -19,6 +19,6 @@ void AXP192_init(void); void AXP192_displaypower(void); uint16_t read_voltage(void); void calibrate_voltage(void); -uint8_t getBattLevel(void); +bool batt_sufficient(void); #endif \ No newline at end of file diff --git a/src/lorawan.cpp b/src/lorawan.cpp index bfcd7c75..bd5284f8 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -666,4 +666,30 @@ void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[], } // mac_decode() +uint8_t getBattLevel() { + /* + return values: + MCMD_DEVS_EXT_POWER = 0x00, // external power supply + MCMD_DEVS_BATT_MIN = 0x01, // min battery value + MCMD_DEVS_BATT_MAX = 0xFE, // max battery value + MCMD_DEVS_BATT_NOINFO = 0xFF, // unknown battery level + */ +#if (defined HAS_PMU || defined BAT_MEASURE_ADC) + uint16_t voltage = read_voltage(); + + switch (voltage) { + case 0: + return MCMD_DEVS_BATT_NOINFO; + case 0xffff: + return MCMD_DEVS_EXT_POWER; + default: + return (voltage > OTA_MIN_BATT ? MCMD_DEVS_BATT_MAX : MCMD_DEVS_BATT_MIN); + } +#else // we don't have any info on battery level + return MCMD_DEVS_BATT_NOINFO; +#endif +} // getBattLevel() + +//u1_t os_getBattLevel(void) { return getBattLevel(); }; + #endif // HAS_LORA \ No newline at end of file diff --git a/src/ota.cpp b/src/ota.cpp index 1a1e9052..18eaa84e 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -41,7 +41,7 @@ inline String getHeaderValue(String header, String headerName) { void start_ota_update() { // check battery status if we can before doing ota - if (getBattLevel() == MCMD_DEVS_BATT_MIN) { + if (!batt_sufficient()) { ESP_LOGE(TAG, "Battery voltage %dmV too low for OTA", batt_voltage); return; } diff --git a/src/power.cpp b/src/power.cpp index 2cb0e1ff..877fc953 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -167,31 +167,15 @@ void calibrate_voltage(void) { #endif } -uint8_t getBattLevel() { - /* - return values: - MCMD_DEVS_EXT_POWER = 0x00, // external power supply - MCMD_DEVS_BATT_MIN = 0x01, // min battery value - MCMD_DEVS_BATT_MAX = 0xFE, // max battery value - MCMD_DEVS_BATT_NOINFO = 0xFF, // unknown battery level - */ +bool batt_sufficient() { #if (defined HAS_PMU || defined BAT_MEASURE_ADC) - uint16_t voltage = read_voltage(); - - switch (voltage) { - case 0: - return MCMD_DEVS_BATT_NOINFO; - case 0xffff: - return MCMD_DEVS_EXT_POWER; - default: - return (voltage > OTA_MIN_BATT ? MCMD_DEVS_BATT_MAX : MCMD_DEVS_BATT_MIN); - } -#else // we don't have any info on battery level - return MCMD_DEVS_BATT_NOINFO; + uint16_t volts = read_voltage(); + return ((volts < 1000) || + (volts > OTA_MIN_BATT)); // no battery or battery sufficient +#else + return true; #endif -} // getBattLevel() - -// u1_t os_getBattLevel(void) { return getBattLevel(); }; +} uint16_t read_voltage() { From 6bf4a287bfbc27a104c6bf0fc6aedf9ecf0fbc1d Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 09:51:13 +0200 Subject: [PATCH 085/105] bugfix battery voltage display --- src/cyclic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cyclic.cpp b/src/cyclic.cpp index d728d1bc..d616d573 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -57,7 +57,7 @@ void doHousekeeping() { // read battery voltage into global variable #if (defined BAT_MEASURE_ADC || defined HAS_PMU) batt_voltage = read_voltage(); - if (batt_voltage = 0xffff) + if (batt_voltage == 0xffff) ESP_LOGI(TAG, "Battery: external power"); else ESP_LOGI(TAG, "Battery: %dmV", batt_voltage); From cc248419aeac1758400478942e25223566bd8f91 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 09:51:33 +0200 Subject: [PATCH 086/105] optimize SF display --- include/lorawan.h | 1 + src/display.cpp | 17 +---------------- src/lorawan.cpp | 8 +++++++- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/include/lorawan.h b/include/lorawan.h index 5c5c67cb..1bf0898e 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -50,6 +50,7 @@ void myTxCallback(void *pUserData, int fSuccess); void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[], const uint8_t tablesize); uint8_t getBattLevel(void); +const char *getSfName(rps_t rps); #if (TIME_SYNC_LORAWAN) void user_request_network_time_callback(void *pVoidUserUTCTime, diff --git a/src/display.cpp b/src/display.cpp index e6d17301..2f6dc132 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -30,19 +30,6 @@ line 7: y = Text for LMIC status; ab = payload queue HAS_DISPLAY u8x8(MY_OLED_RST, MY_OLED_SCL, MY_OLED_SDA); -// helper string for converting LoRa spread factor values -#if defined(CFG_eu868) -const char lora_datarate[] = {"1211100908077BFSNA"}; -#elif defined(CFG_us915) -const char lora_datarate[] = {"100908078CNA121110090807"}; -#elif defined(CFG_as923) -const char lora_datarate[] = {"1211100908077BFSNA"}; -#elif defined(CFG_au921) -const char lora_datarate[] = {"1211100908078CNA1211109C8C7C"}; -#elif defined(CFG_in866) -const char lora_datarate[] = {"121110090807FSNA"}; -#endif - // helper arry for converting month values to text const char *printmonth[] = {"xxx", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; @@ -216,11 +203,9 @@ void draw_page(time_t t, uint8_t page) { #if (HAS_LORA) u8x8.setCursor(11, 3); - u8x8.printf("SF:"); if (cfg.adrmode) // if ADR=on then display SF value inverse u8x8.setInverseFont(1); - u8x8.printf("%c%c", lora_datarate[LMIC.datarate * 2], - lora_datarate[LMIC.datarate * 2 + 1]); + u8x8.printf("%5s", getSfName(LMIC.rps)); if (cfg.adrmode) // switch off inverse if it was turned on u8x8.setInverseFont(0); #endif // HAS_LORA diff --git a/src/lorawan.cpp b/src/lorawan.cpp index bd5284f8..50dab818 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -690,6 +690,12 @@ uint8_t getBattLevel() { #endif } // getBattLevel() -//u1_t os_getBattLevel(void) { return getBattLevel(); }; +// u1_t os_getBattLevel(void) { return getBattLevel(); }; + +const char *getSfName(rps_t rps) { + const char *const t[] = {"FSK", "SF7", "SF8", "SF9", + "SF10", "SF11", "SF12", "SFrfu"}; + return t[getSf(rps)]; +} #endif // HAS_LORA \ No newline at end of file From c3bad526a7feba0b487769606d697e377a9f7de6 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 13:22:45 +0200 Subject: [PATCH 087/105] Changed Lora SF to Lora DR control --- README.md | 20 ++++++++++-- include/globals.h | 2 +- include/lorawan.h | 3 +- platformio.ini | 3 +- src/TTN/packed_decoder.js | 2 +- src/configmanager.cpp | 35 +++++++++++---------- src/display.cpp | 2 +- src/lorawan.cpp | 65 ++++++++++----------------------------- src/paxcounter.conf | 5 ++- src/payload.cpp | 4 +-- src/rcommand.cpp | 32 +++++++++++++++---- 11 files changed, 90 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index c8bebf56..4cb51ca8 100644 --- a/README.md +++ b/README.md @@ -305,13 +305,27 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. 0 = display off 1 = display on [default] -0x05 set LoRa spread factor +0x05 set LoRa datarate - 7 ... 12 [default: 9] + 0 ... 15 see LoRaWAN regional parameters for details [default: 5] + + Example for EU868: + + DataRate Radio Bit/s + 0 LoRa: SF12 / 125 kHz 250 + 1 LoRa: SF11 / 125 kHz 440 + 2 LoRa: SF10 / 125 kHz 980 + 3 LoRa: SF9 / 125 kHz 1760 + 4 LoRa: SF8 / 125 kHz 3125 + 5 LoRa: SF7 / 125 kHz 5470 + 6* LoRa: SF7 / 250 kHz 11000 + 7* FSK: 50 kbps 50000 + + *) not supported by TheThingsNetwork 0x06 set LoRa TXpower - 2 ... 15 [default: 15] + 0 ... 15 [default: 14] 0x07 set LoRa Adaptive Data Rate mode diff --git a/include/globals.h b/include/globals.h index 67ec93d2..773af1ad 100644 --- a/include/globals.h +++ b/include/globals.h @@ -50,7 +50,7 @@ enum timesource_t { _gps, _rtc, _lora, _unsynced }; // Struct holding devices's runtime configuration typedef struct { - uint8_t lorasf; // 7-12, lora spreadfactor + uint8_t loradr; // 0-15, lora datarate uint8_t txpower; // 2-15, lora tx power uint8_t adrmode; // 0=disabled, 1=enabled uint8_t screensaver; // 0=disabled, 1=enabled diff --git a/include/lorawan.h b/include/lorawan.h index 1bf0898e..a69aa4ba 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -40,7 +40,6 @@ void os_getDevKey(u1_t *buf); void os_getArtEui(u1_t *buf); void os_getDevEui(u1_t *buf); void showLoraKeys(void); -void switch_lora(uint8_t sf, uint8_t tx); void lora_send(void *pvParameters); void lora_enqueuedata(MessageBuffer_t *message); void lora_queuereset(void); @@ -51,6 +50,8 @@ void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[], const uint8_t tablesize); uint8_t getBattLevel(void); const char *getSfName(rps_t rps); +const char *getBwName(rps_t rps); +const char *getCrName(rps_t rps); #if (TIME_SYNC_LORAWAN) void user_request_network_time_callback(void *pVoidUserUTCTime, diff --git a/platformio.ini b/platformio.ini index 1c7bb04e..39f7925c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -43,7 +43,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.8.2 +release_version = 1.8.3 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 @@ -74,6 +74,7 @@ lib_deps_basic = 274@>=2.3.3 ;RTC by Michael Miller SimpleButton AXP202X_Library@^1.0.0 + ;https://github.com/cyberman54/AXP202X_Library.git lib_deps_all = ${common.lib_deps_basic} ${common.lib_deps_lora} diff --git a/src/TTN/packed_decoder.js b/src/TTN/packed_decoder.js index 0999c07d..9ee6cf4f 100644 --- a/src/TTN/packed_decoder.js +++ b/src/TTN/packed_decoder.js @@ -37,7 +37,7 @@ function Decoder(bytes, port) { if (port === 3) { // device config data - return decode(bytes, [uint8, uint8, int16, uint8, uint8, uint8, uint8, bitmap1, bitmap2, version], ['lorasf', 'txpower', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags', 'payloadmask', 'version']); + return decode(bytes, [uint8, uint8, int16, uint8, uint8, uint8, uint8, bitmap1, bitmap2, version], ['loradr', 'txpower', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags', 'payloadmask', 'version']); } if (port === 4) { diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 496bcacb..5b235f70 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -9,19 +9,20 @@ nvs_handle my_handle; esp_err_t err; #define PAYLOADMASK \ - ((GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | \ - SENSOR2_DATA | SENSOR3_DATA) & ~BATT_DATA) + ((GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | \ + SENSOR2_DATA | SENSOR3_DATA) & \ + ~BATT_DATA) // populate cfg vars with factory settings void defaultConfig() { - cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora sf, see pacounter.conf - cfg.txpower = 15; // 2-15, lora tx power - cfg.adrmode = 1; // 0=disabled, 1=enabled - cfg.screensaver = 0; // 0=disabled, 1=enabled - cfg.screenon = 1; // 0=disabled, 1=enabled - cfg.countermode = 0; // 0=cyclic, 1=cumulative, 2=cyclic confirmed - cfg.rssilimit = 0; // threshold for rssilimiter, negative value! - cfg.sendcycle = SENDCYCLE; // payload send cycle [seconds/2] + cfg.loradr = LORADRDEFAULT; // 0-15, lora datarate, see pacounter.conf + cfg.txpower = LORATXPOWDEFAULT; // 0-15, lora tx power + cfg.adrmode = 1; // 0=disabled, 1=enabled + cfg.screensaver = 0; // 0=disabled, 1=enabled + cfg.screenon = 1; // 0=disabled, 1=enabled + cfg.countermode = 0; // 0=cyclic, 1=cumulative, 2=cyclic confirmed + cfg.rssilimit = 0; // threshold for rssilimiter, negative value! + cfg.sendcycle = SENDCYCLE; // payload send cycle [seconds/2] cfg.wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100] cfg.blescantime = @@ -96,9 +97,9 @@ void saveConfig() { strcmp(storedversion, cfg.version) != 0) nvs_set_str(my_handle, "version", cfg.version); - if (nvs_get_i8(my_handle, "lorasf", &flash8) != ESP_OK || - flash8 != cfg.lorasf) - nvs_set_i8(my_handle, "lorasf", cfg.lorasf); + if (nvs_get_i8(my_handle, "loradr", &flash8) != ESP_OK || + flash8 != cfg.loradr) + nvs_set_i8(my_handle, "loradr", cfg.loradr); if (nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK || flash8 != cfg.txpower) @@ -221,11 +222,11 @@ void loadConfig() { ESP_LOGI(TAG, "bsecstate = %d", cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE]); }; - if (nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK) { - cfg.lorasf = flash8; - ESP_LOGI(TAG, "lorasf = %d", flash8); + if (nvs_get_i8(my_handle, "loradr", &flash8) == ESP_OK) { + cfg.loradr = flash8; + ESP_LOGI(TAG, "loradr = %d", flash8); } else { - ESP_LOGI(TAG, "lorasf set to default %d", cfg.lorasf); + ESP_LOGI(TAG, "loradr set to default %d", cfg.loradr); saveConfig(); } diff --git a/src/display.cpp b/src/display.cpp index 2f6dc132..a448b9ae 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -205,7 +205,7 @@ void draw_page(time_t t, uint8_t page) { u8x8.setCursor(11, 3); if (cfg.adrmode) // if ADR=on then display SF value inverse u8x8.setInverseFont(1); - u8x8.printf("%5s", getSfName(LMIC.rps)); + u8x8.printf("%5s", getSfName(updr2rps(LMIC.datarate))); if (cfg.adrmode) // switch off inverse if it was turned on u8x8.setInverseFont(0); #endif // HAS_LORA diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 50dab818..4ae42fd9 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -234,11 +234,15 @@ void onEvent(ev_t ev) { sprintf(display_line6, " "); // clear previous lmic status // set data rate adaptation according to saved setting LMIC_setAdrMode(cfg.adrmode); - // set data rate and transmit power if we have no ADR + // set data rate and transmit power to defaults only if we have no ADR if (!cfg.adrmode) - switch_lora(cfg.lorasf, cfg.txpower); + LMIC_setDrTxpow(assertDR(cfg.loradr), cfg.txpower); // show current devaddr ESP_LOGI(TAG, "DEVaddr=%08X", LMIC.devaddr); + ESP_LOGI(TAG, "Radio parameters %s / %s / %s", + getSfName(updr2rps(LMIC.datarate)), + getBwName(updr2rps(LMIC.datarate)), + getCrName(updr2rps(LMIC.datarate))); break; case EV_RFU1: @@ -321,53 +325,6 @@ void onEvent(ev_t ev) { } } -// helper function to assign LoRa datarates to numeric spreadfactor values -void switch_lora(uint8_t sf, uint8_t tx) { - if (tx > 20) - return; - cfg.txpower = tx; - switch (sf) { - case 7: - LMIC_setDrTxpow(DR_SF7, tx); - cfg.lorasf = sf; - break; - case 8: - LMIC_setDrTxpow(DR_SF8, tx); - cfg.lorasf = sf; - break; - case 9: - LMIC_setDrTxpow(DR_SF9, tx); - cfg.lorasf = sf; - break; - case 10: - LMIC_setDrTxpow(DR_SF10, tx); - cfg.lorasf = sf; - break; - case 11: -#if defined(CFG_us915) - LMIC_setDrTxpow(DR_SF11CR, tx); - cfg.lorasf = sf; - break; -#else - LMIC_setDrTxpow(DR_SF11, tx); - cfg.lorasf = sf; - break; -#endif - case 12: -#if defined(CFG_us915) - LMIC_setDrTxpow(DR_SF12CR, tx); - cfg.lorasf = sf; - break; -#else - LMIC_setDrTxpow(DR_SF12, tx); - cfg.lorasf = sf; - break; -#endif - default: - break; - } -} - // LMIC send task void lora_send(void *pvParameters) { configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check @@ -698,4 +655,14 @@ const char *getSfName(rps_t rps) { return t[getSf(rps)]; } +const char *getBwName(rps_t rps) { + const char *const t[] = {"BW125", "BW250", "BW500", "BWrfu"}; + return t[getBw(rps)]; +} + +const char *getCrName(rps_t rps) { + const char *const t[] = {"CR 4/5", "CR 4/6", "CR 4/7", "CR 4/8"}; + return t[getCr(rps)]; +} + #endif // HAS_LORA \ No newline at end of file diff --git a/src/paxcounter.conf b/src/paxcounter.conf index d78d0035..e18c8b60 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -1,3 +1,5 @@ +// clang-format off + // ----- Paxcounter user config file ------ // // --> adapt to your needs and use case <-- @@ -46,7 +48,8 @@ #define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit -#define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs +#define LORADRDEFAULT 5 // 0 .. 15, LoRaWAN datarate, according to regional LoRaWAN specs [default = 5] +#define LORATXPOWDEFAULT 14 // 0 .. 15, LoRaWAN TX power #define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy #define SEND_QUEUE_SIZE 10 // maximum number of messages in payload send queue [1 = no queue] diff --git a/src/payload.cpp b/src/payload.cpp index 5d167fa1..fad4a1bc 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -36,7 +36,7 @@ void PayloadConvert::addVoltage(uint16_t value) { } void PayloadConvert::addConfig(configData_t value) { - buffer[cursor++] = value.lorasf; + buffer[cursor++] = value.loradr; buffer[cursor++] = value.txpower; buffer[cursor++] = value.adrmode; buffer[cursor++] = value.screensaver; @@ -157,7 +157,7 @@ void PayloadConvert::addAlarm(int8_t rssi, uint8_t msg) { void PayloadConvert::addVoltage(uint16_t value) { writeUint16(value); } void PayloadConvert::addConfig(configData_t value) { - writeUint8(value.lorasf); + writeUint8(value.loradr); writeUint8(value.txpower); writeUint16(value.rssilimit); writeUint8(value.sendcycle); diff --git a/src/rcommand.cpp b/src/rcommand.cpp index a74aa770..b3053790 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -193,10 +193,22 @@ void set_monitor(uint8_t val[]) { cfg.monitormode = val[0] ? 1 : 0; } -void set_lorasf(uint8_t val[]) { +void set_loradr(uint8_t val[]) { #if (HAS_LORA) - ESP_LOGI(TAG, "Remote command: set LoRa SF to %d", val[0]); - switch_lora(val[0], cfg.txpower); + if (validDR(val[0])) { + cfg.loradr = val[0]; + ESP_LOGI(TAG, "Remote command: set LoRa Datarate to %d", cfg.loradr); + LMIC_setDrTxpow(assertDR(cfg.loradr), cfg.txpower); + ESP_LOGI(TAG, "Radio parameters now %s / %s / %s", + getSfName(updr2rps(LMIC.datarate)), + getBwName(updr2rps(LMIC.datarate)), + getCrName(updr2rps(LMIC.datarate))); + + } else + ESP_LOGI( + TAG, + "Remote command: set LoRa Datarate called with illegal datarate %d", + val[0]); #else ESP_LOGW(TAG, "Remote command: LoRa not implemented"); #endif // HAS_LORA @@ -247,8 +259,16 @@ void set_rgblum(uint8_t val[]) { void set_lorapower(uint8_t val[]) { #if (HAS_LORA) - ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %d", val[0]); - switch_lora(cfg.lorasf, val[0]); + // set data rate and transmit power only if we have no ADR + if (!cfg.adrmode) { + cfg.txpower = val[0] & 0x0f; + ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %d", cfg.txpower); + LMIC_setDrTxpow(assertDR(cfg.loradr), cfg.txpower); + } else + ESP_LOGI( + TAG, + "Remote command: set LoRa TXPOWER, not executed because ADR is on"); + #else ESP_LOGW(TAG, "Remote command: LoRa not implemented"); #endif // HAS_LORA @@ -331,7 +351,7 @@ void set_flush(uint8_t val[]) { static cmd_t table[] = { {0x01, set_rssi, 1, true}, {0x02, set_countmode, 1, true}, {0x03, set_gps, 1, true}, {0x04, set_display, 1, true}, - {0x05, set_lorasf, 1, true}, {0x06, set_lorapower, 1, true}, + {0x05, set_loradr, 1, true}, {0x06, set_lorapower, 1, true}, {0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true}, {0x09, set_reset, 1, true}, {0x0a, set_sendcycle, 1, true}, {0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true}, From 1daaac6fc64f4e39a747762ee4b1347c555b83b8 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 18:11:05 +0200 Subject: [PATCH 088/105] PMU small corrections --- src/power.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/power.cpp b/src/power.cpp index 877fc953..b4198c1d 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -18,8 +18,7 @@ void pover_event_IRQ(void) { if (pmu.isVbusOverVoltageIRQ()) ESP_LOGI(TAG, "USB voltage %.1fV too high.", pmu.getVbusVoltage()); if (pmu.isVbusPlugInIRQ()) - ESP_LOGI(TAG, "USB plugged, %.0fmAh @ %.1fV", pmu.getVbusCurrent(), - pmu.getVbusVoltage()); + ESP_LOGI(TAG, "USB plugged."); if (pmu.isVbusRemoveIRQ()) ESP_LOGI(TAG, "USB unplugged."); @@ -59,16 +58,16 @@ void pover_event_IRQ(void) { void AXP192_power(bool on) { if (on) { - pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); - pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); - pmu.setPowerOutPut(AXP192_DCDC2, AXP202_ON); - pmu.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); // Lora on T-Beam V1.0 + pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); // Gps on T-Beam V1.0 pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); - pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL); + pmu.setPowerOutPut(AXP192_DCDC3, AXP202_ON); + pmu.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ); } else { - pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); pmu.setPowerOutPut(AXP192_EXTEN, AXP202_OFF); - pmu.setPowerOutPut(AXP192_DCDC2, AXP202_OFF); + pmu.setPowerOutPut(AXP192_DCDC3, AXP202_OFF); + pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF); pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF); pmu.setChgLEDMode(AXP20X_LED_OFF); @@ -78,16 +77,14 @@ void AXP192_power(bool on) { void AXP192_displaypower(void) { if (pmu.isBatteryConnect()) if (pmu.isChargeing()) - ESP_LOGI(TAG, "Battery charging %.0fmAh @ Temp %.1f°C", - pmu.getBattChargeCurrent(), pmu.getTSTemp()); + ESP_LOGI(TAG, "Battery charging @ %.0fmAh", pmu.getBattChargeCurrent()); else - ESP_LOGI(TAG, "Battery not charging, Temp %.1f°C", pmu.getTSTemp()); + ESP_LOGI(TAG, "Battery not charging"); else ESP_LOGI(TAG, "No Battery"); if (pmu.isVBUSPlug()) - ESP_LOGI(TAG, "USB present, %.0fmAh @ %.1fV", pmu.getVbusCurrent(), - pmu.getVbusVoltage()); + ESP_LOGI(TAG, "USB present"); else ESP_LOGI(TAG, "USB not present"); } @@ -102,10 +99,13 @@ void AXP192_init(void) { else { // switch power on - pmu.setDCDC1Voltage(3300); + pmu.setDCDC1Voltage(3300); // for external OLED display pmu.adc1Enable(AXP202_BATT_CUR_ADC1, 1); AXP192_power(true); + // set TS pin mode off to save power + pmu.setTSmode(AXP_TS_PIN_MODE_DISABLE); + // I2C access of AXP202X library currently is not mutexable // so we better should disable AXP interrupts... ? #ifdef PMU_INT @@ -117,7 +117,7 @@ void AXP192_init(void) { pmu.clearIRQ(); #endif // PMU_INT - ESP_LOGI(TAG, "AXP192 PMU initialized, chip Temp %.1f°C", pmu.getTemp()); + ESP_LOGI(TAG, "AXP192 PMU initialized, chip temp %.1f°C", pmu.getTemp()); AXP192_displaypower(); } I2C_MUTEX_UNLOCK(); // release i2c bus access From aa2712034b5cdaa8da6269adb1c3dfbe3b2c58c1 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 18:11:49 +0200 Subject: [PATCH 089/105] v1.8.3 --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 39f7925c..98bb49ec 100644 --- a/platformio.ini +++ b/platformio.ini @@ -73,8 +73,8 @@ lib_deps_basic = 76@>=1.2.2 ;Timezone by Jack Christensen 274@>=2.3.3 ;RTC by Michael Miller SimpleButton - AXP202X_Library@^1.0.0 - ;https://github.com/cyberman54/AXP202X_Library.git + ;AXP202X_Library@^1.0.0 + https://github.com/cyberman54/AXP202X_Library.git lib_deps_all = ${common.lib_deps_basic} ${common.lib_deps_lora} From d70df205fd7344471de44fc41c7bb9524f241be1 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 18:58:49 +0200 Subject: [PATCH 090/105] PMU bugfix --- src/power.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/power.cpp b/src/power.cpp index b4198c1d..8d06c39d 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -60,14 +60,15 @@ void AXP192_power(bool on) { if (on) { pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); // Lora on T-Beam V1.0 pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); // Gps on T-Beam V1.0 - pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); - pmu.setPowerOutPut(AXP192_DCDC3, AXP202_ON); + pmu.setPowerOutPut(AXP192_DCDC2, AXP202_ON); pmu.setPowerOutPut(AXP192_EXTEN, AXP202_ON); + pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); + // pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL); pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ); } else { - pmu.setPowerOutPut(AXP192_EXTEN, AXP202_OFF); - pmu.setPowerOutPut(AXP192_DCDC3, AXP202_OFF); pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); + pmu.setPowerOutPut(AXP192_EXTEN, AXP202_OFF); + pmu.setPowerOutPut(AXP192_DCDC2, AXP202_OFF); pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF); pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF); pmu.setChgLEDMode(AXP20X_LED_OFF); From f8a115ac17d2e5670f79f4d0d893205bff96a09a Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 19:23:43 +0200 Subject: [PATCH 091/105] revert ADR display inverse logic --- src/display.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index a448b9ae..2d8e7a13 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -203,10 +203,10 @@ void draw_page(time_t t, uint8_t page) { #if (HAS_LORA) u8x8.setCursor(11, 3); - if (cfg.adrmode) // if ADR=on then display SF value inverse + if (!cfg.adrmode) // if ADR=off then display SF value inverse u8x8.setInverseFont(1); u8x8.printf("%5s", getSfName(updr2rps(LMIC.datarate))); - if (cfg.adrmode) // switch off inverse if it was turned on + if (!cfg.adrmode) // switch off inverse if it was turned on u8x8.setInverseFont(0); #endif // HAS_LORA From af9d2150bff18e0a5d0a257a6195698796ae1096 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 19:45:37 +0200 Subject: [PATCH 092/105] display line6 code sanitized --- include/globals.h | 9 +++++---- src/display.cpp | 16 ++++++---------- src/lorawan.cpp | 21 ++++++++------------- src/main.cpp | 6 +++--- src/ota.cpp | 2 +- src/rcommand.cpp | 7 ------- 6 files changed, 23 insertions(+), 38 deletions(-) diff --git a/include/globals.h b/include/globals.h index 773af1ad..a753d5fb 100644 --- a/include/globals.h +++ b/include/globals.h @@ -42,7 +42,8 @@ #define SCREEN_MODE (0x80) // I2C bus access control -#define I2C_MUTEX_LOCK() (xSemaphoreTake(I2Caccess, pdMS_TO_TICKS(10)) == pdTRUE) +#define I2C_MUTEX_LOCK() \ + (xSemaphoreTake(I2Caccess, pdMS_TO_TICKS(10)) == pdTRUE) #define I2C_MUTEX_UNLOCK() (xSemaphoreGive(I2Caccess)) enum sendprio_t { prio_low, prio_normal, prio_high }; @@ -103,9 +104,9 @@ extern std::set, Mallocator> macs; extern std::array::iterator it; extern std::array beacons; -extern configData_t cfg; // current device configuration -extern char display_line6[], display_line7[]; // screen buffers -extern uint8_t volatile channel; // wifi channel rotation counter +extern configData_t cfg; // current device configuration +extern char lmic_event_msg[]; // display buffer +extern uint8_t volatile channel; // wifi channel rotation counter extern uint16_t volatile macs_total, macs_wifi, macs_ble, batt_voltage; // display values extern bool volatile TimePulseTick; // 1sec pps flag set by GPS or RTC diff --git a/src/display.cpp b/src/display.cpp index 2d8e7a13..d4786d19 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -13,12 +13,13 @@ Display-Mask (128 x 64 pixel): 3|BLTH:abcde SF:ab 4|WIFI:abcde ch:ab 5|RLIM:abcd abcdKB -6|xxxxxxxxxxxxxxxx 6|20:27:00* 27.Feb 7|yyyyyyyyyyyyyyab - -line 6: x = Text for LORA status OR time/date -line 7: y = Text for LMIC status; ab = payload queue + +line 6: * = time source indicator: L|G|R|?, + inverse = clock controller is active, + pulsed = pps input signal is active +line 7: y = LMIC event message; ab = payload queue length */ @@ -239,17 +240,13 @@ void draw_page(time_t t, uint8_t page) { #endif // HAS_DCF77 || HAS_IF482 if (timeSource != _unsynced) u8x8.printf(" %2d.%3s", day(t), printmonth[month(t)]); -#else // update LoRa status display -#if (HAS_LORA) - u8x8.printf("%-16s", display_line6); -#endif #endif // TIME_SYNC_INTERVAL #if (HAS_LORA) // line 7: update LMiC event display u8x8.setCursor(0, 7); - u8x8.printf("%-14s", display_line7); + u8x8.printf("%-14s", lmic_event_msg); // update LoRa send queue display msgWaiting = uxQueueMessagesWaiting(LoraSendQueue); @@ -259,7 +256,6 @@ void draw_page(time_t t, uint8_t page) { u8x8.printf("%-2s", msgWaiting == SEND_QUEUE_SIZE ? "<>" : buff); } else u8x8.printf(" "); - #endif // HAS_LORA break; // page0 diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 4ae42fd9..573e8aa5 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -231,7 +231,6 @@ void onEvent(ev_t ev) { case EV_JOINED: strcpy_P(buff, PSTR("JOINED")); - sprintf(display_line6, " "); // clear previous lmic status // set data rate adaptation according to saved setting LMIC_setAdrMode(cfg.adrmode); // set data rate and transmit power to defaults only if we have no ADR @@ -258,16 +257,7 @@ void onEvent(ev_t ev) { break; case EV_TXCOMPLETE: - -#if (TIME_SYNC_LORASERVER) - // if last packet sent was a timesync request, store TX timestamp - if (LMIC.pendTxPort == TIMEPORT) - store_time_sync_req(osticks2ms(LMIC.txend)); // milliseconds -#endif - - strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED ACK") - : PSTR("TX COMPLETE")); - sprintf(display_line6, " "); // clear previous lmic status + strcpy_P(buff, PSTR("TX COMPLETE")); break; case EV_LOST_TSYNC: @@ -321,7 +311,7 @@ void onEvent(ev_t ev) { // Log & Display if asked if (*buff) { ESP_LOGI(TAG, "%s", buff); - sprintf(display_line7, buff); + sprintf(lmic_event_msg, buff); } } @@ -585,7 +575,12 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, // transmit complete message handler void myTxCallback(void *pUserData, int fSuccess) { - /* currently no code here */ + +#if (TIME_SYNC_LORASERVER) + // if last packet sent was a timesync request, store TX timestamp + if (LMIC.pendTxPort == TIMEPORT) + store_time_sync_req(osticks2ms(LMIC.txend)); // milliseconds +#endif } // decode LORAWAN MAC message diff --git a/src/main.cpp b/src/main.cpp index c6eb2867..91741688 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,9 +76,9 @@ triggers pps 1 sec impulse // Basic Config #include "main.h" -configData_t cfg; // struct holds current device configuration -char display_line6[16], display_line7[16]; // display buffers -uint8_t volatile channel = 0; // channel rotation counter +configData_t cfg; // struct holds current device configuration +char lmic_event_msg[16]; // display buffer for LMIC event message +uint8_t volatile channel = 0; // channel rotation counter uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0, batt_voltage = 0; // globals for display diff --git a/src/ota.cpp b/src/ota.cpp index 18eaa84e..fc1662bc 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -41,7 +41,7 @@ inline String getHeaderValue(String header, String headerName) { void start_ota_update() { // check battery status if we can before doing ota - if (!batt_sufficient()) { + if (!batt_sufficient()) { ESP_LOGE(TAG, "Battery voltage %dmV too low for OTA", batt_voltage); return; } diff --git a/src/rcommand.cpp b/src/rcommand.cpp index b3053790..5c08210e 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -19,32 +19,25 @@ void do_reset() { void set_reset(uint8_t val[]) { switch (val[0]) { case 0: // restart device - sprintf(display_line6, "Reset pending"); do_reset(); break; case 1: // reset MAC counter ESP_LOGI(TAG, "Remote command: reset MAC counter"); reset_counters(); // clear macs get_salt(); // get new salt - sprintf(display_line6, "Reset counter"); break; case 2: // reset device to factory settings ESP_LOGI(TAG, "Remote command: reset device to factory settings"); - sprintf(display_line6, "Factory reset"); eraseConfig(); break; case 3: // reset send queues ESP_LOGI(TAG, "Remote command: flush send queue"); - sprintf(display_line6, "Queue reset"); flushQueues(); break; case 9: // reset and ask for software update via Wifi OTA ESP_LOGI(TAG, "Remote command: software update via Wifi"); #if (USE_OTA) - sprintf(display_line6, "Software update"); cfg.runmode = 1; -#else - sprintf(display_line6, "Software update not implemented"); #endif // USE_OTA break; From 8fba63a53f461730380046b3c66253dbc4822df0 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 20:00:31 +0200 Subject: [PATCH 093/105] display fine tuning --- src/display.cpp | 7 ++++--- src/lorawan.cpp | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index d4786d19..4826b2a2 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -10,15 +10,16 @@ Display-Mask (128 x 64 pixel): 0|PAX:aabbccddee 1|PAX:aabbccddee 2|B:a.bcV Sats:ab -3|BLTH:abcde SF:ab +3|BLTH:abcde SFab 4|WIFI:abcde ch:ab 5|RLIM:abcd abcdKB 6|20:27:00* 27.Feb 7|yyyyyyyyyyyyyyab -line 6: * = time source indicator: L|G|R|?, +line 6: * = char {L|G|R|?} indicates time source, inverse = clock controller is active, pulsed = pps input signal is active + line 7: y = LMIC event message; ab = payload queue length */ @@ -206,7 +207,7 @@ void draw_page(time_t t, uint8_t page) { u8x8.setCursor(11, 3); if (!cfg.adrmode) // if ADR=off then display SF value inverse u8x8.setInverseFont(1); - u8x8.printf("%5s", getSfName(updr2rps(LMIC.datarate))); + u8x8.printf("%4s", getSfName(updr2rps(LMIC.datarate))); if (!cfg.adrmode) // switch off inverse if it was turned on u8x8.setInverseFont(0); #endif // HAS_LORA diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 573e8aa5..d541dec3 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -646,12 +646,12 @@ uint8_t getBattLevel() { const char *getSfName(rps_t rps) { const char *const t[] = {"FSK", "SF7", "SF8", "SF9", - "SF10", "SF11", "SF12", "SFrfu"}; + "SF10", "SF11", "SF12", "SF?"}; return t[getSf(rps)]; } const char *getBwName(rps_t rps) { - const char *const t[] = {"BW125", "BW250", "BW500", "BWrfu"}; + const char *const t[] = {"BW125", "BW250", "BW500", "BW?"}; return t[getBw(rps)]; } From b587a5604e19ef475de3b8b80e0b2609b256c429 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 21:30:23 +0200 Subject: [PATCH 094/105] update README.md --- README.md | 21 +++++++++++++++++---- platformio.ini | 6 +++--- src/paxcounter.conf | 4 ++-- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4cb51ca8..8b20a195 100644 --- a/README.md +++ b/README.md @@ -311,7 +311,7 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. Example for EU868: - DataRate Radio Bit/s + DataRate Configuration Bit/s 0 LoRa: SF12 / 125 kHz 250 1 LoRa: SF11 / 125 kHz 440 2 LoRa: SF10 / 125 kHz 980 @@ -320,20 +320,33 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. 5 LoRa: SF7 / 125 kHz 5470 6* LoRa: SF7 / 250 kHz 11000 7* FSK: 50 kbps 50000 + 8 .. 14 reserved for future use (RFU) + 15 ignored (device keeps current setting) *) not supported by TheThingsNetwork 0x06 set LoRa TXpower - 0 ... 15 [default: 14] + 0 ... 15 [default: 7] + + TXPower Configuration + 0 Max EIRP (usually +16dB) + 1 -2dB + 2 -4dB + 3 -6dB + 4 -8dB + 5 -10dB + 6 -12dB + 7 -14dB + 8 .. 14 reserved for future use (RFU) + 15 ignored (device keeps current setting) 0x07 set LoRa Adaptive Data Rate mode 0 = ADR off 1 = ADR on [default] - Note: set ADR to off, if device is moving, set to on, if not. - If ADR is set to on, SF value is shown inverted on display. + If ADR is set to off, SF value is shown inverted on display. 0x08 do nothing diff --git a/platformio.ini b/platformio.ini index 98bb49ec..055aadf3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,7 +7,7 @@ ; ---> SELECT THE TARGET PLATFORM HERE! <--- [board] -halfile = generic.h +;halfile = generic.h ;halfile = ebox.h ;halfile = eboxtube.h ;halfile = ecopower.h @@ -18,7 +18,7 @@ halfile = generic.h ;halfile = ttgov21old.h ;halfile = ttgov21new.h ;halfile = ttgofox.h -;halfile = ttgobeam.h +halfile = ttgobeam.h ;halfile = ttgobeam10.h ;halfile = fipy.h ;halfile = lopy.h @@ -46,7 +46,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I release_version = 1.8.3 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose -debug_level = 3 +debug_level = 4 extra_scripts = pre:build.py otakeyfile = ota.conf lorakeyfile = loraconf.h diff --git a/src/paxcounter.conf b/src/paxcounter.conf index e18c8b60..5ee3a9a2 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -49,7 +49,7 @@ #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit #define LORADRDEFAULT 5 // 0 .. 15, LoRaWAN datarate, according to regional LoRaWAN specs [default = 5] -#define LORATXPOWDEFAULT 14 // 0 .. 15, LoRaWAN TX power +#define LORATXPOWDEFAULT 7 // 0 .. 15, LoRaWAN TX power [default = 7] #define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy #define SEND_QUEUE_SIZE 10 // maximum number of messages in payload send queue [1 = no queue] @@ -75,7 +75,7 @@ #define TIME_SYNC_INTERVAL_RETRY 10 // retry time sync after lost sync each .. minutes [default = 10], 0 means off #define TIME_SYNC_COMPILEDATE 0 // set to 1 to use compile date to initialize RTC after power outage [default = 0] #define TIME_SYNC_LORAWAN 0 // set to 1 to use LORA network as time source, 0 means off [default = 0] -#define TIME_SYNC_LORASERVER 0 // set to 1 to use LORA timeserver as time source, 0 means off [default = 0] +#define TIME_SYNC_LORASERVER 1 // set to 1 to use LORA timeserver as time source, 0 means off [default = 0] // settings for syncing time with timeserver applications #define TIME_SYNC_SAMPLES 1 // number of time requests for averaging From 464809a54e4f530733a16bed0d24b09d442cad29 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 21:42:59 +0200 Subject: [PATCH 095/105] bugfix cfg.txpower --- README.md | 14 +------------- platformio.ini | 8 ++++---- src/paxcounter.conf | 2 +- src/rcommand.cpp | 2 +- 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 8b20a195..eaea51cd 100644 --- a/README.md +++ b/README.md @@ -327,19 +327,7 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. 0x06 set LoRa TXpower - 0 ... 15 [default: 7] - - TXPower Configuration - 0 Max EIRP (usually +16dB) - 1 -2dB - 2 -4dB - 3 -6dB - 4 -8dB - 5 -10dB - 6 -12dB - 7 -14dB - 8 .. 14 reserved for future use (RFU) - 15 ignored (device keeps current setting) + 0 ... 255 desired TX power in dBm [default: 14] 0x07 set LoRa Adaptive Data Rate mode diff --git a/platformio.ini b/platformio.ini index 055aadf3..dbab2b1b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,7 +7,7 @@ ; ---> SELECT THE TARGET PLATFORM HERE! <--- [board] -;halfile = generic.h +halfile = generic.h ;halfile = ebox.h ;halfile = eboxtube.h ;halfile = ecopower.h @@ -18,7 +18,7 @@ ;halfile = ttgov21old.h ;halfile = ttgov21new.h ;halfile = ttgofox.h -halfile = ttgobeam.h +;halfile = ttgobeam.h ;halfile = ttgobeam10.h ;halfile = fipy.h ;halfile = lopy.h @@ -43,10 +43,10 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.8.3 +release_version = 1.8.31 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose -debug_level = 4 +debug_level = 3 extra_scripts = pre:build.py otakeyfile = ota.conf lorakeyfile = loraconf.h diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 5ee3a9a2..4f866c27 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -49,7 +49,7 @@ #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit #define LORADRDEFAULT 5 // 0 .. 15, LoRaWAN datarate, according to regional LoRaWAN specs [default = 5] -#define LORATXPOWDEFAULT 7 // 0 .. 15, LoRaWAN TX power [default = 7] +#define LORATXPOWDEFAULT 7 // 0 .. 255, LoRaWAN TX power in dBm [default = 14] #define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy #define SEND_QUEUE_SIZE 10 // maximum number of messages in payload send queue [1 = no queue] diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 5c08210e..e8b9f3da 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -254,7 +254,7 @@ void set_lorapower(uint8_t val[]) { #if (HAS_LORA) // set data rate and transmit power only if we have no ADR if (!cfg.adrmode) { - cfg.txpower = val[0] & 0x0f; + cfg.txpower = val[0]; ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %d", cfg.txpower); LMIC_setDrTxpow(assertDR(cfg.loradr), cfg.txpower); } else From 424329afb20f06ea414e33ac1bff2f50c8e94f91 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Fri, 20 Sep 2019 21:45:16 +0200 Subject: [PATCH 096/105] Update paxcounter.conf --- src/paxcounter.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 4f866c27..40852f59 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -75,7 +75,7 @@ #define TIME_SYNC_INTERVAL_RETRY 10 // retry time sync after lost sync each .. minutes [default = 10], 0 means off #define TIME_SYNC_COMPILEDATE 0 // set to 1 to use compile date to initialize RTC after power outage [default = 0] #define TIME_SYNC_LORAWAN 0 // set to 1 to use LORA network as time source, 0 means off [default = 0] -#define TIME_SYNC_LORASERVER 1 // set to 1 to use LORA timeserver as time source, 0 means off [default = 0] +#define TIME_SYNC_LORASERVER 0 // set to 1 to use LORA timeserver as time source, 0 means off [default = 0] // settings for syncing time with timeserver applications #define TIME_SYNC_SAMPLES 1 // number of time requests for averaging @@ -111,4 +111,4 @@ #define CAYENNE_ACTUATOR 10 // actuator commands #define CAYENNE_DEVICECONFIG 11 // device period configuration #define CAYENNE_SENSORREAD 13 // sensor period configuration -#define CAYENNE_SENSORENABLE 14 // sensor enable configuration \ No newline at end of file +#define CAYENNE_SENSORENABLE 14 // sensor enable configuration From 9408ed99feb99b4040243509ea41521e9b0f7e67 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 21 Sep 2019 08:23:39 +0200 Subject: [PATCH 097/105] PMU: show USB power --- src/power.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/power.cpp b/src/power.cpp index 8d06c39d..c7297123 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -16,9 +16,10 @@ void pover_event_IRQ(void) { // put your power event handler code here if (pmu.isVbusOverVoltageIRQ()) - ESP_LOGI(TAG, "USB voltage %.1fV too high.", pmu.getVbusVoltage()); + ESP_LOGI(TAG, "USB voltage %.2fV too high.", pmu.getVbusVoltage() / 1000); if (pmu.isVbusPlugInIRQ()) - ESP_LOGI(TAG, "USB plugged."); + ESP_LOGI(TAG, "USB plugged, %.2fV @ %.0mA", pmu.getVbusVoltage() / 1000, + pmu.getVbusCurrent()); if (pmu.isVbusRemoveIRQ()) ESP_LOGI(TAG, "USB unplugged."); @@ -78,14 +79,16 @@ void AXP192_power(bool on) { void AXP192_displaypower(void) { if (pmu.isBatteryConnect()) if (pmu.isChargeing()) - ESP_LOGI(TAG, "Battery charging @ %.0fmAh", pmu.getBattChargeCurrent()); + ESP_LOGI(TAG, "Battery charging, %.2fV @ %.0fmAh", + pmu.getBattVoltage() / 1000, pmu.getBattChargeCurrent()); else ESP_LOGI(TAG, "Battery not charging"); else ESP_LOGI(TAG, "No Battery"); if (pmu.isVBUSPlug()) - ESP_LOGI(TAG, "USB present"); + ESP_LOGI(TAG, "USB present, %.2fV @ %.0fmA", pmu.getVbusVoltage() / 1000, + pmu.getVbusCurrent()); else ESP_LOGI(TAG, "USB not present"); } @@ -101,9 +104,14 @@ void AXP192_init(void) { // switch power on pmu.setDCDC1Voltage(3300); // for external OLED display - pmu.adc1Enable(AXP202_BATT_CUR_ADC1, 1); AXP192_power(true); + // switch ADCs on + pmu.adc1Enable(AXP202_BATT_VOL_ADC1, true); + pmu.adc1Enable(AXP202_BATT_CUR_ADC1, true); + pmu.adc1Enable(AXP202_VBUS_VOL_ADC1, true); + pmu.adc1Enable(AXP202_VBUS_CUR_ADC1, true); + // set TS pin mode off to save power pmu.setTSmode(AXP_TS_PIN_MODE_DISABLE); From e95248d8a167c413f6e5bfa727f7a271e7e3cb96 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sat, 21 Sep 2019 21:42:55 +0200 Subject: [PATCH 098/105] platformio.ini: pinned commit MCCI LMIC --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index dbab2b1b..5dd08b65 100644 --- a/platformio.ini +++ b/platformio.ini @@ -56,7 +56,7 @@ monitor_speed = 115200 upload_speed = 115200 lib_deps_lora = ;MCCI LoRaWAN LMIC library@2.3.2 - https://github.com/mcci-catena/arduino-lmic.git + https://github.com/mcci-catena/arduino-lmic.git#852f348 lib_deps_display = U8g2@>=2.26.13 lib_deps_matrix_display = From 9a9deb9c1cd6fd1616e7bc7547b115d1691b2c1d Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 23 Sep 2019 15:39:58 +0200 Subject: [PATCH 099/105] mute gpsread in verbose debug mode --- src/gpsread.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gpsread.cpp b/src/gpsread.cpp index a4dced58..eab3b3b3 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -153,10 +153,10 @@ void gps_loop(void *pvParameters) { #endif } // if - // show NMEA data in verbose mode, useful for debugging GPS - ESP_LOGV(TAG, "GPS NMEA data: passed %u / failed: %u / with fix: %u", - gps.passedChecksum(), gps.failedChecksum(), - gps.sentencesWithFix()); + // show NMEA data in verbose mode, useful for debugging GPS, bu tvery noisy + //ESP_LOGV(TAG, "GPS NMEA data: passed %u / failed: %u / with fix: %u", + // gps.passedChecksum(), gps.failedChecksum(), + // gps.sentencesWithFix()); delay(2); // yield to CPU From 6abfc26f2ef62923d2446fc22c7c303b316231f7 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 23 Sep 2019 15:40:34 +0200 Subject: [PATCH 100/105] LORA SF display fine tuned --- src/lorawan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index d541dec3..088d4305 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -645,7 +645,7 @@ uint8_t getBattLevel() { // u1_t os_getBattLevel(void) { return getBattLevel(); }; const char *getSfName(rps_t rps) { - const char *const t[] = {"FSK", "SF7", "SF8", "SF9", + const char *const t[] = {"FSK", "SF7", "SF8", "SF9", "SF10", "SF11", "SF12", "SF?"}; return t[getSf(rps)]; } From 7daa36366b1d8a9859a7a57c9bc55ae104e40d9d Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 23 Sep 2019 15:45:47 +0200 Subject: [PATCH 101/105] v1.8.34 (power on/off features for T-BEAM V10) --- include/power.h | 16 +++---- platformio.ini | 13 +++--- src/cyclic.cpp | 5 +- src/display.cpp | 9 ++-- src/hal/ttgobeam10.h | 49 ++++++++++++++++---- src/irqhandler.cpp | 2 +- src/power.cpp | 108 +++++++++++++++++++++++-------------------- 7 files changed, 120 insertions(+), 82 deletions(-) diff --git a/include/power.h b/include/power.h index c27daa6c..1ef571e1 100644 --- a/include/power.h +++ b/include/power.h @@ -9,16 +9,16 @@ #define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate #define NO_OF_SAMPLES 64 // we do some multisampling to get better values -#ifdef HAS_PMU -#include -void pover_event_IRQ(void); -void AXP192_power(bool on); -#endif - -void AXP192_init(void); -void AXP192_displaypower(void); uint16_t read_voltage(void); void calibrate_voltage(void); bool batt_sufficient(void); +#ifdef HAS_PMU +#include +void power_event_IRQ(void); +void AXP192_power(bool on); +void AXP192_init(void); +void AXP192_showstatus(void); +#endif // HAS_PMU + #endif \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 5dd08b65..ba1ef203 100644 --- a/platformio.ini +++ b/platformio.ini @@ -43,7 +43,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.8.31 +release_version = 1.8.34 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 @@ -55,7 +55,7 @@ platform_espressif32 = espressif32@1.10.0 monitor_speed = 115200 upload_speed = 115200 lib_deps_lora = - ;MCCI LoRaWAN LMIC library@2.3.2 + ;MCCI LoRaWAN LMIC library@3.1.0 https://github.com/mcci-catena/arduino-lmic.git#852f348 lib_deps_display = U8g2@>=2.26.13 @@ -73,8 +73,9 @@ lib_deps_basic = 76@>=1.2.2 ;Timezone by Jack Christensen 274@>=2.3.3 ;RTC by Michael Miller SimpleButton - ;AXP202X_Library@^1.0.0 - https://github.com/cyberman54/AXP202X_Library.git + ;AXP202X_Library@^1.0.1 + https://github.com/lewisxhe/AXP202X_Library.git#8045ddf + ;https://github.com/cyberman54/AXP202X_Library.git#b7116de lib_deps_all = ${common.lib_deps_basic} ${common.lib_deps_lora} @@ -120,6 +121,4 @@ upload_protocol = esptool upload_protocol = esptool build_type = debug platform = https://github.com/platformio/platform-espressif32.git#develop -platform_packages = - ; use upstream Git version - framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git +platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git diff --git a/src/cyclic.cpp b/src/cyclic.cpp index d616d573..ef2ce200 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -62,10 +62,7 @@ void doHousekeeping() { else ESP_LOGI(TAG, "Battery: %dmV", batt_voltage); #ifdef HAS_PMU - if (I2C_MUTEX_LOCK()) { - AXP192_displaypower(); - I2C_MUTEX_UNLOCK(); - } + AXP192_showstatus(); #endif #endif diff --git a/src/display.cpp b/src/display.cpp index 4826b2a2..b89f551d 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -179,7 +179,10 @@ void draw_page(time_t t, uint8_t page) { // update Battery status (line 2) #if (defined BAT_MEASURE_ADC || defined HAS_PMU) u8x8.setCursor(0, 2); - u8x8.printf("B:%.2fV", batt_voltage / 1000.0); + if (batt_voltage == 0xffff) + u8x8.printf("B:USB "); + else + u8x8.printf("B:%.2fV", batt_voltage / 1000.0); #endif // update GPS status (line 2) @@ -204,10 +207,10 @@ void draw_page(time_t t, uint8_t page) { #endif #if (HAS_LORA) - u8x8.setCursor(11, 3); + u8x8.setCursor(12, 3); if (!cfg.adrmode) // if ADR=off then display SF value inverse u8x8.setInverseFont(1); - u8x8.printf("%4s", getSfName(updr2rps(LMIC.datarate))); + u8x8.printf("%-4s", getSfName(updr2rps(LMIC.datarate))); if (!cfg.adrmode) // switch off inverse if it was turned on u8x8.setInverseFont(0); #endif // HAS_LORA diff --git a/src/hal/ttgobeam10.h b/src/hal/ttgobeam10.h index dffe7c61..fa0b3ffa 100644 --- a/src/hal/ttgobeam10.h +++ b/src/hal/ttgobeam10.h @@ -7,9 +7,24 @@ #include -// Hardware related definitions for TTGO T-Beam board -// (only) for newer T-Beam version T22_V10 -// pinouts taken from https://github.com/lewisxhe/TTGO-T-Beam +/* +Hardware related definitions for TTGO T-Beam board +(only) for newer T-Beam version T22_V10 +pinouts taken from https://github.com/lewisxhe/TTGO-T-Beam + +/// Button functions: /// +Power, short press -> set device on (toggles display while device is on) +Power, long press -> set device off +User, short press -> flip display page +User, long press -> send LORA message +Reset -> reset device +*/ + +//#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C +#define MY_OLED_SDA SDA +#define MY_OLED_SCL SCL +#define MY_OLED_RST U8X8_PIN_NONE +//#define DISPLAY_FLIP 1 // use if display is rotated #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1276_radio 1 // HPD13A LoRa SoC @@ -30,16 +45,30 @@ //#define HAS_BME680 SDA, SCL //#define BME680_ADDR BME680_I2C_ADDR_PRIMARY // !! connect SDIO of BME680 to GND !! -// display (if connected) -//#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C -//#define MY_OLED_SDA SDA -//#define MY_OLED_SCL SCL -//#define MY_OLED_RST U8X8_PIN_NONE -//#define DISPLAY_FLIP 1 // use if display is rotated - // user defined sensors (if connected) //#define HAS_SENSORS 1 // comment out if device has user defined sensors //#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature #endif + +/* + +// T-Beam V10 has on board power management by AXP192 PMU chip: +// +// DCDC1 0.7-3.5V @ 1200mA -> OLED +// DCDC3 0.7-3.5V @ 700mA -> ESP32 (keep this on!) +// LDO1 30mA -> GPS Backup +// LDO2 200mA -> LORA +// LDO3 200mA -> GPS + +// Wiring for I2C OLED display: +// +// Signal Header OLED +// 3V3 7 VCC +// GND 8 GND +// IO22(SCL) 9 SCL +// IO21(SDA) 10 SDA +// + +*/ diff --git a/src/irqhandler.cpp b/src/irqhandler.cpp index 74bcd29f..8d1be880 100644 --- a/src/irqhandler.cpp +++ b/src/irqhandler.cpp @@ -66,7 +66,7 @@ void irqHandler(void *pvParameters) { // do we have a power event? #if (HAS_PMU) if (InterruptStatus & PMU_IRQ) - pover_event_IRQ(); + power_event_IRQ(); #endif // is time to send the payload? diff --git a/src/power.cpp b/src/power.cpp index c7297123..83748286 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -9,9 +9,12 @@ static const char TAG[] = __FILE__; AXP20X_Class pmu; -void pover_event_IRQ(void) { - // block i2c bus access - if (I2C_MUTEX_LOCK()) { +void power_event_IRQ(void) { + + if (!I2C_MUTEX_LOCK()) + ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0); + else { + pmu.readIRQ(); // put your power event handler code here @@ -36,61 +39,63 @@ void pover_event_IRQ(void) { if (pmu.isBattTempHighIRQ()) ESP_LOGI(TAG, "Battery low temperature."); - // wake up + // display on/off if (pmu.isPEKShortPressIRQ()) { - ESP_LOGI(TAG, "Power Button short pressed."); - AXP192_power(true); + cfg.screenon = !cfg.screenon; } - // enter sleep mode + + // shutdown power if (pmu.isPEKLongtPressIRQ()) { - ESP_LOGI(TAG, "Power Button long pressed."); - AXP192_power(false); - delay(20); - esp_sleep_enable_ext1_wakeup(GPIO_SEL_38, ESP_EXT1_WAKEUP_ALL_LOW); - esp_deep_sleep_start(); + AXP192_power(false); // switch off Lora, GPS, display + pmu.shutdown(); } pmu.clearIRQ(); - I2C_MUTEX_UNLOCK(); // release i2c bus access - } else - ESP_LOGI(TAG, "Unknown PMU event."); + I2C_MUTEX_UNLOCK(); + } // mutex + + // refresh stored voltage value + read_voltage(); } void AXP192_power(bool on) { - if (on) { - pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); // Lora on T-Beam V1.0 - pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); // Gps on T-Beam V1.0 - pmu.setPowerOutPut(AXP192_DCDC2, AXP202_ON); - pmu.setPowerOutPut(AXP192_EXTEN, AXP202_ON); - pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); + pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); // Lora on T-Beam V1.0 + pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); // Gps on T-Beam V1.0 + pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); // OLED on T-Beam v1.0 // pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL); pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ); } else { + pmu.setChgLEDMode(AXP20X_LED_OFF); pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); - pmu.setPowerOutPut(AXP192_EXTEN, AXP202_OFF); - pmu.setPowerOutPut(AXP192_DCDC2, AXP202_OFF); pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF); pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF); - pmu.setChgLEDMode(AXP20X_LED_OFF); } } -void AXP192_displaypower(void) { - if (pmu.isBatteryConnect()) - if (pmu.isChargeing()) - ESP_LOGI(TAG, "Battery charging, %.2fV @ %.0fmAh", - pmu.getBattVoltage() / 1000, pmu.getBattChargeCurrent()); - else - ESP_LOGI(TAG, "Battery not charging"); - else - ESP_LOGI(TAG, "No Battery"); +void AXP192_showstatus(void) { - if (pmu.isVBUSPlug()) - ESP_LOGI(TAG, "USB present, %.2fV @ %.0fmA", pmu.getVbusVoltage() / 1000, - pmu.getVbusCurrent()); - else - ESP_LOGI(TAG, "USB not present"); + if (!I2C_MUTEX_LOCK()) + ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0); + else { + + if (pmu.isBatteryConnect()) + if (pmu.isChargeing()) + ESP_LOGI(TAG, "Battery charging, %.2fV @ %.0fmAh", + pmu.getBattVoltage() / 1000, pmu.getBattChargeCurrent()); + else + ESP_LOGI(TAG, "Battery not charging"); + else + ESP_LOGI(TAG, "No Battery"); + + if (pmu.isVBUSPlug()) + ESP_LOGI(TAG, "USB powered, %.0fmW", + pmu.getVbusVoltage() / 1000 * pmu.getVbusCurrent()); + else + ESP_LOGI(TAG, "USB not present"); + + I2C_MUTEX_UNLOCK(); + } // mutex } void AXP192_init(void) { @@ -102,9 +107,10 @@ void AXP192_init(void) { ESP_LOGI(TAG, "AXP192 PMU initialization failed"); else { - // switch power on - pmu.setDCDC1Voltage(3300); // for external OLED display - AXP192_power(true); + // configure AXP192 + pmu.setDCDC1Voltage(3300); // for external OLED display + pmu.setTimeOutShutdown(false); // no automatic shutdown + pmu.setTSmode(AXP_TS_PIN_MODE_DISABLE); // TS pin mode off to save power // switch ADCs on pmu.adc1Enable(AXP202_BATT_VOL_ADC1, true); @@ -112,8 +118,8 @@ void AXP192_init(void) { pmu.adc1Enable(AXP202_VBUS_VOL_ADC1, true); pmu.adc1Enable(AXP202_VBUS_CUR_ADC1, true); - // set TS pin mode off to save power - pmu.setTSmode(AXP_TS_PIN_MODE_DISABLE); + // switch power rails on + AXP192_power(true); // I2C access of AXP202X library currently is not mutexable // so we better should disable AXP interrupts... ? @@ -121,13 +127,13 @@ void AXP192_init(void) { pinMode(PMU_INT, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(PMU_INT), PMUIRQ, FALLING); pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | - AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, + AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ | + AXP202_CHARGING_FINISHED_IRQ, 1); pmu.clearIRQ(); #endif // PMU_INT - ESP_LOGI(TAG, "AXP192 PMU initialized, chip temp %.1f°C", pmu.getTemp()); - AXP192_displaypower(); + ESP_LOGI(TAG, "AXP192 PMU initialized"); } I2C_MUTEX_UNLOCK(); // release i2c bus access } else @@ -157,7 +163,7 @@ void calibrate_voltage(void) { ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12)); ESP_ERROR_CHECK(adc1_config_channel_atten(adc_channel, atten)); #else // ADC2 - // ESP_ERROR_CHECK(adc2_config_width(ADC_WIDTH_BIT_12)); + // ESP_ERROR_CHECK(adc2_config_width(ADC_WIDTH_BIT_12)); ESP_ERROR_CHECK(adc2_config_channel_atten(adc_channel, atten)); #endif // calibrate ADC @@ -187,11 +193,15 @@ bool batt_sufficient() { } uint16_t read_voltage() { - uint16_t voltage = 0; #ifdef HAS_PMU - voltage = pmu.isVBUSPlug() ? 0xffff : pmu.getBattVoltage(); + if (!I2C_MUTEX_LOCK()) + ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0); + else { + voltage = pmu.isVBUSPlug() ? 0xffff : pmu.getBattVoltage(); + I2C_MUTEX_UNLOCK(); + } #else #ifdef BAT_MEASURE_ADC From 1ae64f03aa8455b67596020097a327efdf560020 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 23 Sep 2019 16:23:44 +0200 Subject: [PATCH 102/105] library version updates (issue #452) --- platformio.ini | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index ba1ef203..5ab8b09e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -55,8 +55,7 @@ platform_espressif32 = espressif32@1.10.0 monitor_speed = 115200 upload_speed = 115200 lib_deps_lora = - ;MCCI LoRaWAN LMIC library@3.1.0 - https://github.com/mcci-catena/arduino-lmic.git#852f348 + MCCI LoRaWAN LMIC library>=@3.0.99 lib_deps_display = U8g2@>=2.26.13 lib_deps_matrix_display = @@ -75,7 +74,6 @@ lib_deps_basic = SimpleButton ;AXP202X_Library@^1.0.1 https://github.com/lewisxhe/AXP202X_Library.git#8045ddf - ;https://github.com/cyberman54/AXP202X_Library.git#b7116de lib_deps_all = ${common.lib_deps_basic} ${common.lib_deps_lora} From dae486ae6533cf9617b6b077f005a2b95e9ab00a Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 23 Sep 2019 16:50:10 +0200 Subject: [PATCH 103/105] Update platformio.ini --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 5ab8b09e..adfcc3e1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -55,7 +55,7 @@ platform_espressif32 = espressif32@1.10.0 monitor_speed = 115200 upload_speed = 115200 lib_deps_lora = - MCCI LoRaWAN LMIC library>=@3.0.99 + MCCI LoRaWAN LMIC library@>=3.0.99 lib_deps_display = U8g2@>=2.26.13 lib_deps_matrix_display = From 61558d9d67460e35d684839c1038cfcf85792f95 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 23 Sep 2019 16:50:49 +0200 Subject: [PATCH 104/105] Update platformio.ini --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 5ab8b09e..adfcc3e1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -55,7 +55,7 @@ platform_espressif32 = espressif32@1.10.0 monitor_speed = 115200 upload_speed = 115200 lib_deps_lora = - MCCI LoRaWAN LMIC library>=@3.0.99 + MCCI LoRaWAN LMIC library@>=3.0.99 lib_deps_display = U8g2@>=2.26.13 lib_deps_matrix_display = From 868b788b5f37af1dc8aac284c8e5a71c2d6f8a1f Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 30 Sep 2019 18:33:32 +0200 Subject: [PATCH 105/105] Downgrade platformio-espressif 1.10.0 -> 1.9.0 v1.10.0 breaks HTTPS communication for ota.cpp :-( --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index adfcc3e1..3d1eda59 100644 --- a/platformio.ini +++ b/platformio.ini @@ -51,7 +51,7 @@ extra_scripts = pre:build.py otakeyfile = ota.conf lorakeyfile = loraconf.h lmicconfigfile = lmic_config.h -platform_espressif32 = espressif32@1.10.0 +platform_espressif32 = espressif32@1.9.0 monitor_speed = 115200 upload_speed = 115200 lib_deps_lora =