ESP32-PaxCounter/src/main.cpp

351 lines
11 KiB
C++
Raw Normal View History

2018-06-10 22:46:13 +02:00
/*
//////////////////////// ESP32-Paxcounter \\\\\\\\\\\\\\\\\\\\\\\\\\
2018-06-10 22:46:13 +02:00
Copyright 2018 Oliver Brandmueller <ob@sysadm.in>
Copyright 2018 Klaus Wilting <verkehrsrot@arcor.de>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
NOTICE:
Parts of the source files in this repository are made available under different
licenses. Refer to LICENSE.txt file in repository for more details.
2018-09-22 21:26:11 +02:00
//////////////////////// ESP32-Paxcounter \\\\\\\\\\\\\\\\\\\\\\\\\\
Uused tasks and timers:
Task Core Prio Purpose
====================================================================================
2018-09-27 14:01:23 +02:00
wifiloop 0 4 rotates wifi channels
ledloop 0 3 blinks LEDs
gpsloop 0 2 read data from GPS over serial or i2c
statemachine 0 1 switches application process logic
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer task
looptask 1 1 arduino loop() -> runs the LMIC stack
IDLE 1 0 ESP32 arduino scheduler
2018-09-22 21:26:11 +02:00
ESP32 hardware timers
==========================
0 Display-Refresh
1 Wifi Channel Switch
2 Send Cycle
3 Housekeeping
2018-06-10 22:46:13 +02:00
*/
// Basic Config
2018-07-17 11:53:43 +02:00
#include "main.h"
2018-06-10 22:46:13 +02:00
2018-09-15 18:59:20 +02:00
configData_t cfg; // struct holds current device configuration
2018-07-14 20:07:33 +02:00
char display_line6[16], display_line7[16]; // display buffers
2018-09-23 22:12:10 +02:00
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
2018-07-22 08:41:41 +02:00
// hardware timer for cyclic tasks
hw_timer_t *channelSwitch, *sendCycle, *homeCycle;
2018-06-10 22:46:13 +02:00
2018-07-15 14:28:05 +02:00
// this variables will be changed in the ISR, and read in main loop
2018-09-23 22:12:10 +02:00
uint8_t volatile ButtonPressedIRQ = 0, ChannelTimerIRQ = 0,
SendCycleTimerIRQ = 0, DisplayTimerIRQ = 0, HomeCycleIRQ = 0;
2018-07-15 14:28:05 +02:00
TaskHandle_t stateMachineTask, wifiSwitchTask;
2018-09-27 14:01:23 +02:00
SemaphoreHandle_t xWifiChannelSwitchSemaphore;
2018-08-12 00:17:57 +02:00
2018-08-04 14:37:41 +02:00
// RTos send queues for payload transmit
2018-08-11 19:12:04 +02:00
#ifdef HAS_LORA
QueueHandle_t LoraSendQueue;
#endif
#ifdef HAS_SPI
QueueHandle_t SPISendQueue;
#endif
2018-08-03 23:50:04 +02:00
#ifdef HAS_GPS
TaskHandle_t GpsTask;
#endif
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
TaskHandle_t ledLoopTask;
#endif
2018-08-11 19:12:04 +02:00
std::set<uint16_t> macs; // container holding unique MAC adress hashes
2018-06-10 22:46:13 +02:00
// initialize payload encoder
2018-07-19 22:33:37 +02:00
PayloadConvert payload(PAYLOAD_BUFFER_SIZE);
2018-06-16 19:50:36 +02:00
2018-06-10 22:46:13 +02:00
// local Tag for logging
static const char TAG[] = "main";
void setup() {
2018-06-17 11:40:52 +02:00
// disable the default wifi logging
esp_log_level_set("wifi", ESP_LOG_NONE);
2018-08-02 11:33:02 +02:00
char features[100] = "";
2018-06-10 22:46:13 +02:00
// disable brownout detection
#ifdef DISABLE_BROWNOUT
// register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4
2018-09-23 22:12:10 +02:00
(*((uint32_t volatile *)ETS_UNCACHED_ADDR((DR_REG_RTCCNTL_BASE + 0xd4)))) = 0;
2018-06-10 22:46:13 +02:00
#endif
// setup debug output or silence device
#ifdef VERBOSE
Serial.begin(115200);
esp_log_level_set("*", ESP_LOG_VERBOSE);
#else
// mute logs completely by redirecting them to silence function
esp_log_level_set("*", ESP_LOG_NONE);
esp_log_set_vprintf(redirect_log);
#endif
2018-09-22 21:26:11 +02:00
// read (and initialize on first run) runtime settings from NVRAM
loadConfig(); // includes initialize if necessary
2018-06-10 22:46:13 +02:00
2018-09-22 21:26:11 +02:00
// initialize leds
#if (HAS_LED != NOT_A_PIN)
pinMode(HAS_LED, OUTPUT);
strcat_P(features, " LED");
#endif
#ifdef HAS_RGB_LED
rgb_set_color(COLOR_PINK);
strcat_P(features, " RGB");
#endif
2018-06-10 22:46:13 +02:00
2018-09-22 21:26:11 +02:00
// initialize wifi antenna
#ifdef HAS_ANTENNA_SWITCH
strcat_P(features, " ANT");
antenna_init();
antenna_select(cfg.wifiant);
#endif
2018-06-10 22:46:13 +02:00
2018-09-22 21:26:11 +02:00
// switch off bluetooth, if not compiled
#ifdef BLECOUNTER
strcat_P(features, " BLE");
#else
bool btstop = btStop();
//esp_bt_controller_mem_release(ESP_BT_MODE_BTDM);
2018-06-10 22:46:13 +02:00
#endif
2018-09-22 21:26:11 +02:00
// initialize battery status
#ifdef HAS_BATTERY_PROBE
strcat_P(features, " BATT");
calibrate_voltage();
batt_voltage = read_voltage();
#endif
2018-09-24 16:36:11 +02:00
#ifdef USE_OTA
strcat_P(features, " OTA");
2018-09-22 21:26:11 +02:00
// reboot to firmware update mode if ota trigger switch is set
if (cfg.runmode == 1) {
cfg.runmode = 0;
saveConfig();
start_ota_update();
}
2018-09-24 16:36:11 +02:00
#endif
2018-08-11 19:12:04 +02:00
2018-09-22 21:26:11 +02:00
// initialize button
#ifdef HAS_BUTTON
strcat_P(features, " BTN_");
#ifdef BUTTON_PULLUP
strcat_P(features, "PU");
// install button interrupt (pullup mode)
pinMode(HAS_BUTTON, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING);
#else
strcat_P(features, "PD");
// install button interrupt (pulldown mode)
pinMode(HAS_BUTTON, INPUT_PULLDOWN);
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING);
#endif // BUTTON_PULLUP
#endif // HAS_BUTTON
// initialize gps
#ifdef HAS_GPS
strcat_P(features, " GPS");
2018-08-11 19:12:04 +02:00
#endif
// initialize LoRa
2018-08-03 23:50:04 +02:00
#ifdef HAS_LORA
2018-08-11 19:12:04 +02:00
strcat_P(features, " LORA");
2018-08-04 14:37:41 +02:00
LoraSendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(MessageBuffer_t));
2018-08-03 23:50:04 +02:00
if (LoraSendQueue == 0) {
ESP_LOGE(TAG, "Could not create LORA send queue. Aborting.");
exit(0);
} else
ESP_LOGI(TAG, "LORA send queue created, size %d Bytes",
SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE);
#endif
2018-08-11 19:12:04 +02:00
// initialize SPI
2018-08-03 23:50:04 +02:00
#ifdef HAS_SPI
2018-08-11 19:12:04 +02:00
strcat_P(features, " SPI");
2018-08-04 14:37:41 +02:00
SPISendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(MessageBuffer_t));
2018-08-03 23:50:04 +02:00
if (SPISendQueue == 0) {
ESP_LOGE(TAG, "Could not create SPI send queue. Aborting.");
exit(0);
} else
ESP_LOGI(TAG, "SPI send queue created, size %d Bytes",
SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE);
#endif
2018-09-22 21:26:11 +02:00
#ifdef VENDORFILTER
strcat_P(features, " OUIFLT");
2018-06-10 22:46:13 +02:00
#endif
2018-09-22 21:26:11 +02:00
ESP_LOGI(TAG, "Starting %s v%s", PRODUCTNAME, PROGVERSION);
2018-07-15 14:28:05 +02:00
2018-09-22 21:26:11 +02:00
// print chip information on startup if in verbose mode
#ifdef VERBOSE
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
ESP_LOGI(TAG,
"This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision "
"%d, %dMB %s Flash",
chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "",
chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded"
: "external");
ESP_LOGI(TAG, "ESP32 SDK: %s", ESP.getSdkVersion());
ESP_LOGI(TAG, "Free RAM: %d bytes", ESP.getFreeHeap());
2018-06-10 22:46:13 +02:00
#ifdef HAS_GPS
2018-09-22 21:26:11 +02:00
ESP_LOGI(TAG, "TinyGPS+ v%s", TinyGPSPlus::libraryVersion());
2018-06-10 22:46:13 +02:00
#endif
2018-09-22 21:26:11 +02:00
#endif // verbose
2018-07-22 08:41:41 +02:00
2018-07-23 13:20:06 +02:00
// initialize display
2018-06-10 22:46:13 +02:00
#ifdef HAS_DISPLAY
2018-06-17 11:40:52 +02:00
strcat_P(features, " OLED");
2018-06-10 22:46:13 +02:00
DisplayState = cfg.screenon;
#endif
2018-07-14 23:13:25 +02:00
// setup send cycle trigger IRQ using esp32 hardware timer 2
sendCycle = timerBegin(2, 8000, true);
timerAttachInterrupt(sendCycle, &SendCycleIRQ, true);
timerAlarmWrite(sendCycle, cfg.sendcycle * 2 * 10000, true);
timerAlarmEnable(sendCycle);
2018-07-14 23:13:25 +02:00
2018-07-22 20:27:58 +02:00
// setup house keeping cycle trigger IRQ using esp32 hardware timer 3
homeCycle = timerBegin(3, 8000, true);
timerAttachInterrupt(homeCycle, &homeCycleIRQ, true);
timerAlarmWrite(homeCycle, HOMECYCLE * 10000, true);
timerAlarmEnable(homeCycle);
2018-09-21 12:25:52 +02:00
2018-09-27 14:01:23 +02:00
// setup channel rotation trigger IRQ using esp32 hardware timer 1
xWifiChannelSwitchSemaphore = xSemaphoreCreateBinary();
channelSwitch = timerBegin(1, 800, true);
timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true);
timerAlarmWrite(channelSwitch, cfg.wifichancycle * 1000, true);
2018-09-21 12:25:52 +02:00
timerAlarmEnable(channelSwitch);
2018-07-22 08:41:41 +02:00
2018-06-17 11:40:52 +02:00
// show payload encoder
#if PAYLOAD_ENCODER == 1
2018-08-02 11:33:02 +02:00
strcat_P(features, " PLAIN");
2018-06-17 11:40:52 +02:00
#elif PAYLOAD_ENCODER == 2
2018-08-02 11:33:02 +02:00
strcat_P(features, " PACKED");
2018-06-17 11:40:52 +02:00
#elif PAYLOAD_ENCODER == 3
2018-08-02 11:33:02 +02:00
strcat_P(features, " LPPDYN");
2018-07-22 16:12:46 +02:00
#elif PAYLOAD_ENCODER == 4
2018-08-02 11:33:02 +02:00
strcat_P(features, " LPPPKD");
2018-06-17 11:40:52 +02:00
#endif
2018-06-10 22:46:13 +02:00
// show compiled features
2018-07-23 17:38:33 +02:00
ESP_LOGI(TAG, "Features:%s", features);
2018-06-10 22:46:13 +02:00
2018-07-14 20:07:33 +02:00
#ifdef HAS_LORA
// output LoRaWAN keys to console
2018-06-10 22:46:13 +02:00
#ifdef VERBOSE
2018-08-03 23:50:04 +02:00
showLoraKeys();
2018-06-10 22:46:13 +02:00
#endif
2018-07-15 14:28:05 +02:00
#endif
2018-06-10 22:46:13 +02:00
// start BLE scan callback if BLE function is enabled in NVRAM configuration
#ifdef BLECOUNTER
if (cfg.blescan) {
ESP_LOGI(TAG, "Starting Bluetooth...");
2018-06-10 22:46:13 +02:00
start_BLEscan();
}
#endif
2018-07-15 14:28:05 +02:00
// start wifi in monitor mode and start channel rotation task on core 0
ESP_LOGI(TAG, "Starting Wifi...");
2018-07-15 14:28:05 +02:00
wifi_sniffer_init();
// initialize salt value using esp_random() called by random() in
2018-09-15 18:59:20 +02:00
// arduino-esp32 core. Note: do this *after* wifi has started, since
// function gets it's seed from RF noise
2018-09-23 22:12:10 +02:00
get_salt(); // get new 16bit for salting hashes
2018-06-10 22:46:13 +02:00
#ifdef HAS_GPS
ESP_LOGI(TAG, "Starting GPS...");
xTaskCreatePinnedToCore(gps_loop, /* task function */
"gpsloop", /* name of task */
1024, /* stack size of task */
(void *)1, /* parameter of the task */
2, /* priority of the task */
&GpsTask, /* task handle*/
0); /* CPU core */
#endif
2018-09-27 14:01:23 +02:00
2018-09-21 18:23:34 +02:00
// start state machine
ESP_LOGI(TAG, "Starting Statemachine...");
2018-09-27 14:01:23 +02:00
xTaskCreatePinnedToCore(stateMachine, /* task function */
"stateloop", /* name of task */
2048, /* stack size of task */
(void *)1, /* parameter of the task */
1, /* priority of the task */
2018-09-27 14:01:23 +02:00
&stateMachineTask, /* task handle */
0); /* CPU core */
2018-09-22 13:43:12 +02:00
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
// start led loop
ESP_LOGI(TAG, "Starting LEDloop...");
xTaskCreatePinnedToCore(ledLoop, /* task function */
"ledloop", /* name of task */
1024, /* stack size of task */
(void *)1, /* parameter of the task */
3, /* priority of the task */
&ledLoopTask, /* task handle */
0); /* CPU core */
2018-09-22 13:43:12 +02:00
#endif
// start wifi channel rotation task
ESP_LOGI(TAG, "Starting Wifi Channel rotation...");
xTaskCreatePinnedToCore(switchWifiChannel, /* task function */
"wifiloop", /* name of task */
2048, /* stack size of task */
NULL, /* parameter of the task */
4, /* priority of the task */
&wifiSwitchTask, /* task handle*/
0); /* CPU core */
} // setup()
void loop() {
osjob_t initjob;
// initialize run-time env
os_init();
// setup initial job
os_setCallback(&initjob, initlmic);
// execute scheduled jobs and events
while (1) {
os_runloop_once(); // execute LMIC jobs
vTaskDelay(2 / portTICK_PERIOD_MS); // yield to CPU
}
2018-09-27 14:01:23 +02:00
}