commit
f38c4024a7
@ -26,7 +26,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng
|
|||||||
|
|
||||||
[common]
|
[common]
|
||||||
; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
|
; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
|
||||||
release_version = 1.5.8
|
release_version = 1.5.9
|
||||||
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
|
; 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
|
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
|
||||||
debug_level = 0
|
debug_level = 0
|
||||||
|
@ -7,15 +7,15 @@
|
|||||||
static const char TAG[] = "main";
|
static const char TAG[] = "main";
|
||||||
|
|
||||||
void IRAM_ATTR ButtonIRQ() {
|
void IRAM_ATTR ButtonIRQ() {
|
||||||
portENTER_CRITICAL(&timerMux);
|
portENTER_CRITICAL(&mutexButton);
|
||||||
ButtonPressedIRQ++;
|
ButtonPressedIRQ++;
|
||||||
portEXIT_CRITICAL(&timerMux);
|
portEXIT_CRITICAL(&mutexButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
void readButton() {
|
void readButton() {
|
||||||
portENTER_CRITICAL(&timerMux);
|
portENTER_CRITICAL(&mutexButton);
|
||||||
ButtonPressedIRQ = 0;
|
ButtonPressedIRQ = 0;
|
||||||
portEXIT_CRITICAL(&timerMux);
|
portEXIT_CRITICAL(&mutexButton);
|
||||||
ESP_LOGI(TAG, "Button pressed");
|
ESP_LOGI(TAG, "Button pressed");
|
||||||
payload.reset();
|
payload.reset();
|
||||||
payload.addButton(0x01);
|
payload.addButton(0x01);
|
||||||
|
@ -12,9 +12,9 @@ static const char TAG[] = "main";
|
|||||||
// do all housekeeping
|
// do all housekeeping
|
||||||
void doHousekeeping() {
|
void doHousekeeping() {
|
||||||
|
|
||||||
portENTER_CRITICAL(&timerMux);
|
portENTER_CRITICAL(&mutexHomeCycle);
|
||||||
HomeCycleIRQ = 0;
|
HomeCycleIRQ = 0;
|
||||||
portEXIT_CRITICAL(&timerMux);
|
portEXIT_CRITICAL(&mutexHomeCycle);
|
||||||
|
|
||||||
// update uptime counter
|
// update uptime counter
|
||||||
uptime();
|
uptime();
|
||||||
@ -69,9 +69,9 @@ void doHousekeeping() {
|
|||||||
} // doHousekeeping()
|
} // doHousekeeping()
|
||||||
|
|
||||||
void IRAM_ATTR homeCycleIRQ() {
|
void IRAM_ATTR homeCycleIRQ() {
|
||||||
portENTER_CRITICAL(&timerMux);
|
portENTER_CRITICAL(&mutexHomeCycle);
|
||||||
HomeCycleIRQ++;
|
HomeCycleIRQ++;
|
||||||
portEXIT_CRITICAL(&timerMux);
|
portEXIT_CRITICAL(&mutexHomeCycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// uptime counter 64bit to prevent millis() rollover after 49 days
|
// uptime counter 64bit to prevent millis() rollover after 49 days
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define _CYCLIC_H
|
#define _CYCLIC_H
|
||||||
|
|
||||||
void doHousekeeping(void);
|
void doHousekeeping(void);
|
||||||
void homeCycleIRQ(void);
|
void IRAM_ATTR homeCycleIRQ(void);
|
||||||
uint64_t uptime(void);
|
uint64_t uptime(void);
|
||||||
void reset_counters(void);
|
void reset_counters(void);
|
||||||
int redirect_log(const char *fmt, va_list args);
|
int redirect_log(const char *fmt, va_list args);
|
||||||
|
@ -91,9 +91,9 @@ void init_display(const char *Productname, const char *Version) {
|
|||||||
|
|
||||||
void refreshtheDisplay() {
|
void refreshtheDisplay() {
|
||||||
|
|
||||||
portENTER_CRITICAL(&timerMux);
|
portENTER_CRITICAL(&mutexDisplay);
|
||||||
DisplayTimerIRQ = 0;
|
DisplayTimerIRQ = 0;
|
||||||
portEXIT_CRITICAL(&timerMux);
|
portEXIT_CRITICAL(&mutexDisplay);
|
||||||
|
|
||||||
// set display on/off according to current device configuration
|
// set display on/off according to current device configuration
|
||||||
if (DisplayState != cfg.screenon) {
|
if (DisplayState != cfg.screenon) {
|
||||||
@ -191,9 +191,9 @@ void refreshtheDisplay() {
|
|||||||
} // refreshDisplay()
|
} // refreshDisplay()
|
||||||
|
|
||||||
void IRAM_ATTR DisplayIRQ() {
|
void IRAM_ATTR DisplayIRQ() {
|
||||||
portENTER_CRITICAL_ISR(&timerMux);
|
portENTER_CRITICAL_ISR(&mutexDisplay);
|
||||||
DisplayTimerIRQ++;
|
DisplayTimerIRQ++;
|
||||||
portEXIT_CRITICAL_ISR(&timerMux);
|
portEXIT_CRITICAL_ISR(&mutexDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // HAS_DISPLAY
|
#endif // HAS_DISPLAY
|
@ -9,6 +9,6 @@ extern HAS_DISPLAY u8x8;
|
|||||||
void init_display(const char *Productname, const char *Version);
|
void init_display(const char *Productname, const char *Version);
|
||||||
void refreshtheDisplay(void);
|
void refreshtheDisplay(void);
|
||||||
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb);
|
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb);
|
||||||
void DisplayIRQ(void);
|
void IRAM_ATTR DisplayIRQ(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -46,7 +46,7 @@ extern uint16_t volatile macs_total, macs_wifi, macs_ble,
|
|||||||
batt_voltage; // display values
|
batt_voltage; // display values
|
||||||
extern std::set<uint16_t> macs; // temp storage for MACs
|
extern std::set<uint16_t> macs; // temp storage for MACs
|
||||||
extern hw_timer_t *channelSwitch, *sendCycle;
|
extern hw_timer_t *channelSwitch, *sendCycle;
|
||||||
extern portMUX_TYPE timerMux;
|
extern portMUX_TYPE mutexButton, mutexDisplay, mutexHomeCycle, mutexSendCycle;
|
||||||
extern volatile uint8_t SendCycleTimerIRQ, HomeCycleIRQ, DisplayTimerIRQ,
|
extern volatile uint8_t SendCycleTimerIRQ, HomeCycleIRQ, DisplayTimerIRQ,
|
||||||
ChannelTimerIRQ, ButtonPressedIRQ;
|
ChannelTimerIRQ, ButtonPressedIRQ;
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
#define HAS_LED NOT_A_PIN // no usable LED on board
|
#define HAS_LED NOT_A_PIN // no usable LED on board
|
||||||
|
|
||||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||||
#define DISPLAY_FLIP 1 // rotated display
|
//#define DISPLAY_FLIP 1 // rotated display
|
||||||
#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7
|
//#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7
|
||||||
#define BATT_FACTOR 2 // voltage divider 100k/100k on board
|
//#define BATT_FACTOR 2 // voltage divider 100k/100k on board
|
||||||
|
|
||||||
// re-define pin definitions of pins_arduino.h
|
// re-define pin definitions of pins_arduino.h
|
||||||
#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input
|
#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input
|
||||||
|
@ -34,9 +34,9 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include "hash.h"
|
||||||
|
|
||||||
uint32_t rokkit(const char *data, int len) {
|
uint32_t IRAM_ATTR rokkit(const char *data, int len) {
|
||||||
uint32_t hash, tmp;
|
uint32_t hash, tmp;
|
||||||
int rem;
|
int rem;
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#ifndef _HASH_H
|
#ifndef _HASH_H
|
||||||
#define _HASH_H
|
#define _HASH_H
|
||||||
|
|
||||||
uint32_t rokkit(const char *data, int len);
|
#include <Arduino.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
uint32_t IRAM_ATTR rokkit(const char *data, int len);
|
||||||
|
|
||||||
#endif
|
#endif
|
22
src/main.cpp
22
src/main.cpp
@ -26,12 +26,12 @@ licenses. Refer to LICENSE.txt file in repository for more details.
|
|||||||
Uused tasks and timers:
|
Uused tasks and timers:
|
||||||
|
|
||||||
Task Core Prio Purpose
|
Task Core Prio Purpose
|
||||||
====================================================================
|
====================================================================================
|
||||||
IDLE 0 0 ESP32 arduino scheduler
|
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer task
|
||||||
gpsloop 0 2 read data from GPS over serial or i2c
|
gpsloop 0 2 read data from GPS over serial or i2c
|
||||||
IDLE 1 0 Arduino loop() -> used for LED switching
|
IDLE 1 0 Arduino loop() -> used for LED switching
|
||||||
loraloop 1 1 runs the LMIC stack
|
loraloop 1 3 runs the LMIC stack
|
||||||
statemachine 1 3 switches application process logic
|
statemachine 1 1 switches application process logic
|
||||||
wifiloop 0 4 rotates wifi channels
|
wifiloop 0 4 rotates wifi channels
|
||||||
|
|
||||||
ESP32 hardware timers
|
ESP32 hardware timers
|
||||||
@ -77,9 +77,11 @@ QueueHandle_t SPISendQueue;
|
|||||||
TaskHandle_t GpsTask = NULL;
|
TaskHandle_t GpsTask = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
portMUX_TYPE timerMux =
|
// sync main loop and ISR when modifying IRQ handler shared variables
|
||||||
portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying IRQ
|
portMUX_TYPE mutexButton = portMUX_INITIALIZER_UNLOCKED;
|
||||||
// handler shared variables
|
portMUX_TYPE mutexDisplay = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
portMUX_TYPE mutexHomeCycle = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
portMUX_TYPE mutexSendCycle = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
std::set<uint16_t> macs; // container holding unique MAC adress hashes
|
std::set<uint16_t> macs; // container holding unique MAC adress hashes
|
||||||
|
|
||||||
@ -312,7 +314,7 @@ void setup() {
|
|||||||
"loraloop", /* name of task */
|
"loraloop", /* name of task */
|
||||||
2560, /* stack size of task */
|
2560, /* stack size of task */
|
||||||
(void *)1, /* parameter of the task */
|
(void *)1, /* parameter of the task */
|
||||||
1, /* priority of the task */
|
3, /* priority of the task */
|
||||||
&LoraTask, /* task handle*/
|
&LoraTask, /* task handle*/
|
||||||
1); /* CPU core */
|
1); /* CPU core */
|
||||||
#endif
|
#endif
|
||||||
@ -350,7 +352,7 @@ void setup() {
|
|||||||
// start wifi channel rotation task
|
// start wifi channel rotation task
|
||||||
xTaskCreatePinnedToCore(switchWifiChannel, /* task function */
|
xTaskCreatePinnedToCore(switchWifiChannel, /* task function */
|
||||||
"wifiloop", /* name of task */
|
"wifiloop", /* name of task */
|
||||||
1024, /* stack size of task */
|
1536, /* stack size of task */
|
||||||
NULL, /* parameter of the task */
|
NULL, /* parameter of the task */
|
||||||
4, /* priority of the task */
|
4, /* priority of the task */
|
||||||
&wifiSwitchTask, /* task handle*/
|
&wifiSwitchTask, /* task handle*/
|
||||||
@ -362,7 +364,7 @@ void setup() {
|
|||||||
"stateloop", /* name of task */
|
"stateloop", /* name of task */
|
||||||
2048, /* stack size of task */
|
2048, /* stack size of task */
|
||||||
(void *)1, /* parameter of the task */
|
(void *)1, /* parameter of the task */
|
||||||
3, /* priority of the task */
|
1, /* priority of the task */
|
||||||
&stateMachineTask, /* task handle */
|
&stateMachineTask, /* task handle */
|
||||||
1); /* CPU core */
|
1); /* CPU core */
|
||||||
|
|
||||||
|
@ -314,7 +314,8 @@ void do_ota_update() {
|
|||||||
client.stop();
|
client.stop();
|
||||||
} // do_ota_update
|
} // do_ota_update
|
||||||
|
|
||||||
void display(const uint8_t row, const std::string status, const std::string msg) {
|
void display(const uint8_t row, const std::string status,
|
||||||
|
const std::string msg) {
|
||||||
#ifdef HAS_DISPLAY
|
#ifdef HAS_DISPLAY
|
||||||
u8x8.setCursor(14, row);
|
u8x8.setCursor(14, row);
|
||||||
u8x8.print((status.substr(0, 2)).c_str());
|
u8x8.print((status.substr(0, 2)).c_str());
|
||||||
@ -323,15 +324,17 @@ void display(const uint8_t row, const std::string status, const std::string msg)
|
|||||||
u8x8.setCursor(0, 7);
|
u8x8.setCursor(0, 7);
|
||||||
u8x8.print(msg.substr(0, 16).c_str());
|
u8x8.print(msg.substr(0, 16).c_str());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_DISPLAY
|
||||||
// callback function to show download progress while streaming data
|
// callback function to show download progress while streaming data
|
||||||
void show_progress(size_t current, size_t size) {
|
void show_progress(size_t current, size_t size) {
|
||||||
char buf[17];
|
char buf[17];
|
||||||
snprintf(buf, 17, "%-9lu (%3lu%%)", current, current * 100 / size);
|
snprintf(buf, 17, "%-9lu (%3lu%%)", current, current * 100 / size);
|
||||||
display(4, "**", buf);
|
display(4, "**", buf);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// helper function to compare two versions. Returns 1 if v2 is
|
// helper function to compare two versions. Returns 1 if v2 is
|
||||||
// smaller, -1 if v1 is smaller, 0 if equal
|
// smaller, -1 if v1 is smaller, 0 if equal
|
||||||
|
@ -14,8 +14,11 @@
|
|||||||
void do_ota_update();
|
void do_ota_update();
|
||||||
void start_ota_update();
|
void start_ota_update();
|
||||||
int version_compare(const String v1, const String v2);
|
int version_compare(const String v1, const String v2);
|
||||||
|
void display(const uint8_t row, const std::string status,
|
||||||
|
const std::string msg);
|
||||||
|
#ifdef HAS_DISPLAY
|
||||||
void show_progress(size_t current, size_t size);
|
void show_progress(size_t current, size_t size);
|
||||||
void display(const uint8_t row, const std::string status, const std::string msg);
|
#endif
|
||||||
|
|
||||||
#endif // USE_OTA
|
#endif // USE_OTA
|
||||||
|
|
||||||
|
@ -37,9 +37,9 @@ void SendData(uint8_t port) {
|
|||||||
// interrupt triggered function to prepare payload to send
|
// interrupt triggered function to prepare payload to send
|
||||||
void sendPayload() {
|
void sendPayload() {
|
||||||
|
|
||||||
portENTER_CRITICAL(&timerMux);
|
portENTER_CRITICAL(&mutexSendCycle);
|
||||||
SendCycleTimerIRQ = 0;
|
SendCycleTimerIRQ = 0;
|
||||||
portEXIT_CRITICAL(&timerMux);
|
portEXIT_CRITICAL(&mutexSendCycle);
|
||||||
|
|
||||||
// append counter data to payload
|
// append counter data to payload
|
||||||
payload.reset();
|
payload.reset();
|
||||||
@ -68,9 +68,9 @@ void sendPayload() {
|
|||||||
|
|
||||||
// interrupt handler used for payload send cycle timer
|
// interrupt handler used for payload send cycle timer
|
||||||
void IRAM_ATTR SendCycleIRQ() {
|
void IRAM_ATTR SendCycleIRQ() {
|
||||||
portENTER_CRITICAL(&timerMux);
|
portENTER_CRITICAL(&mutexSendCycle);
|
||||||
SendCycleTimerIRQ++;
|
SendCycleTimerIRQ++;
|
||||||
portEXIT_CRITICAL(&timerMux);
|
portEXIT_CRITICAL(&mutexSendCycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// interrupt triggered function to eat data from send queues and transmit it
|
// interrupt triggered function to eat data from send queues and transmit it
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
void SendData(uint8_t port);
|
void SendData(uint8_t port);
|
||||||
void sendPayload(void);
|
void sendPayload(void);
|
||||||
void SendCycleIRQ(void);
|
void IRAM_ATTR SendCycleIRQ(void);
|
||||||
void checkSendQueues(void);
|
void checkSendQueues(void);
|
||||||
void flushQueues();
|
void flushQueues();
|
||||||
|
|
||||||
|
@ -31,4 +31,5 @@ void stateMachine(void *pvParameters) {
|
|||||||
// give yield to CPU
|
// give yield to CPU
|
||||||
vTaskDelay(2 / portTICK_PERIOD_MS);
|
vTaskDelay(2 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
vTaskDelete(NULL); // shoud never be reached
|
||||||
}
|
}
|
@ -28,8 +28,10 @@ IRAM_ATTR void wifi_sniffer_packet_handler(void *buff,
|
|||||||
void wifi_sniffer_init(void) {
|
void wifi_sniffer_init(void) {
|
||||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||||
cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM
|
cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM
|
||||||
|
cfg.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}; // we need only MGMT frames
|
// .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // only MGMT frames
|
||||||
|
.filter_mask = WIFI_PROMIS_FILTER_MASK_ALL}; // we use all frames
|
||||||
|
|
||||||
// esp_event_loop_init(NULL, NULL);
|
// esp_event_loop_init(NULL, NULL);
|
||||||
// ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
|
// ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
|
||||||
@ -55,14 +57,15 @@ void ChannelSwitchIRQ() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wifi channel rotation task
|
// Wifi channel rotation task
|
||||||
void switchWifiChannel(void * parameter) {
|
void switchWifiChannel(void *parameter) {
|
||||||
while (1) {
|
while (1) {
|
||||||
// task is remaining in block state waiting for channel switch timer interrupt event
|
// task is remaining in block state waiting for channel switch timer
|
||||||
|
// interrupt event
|
||||||
xSemaphoreTake(xWifiChannelSwitchSemaphore, portMAX_DELAY);
|
xSemaphoreTake(xWifiChannelSwitchSemaphore, portMAX_DELAY);
|
||||||
// rotates variable channel 1..WIFI_CHANNEL_MAX
|
// rotates variable channel 1..WIFI_CHANNEL_MAX
|
||||||
channel = (channel % WIFI_CHANNEL_MAX) + 1;
|
channel = (channel % WIFI_CHANNEL_MAX) + 1;
|
||||||
esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
|
esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
|
||||||
ESP_LOGD(TAG, "Wifi set channel %d", channel);
|
ESP_LOGD(TAG, "Wifi set channel %d", channel);
|
||||||
}
|
}
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL); // shoud never be reached
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ typedef struct {
|
|||||||
} wifi_ieee80211_packet_t;
|
} wifi_ieee80211_packet_t;
|
||||||
|
|
||||||
void wifi_sniffer_init(void);
|
void wifi_sniffer_init(void);
|
||||||
void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
|
void IRAM_ATTR wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
|
||||||
void ChannelSwitchIRQ(void);
|
void ChannelSwitchIRQ(void);
|
||||||
void switchWifiChannel(void * parameter);
|
void switchWifiChannel(void * parameter);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user