deep code refactoring
This commit is contained in:
		
							parent
							
								
									53fbab8f92
								
							
						
					
					
						commit
						beb7d9aab8
					
				| @ -298,7 +298,7 @@ static const u8x8_display_info_t u8x8_ssd1306_128x64_noname_display_info = | ||||
|   /* sck_pulse_width_ns = */ 50,	/* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */ | ||||
|   /* sck_clock_hz = */ 8000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */ | ||||
|   /* spi_mode = */ 0,		/* active high, rising edge */ | ||||
|   /* i2c_bus_clock_100kHz = */ 1, | ||||
|   /* ==> i2c_bus_clock_100kHz = */ 4, | ||||
|   /* data_setup_time_ns = */ 40, | ||||
|   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */ | ||||
|   /* tile_width = */ 16, | ||||
|  | ||||
| @ -19,24 +19,22 @@ env_default = heltec | ||||
| ;env_default = lopy | ||||
| ;env_default = lopy4 | ||||
| ;env_default = fipy | ||||
| ;env_default = lolin32lite | ||||
| ;env_default = lolin32 | ||||
| ;env_default = lolin32litelora | ||||
| ;env_default = lolin32lora | ||||
| ; | ||||
| description = Paxcounter is a proof-of-concept ESP32 device for metering passenger flows in realtime. It counts how many mobile devices are around. | ||||
| 
 | ||||
| [common_env_data] | ||||
| ;platform_espressif32 = espressif32@1.0.2 | ||||
| platform_espressif32 = espressif32@1.0.2 | ||||
| ;platform_espressif32 = espressif32@1.1.2 | ||||
| platform_espressif32 = https://github.com/platformio/platform-espressif32.git#feature/stage | ||||
| ;platform_espressif32 = https://github.com/platformio/platform-espressif32.git#feature/stage | ||||
| board_build.partitions = no_ota.csv | ||||
| monitor_speed = 115200 | ||||
| upload_speed = 921600 | ||||
| lib_deps_all = | ||||
| lib_deps_display = | ||||
| ;   U8g2@>=2.23.12 | ||||
| ; U8g2 library stored local to tweak i2c display speed down to 100khz | ||||
| ; speed 400khz causes interrupt injection error with espressif32 core v1.1.x | ||||
| ; will be removed again after bug in espressif32 core is solved | ||||
| ; speed, because 400khz causes interrupt injection error with espressif32 core v1.1.x | ||||
| ; will be removed again after bug in espressif32 core v1.1.x is solved | ||||
| lib_deps_rgbled = | ||||
|     SmartLeds@>=1.1.3 | ||||
| lib_deps_gps = | ||||
| @ -88,6 +86,7 @@ platform = ${common_env_data.platform_espressif32} | ||||
| framework = arduino | ||||
| board = esp32dev | ||||
| board_build.partitions = ${common_env_data.board_build.partitions} | ||||
| upload_speed = 921600 | ||||
| monitor_speed = 115200 | ||||
| lib_deps =  | ||||
|     ${common_env_data.lib_deps_all} | ||||
| @ -100,6 +99,7 @@ platform = ${common_env_data.platform_espressif32} | ||||
| framework = arduino | ||||
| board = esp32dev | ||||
| board_build.partitions = ${common_env_data.board_build.partitions} | ||||
| upload_speed = 921600 | ||||
| monitor_speed = 115200 | ||||
| lib_deps =  | ||||
|     ${common_env_data.lib_deps_all} | ||||
| @ -112,6 +112,7 @@ platform = ${common_env_data.platform_espressif32} | ||||
| framework = arduino | ||||
| board = esp32dev | ||||
| board_build.partitions = ${common_env_data.board_build.partitions} | ||||
| upload_speed = 921600 | ||||
| monitor_speed = 115200 | ||||
| lib_deps =  | ||||
|     ${common_env_data.lib_deps_all} | ||||
| @ -124,6 +125,7 @@ platform = ${common_env_data.platform_espressif32} | ||||
| framework = arduino | ||||
| board = esp32dev | ||||
| board_build.partitions = ${common_env_data.board_build.partitions} | ||||
| upload_speed = 921600 | ||||
| monitor_speed = 115200 | ||||
| lib_deps =  | ||||
|     ${common_env_data.lib_deps_all} | ||||
| @ -136,6 +138,7 @@ platform = ${common_env_data.platform_espressif32} | ||||
| framework = arduino | ||||
| board = esp32dev | ||||
| board_build.partitions = ${common_env_data.board_build.partitions} | ||||
| upload_speed = 921600 | ||||
| monitor_speed = 115200 | ||||
| lib_deps =  | ||||
|     ${common_env_data.lib_deps_all} | ||||
| @ -149,6 +152,7 @@ platform = ${common_env_data.platform_espressif32} | ||||
| framework = arduino | ||||
| board = esp32dev | ||||
| board_build.partitions = ${common_env_data.board_build.partitions} | ||||
| upload_speed = 921600 | ||||
| monitor_speed = 115200 | ||||
| lib_deps = | ||||
|     ${common_env_data.lib_deps_all} | ||||
| @ -157,11 +161,12 @@ lib_deps = | ||||
| build_flags = | ||||
|     ${common_env_data.build_flags} | ||||
| 
 | ||||
| [env:lolin32lite] | ||||
| [env:lolin32litelora] | ||||
| platform = ${common_env_data.platform_espressif32} | ||||
| framework = arduino | ||||
| board = lolin32 | ||||
| board_build.partitions = ${common_env_data.board_build.partitions} | ||||
| upload_speed = 921600 | ||||
| monitor_speed = 115200 | ||||
| lib_deps =  | ||||
|     ${common_env_data.lib_deps_all} | ||||
| @ -169,11 +174,12 @@ lib_deps = | ||||
| build_flags = | ||||
|     ${common_env_data.build_flags} | ||||
| 
 | ||||
| [env:lolin32] | ||||
| [env:lolin32lora] | ||||
| platform = ${common_env_data.platform_espressif32} | ||||
| framework = arduino  | ||||
| board = lolin32 | ||||
| board_build.partitions = ${common_env_data.board_build.partitions} | ||||
| upload_speed = 921600 | ||||
| monitor_speed = 115200 | ||||
| lib_deps =  | ||||
|     ${common_env_data.lib_deps_all} | ||||
|  | ||||
							
								
								
									
										7
									
								
								src/antenna.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/antenna.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| #ifndef antenna_H | ||||
| #define antenna_H | ||||
| 
 | ||||
| void antenna_init(void); | ||||
| void antenna_select(const uint8_t _ant); | ||||
| 
 | ||||
| #endif | ||||
| @ -2,12 +2,6 @@ | ||||
| 
 | ||||
| #include "globals.h" | ||||
| 
 | ||||
| #include <driver/adc.h> | ||||
| #include <esp_adc_cal.h> | ||||
| 
 | ||||
| #define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate
 | ||||
| #define NO_OF_SAMPLES 64  // we do multisampling
 | ||||
| 
 | ||||
| // Local logging tag
 | ||||
| static const char TAG[] = "main"; | ||||
| 
 | ||||
							
								
								
									
										12
									
								
								src/battery.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/battery.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| #ifndef battery_H | ||||
| #define battery_H | ||||
| 
 | ||||
| #include <driver/adc.h> | ||||
| #include <esp_adc_cal.h> | ||||
| 
 | ||||
| #define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate
 | ||||
| #define NO_OF_SAMPLES 64  // we do multisampling
 | ||||
| 
 | ||||
| uint16_t read_voltage(void); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										7
									
								
								src/blescan.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/blescan.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| #ifndef BLESCAN_H | ||||
| #define BLESCAN_H | ||||
| 
 | ||||
| void start_BLEscan(void); | ||||
| void stop_BLEscan(void); | ||||
| 
 | ||||
| #endif | ||||
| @ -8,14 +8,8 @@ | ||||
| static const char TAG[] = "flash"; | ||||
| 
 | ||||
| nvs_handle my_handle; | ||||
| 
 | ||||
| esp_err_t err; | ||||
| 
 | ||||
| // defined in antenna.cpp
 | ||||
| #ifdef HAS_ANTENNA_SWITCH | ||||
| void antenna_select(const uint8_t _ant); | ||||
| #endif | ||||
| 
 | ||||
| // populate cfg vars with factory settings
 | ||||
| void defaultConfig() { | ||||
|   cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora sf, see pacounter.conf
 | ||||
| @ -324,7 +318,7 @@ void loadConfig() { | ||||
| 
 | ||||
|     // put actions to be triggered after config loaded here
 | ||||
| 
 | ||||
| #ifdef HAS_ANTENNA_SWITCH // set antenna type, if device has one
 | ||||
| #ifdef HAS_ANTENNA_SWITCH // set antenna type
 | ||||
|     antenna_select(cfg.wifiant); | ||||
| #endif | ||||
|   } | ||||
|  | ||||
							
								
								
									
										158
									
								
								src/display.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								src/display.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,158 @@ | ||||
| #ifdef HAS_DISPLAY | ||||
| 
 | ||||
| // Basic Config
 | ||||
| #include "globals.h" | ||||
| #include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
 | ||||
| 
 | ||||
| HAS_DISPLAY u8x8(OLED_RST, OLED_SCL, OLED_SDA); | ||||
| 
 | ||||
| // helper function, prints a hex key on display
 | ||||
| void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) { | ||||
|   const uint8_t *p; | ||||
|   for (uint8_t i = 0; i < len; i++) { | ||||
|     p = lsb ? key + len - i - 1 : key + i; | ||||
|     u8x8.printf("%02X", *p); | ||||
|   } | ||||
|   u8x8.printf("\n"); | ||||
| } | ||||
| 
 | ||||
| // show startup screen
 | ||||
| void init_display(const char *Productname, const char *Version) { | ||||
|   uint8_t buf[32]; | ||||
|   u8x8.begin(); | ||||
|   u8x8.setFont(u8x8_font_chroma48medium8_r); | ||||
|   u8x8.clear(); | ||||
|   u8x8.setFlipMode(0); | ||||
|   u8x8.setInverseFont(1); | ||||
|   u8x8.draw2x2String(0, 0, Productname); | ||||
|   u8x8.setInverseFont(0); | ||||
|   u8x8.draw2x2String(2, 2, Productname); | ||||
|   delay(1500); | ||||
|   u8x8.clear(); | ||||
|   u8x8.setFlipMode(1); | ||||
|   u8x8.setInverseFont(1); | ||||
|   u8x8.draw2x2String(0, 0, Productname); | ||||
|   u8x8.setInverseFont(0); | ||||
|   u8x8.draw2x2String(2, 2, Productname); | ||||
|   delay(1500); | ||||
| 
 | ||||
|   u8x8.setFlipMode(0); | ||||
|   u8x8.clear(); | ||||
| 
 | ||||
| #ifdef DISPLAY_FLIP | ||||
|   u8x8.setFlipMode(1); | ||||
| #endif | ||||
| 
 | ||||
| // Display chip information
 | ||||
| #ifdef VERBOSE | ||||
|   esp_chip_info_t chip_info; | ||||
|   esp_chip_info(&chip_info); | ||||
|   u8x8.printf("ESP32 %d cores\nWiFi%s%s\n", chip_info.cores, | ||||
|               (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", | ||||
|               (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); | ||||
|   u8x8.printf("ESP Rev.%d\n", chip_info.revision); | ||||
|   u8x8.printf("%dMB %s Flash\n", spi_flash_get_chip_size() / (1024 * 1024), | ||||
|               (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext."); | ||||
| #endif // VERBOSE
 | ||||
| 
 | ||||
|   u8x8.print(Productname); | ||||
|   u8x8.print(" v"); | ||||
|   u8x8.println(PROGVERSION); | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
|   u8x8.println("DEVEUI:"); | ||||
|   os_getDevEui((u1_t *)buf); | ||||
|   DisplayKey(buf, 8, true); | ||||
| #endif // HAS_LORA
 | ||||
| 
 | ||||
|   delay(5000); | ||||
|   u8x8.clear(); | ||||
|   u8x8.setPowerSave(!cfg.screenon); // set display off if disabled
 | ||||
|   u8x8.draw2x2String(0, 0, "PAX:0"); | ||||
| #ifdef BLECOUNTER | ||||
|   u8x8.setCursor(0, 3); | ||||
|   u8x8.printf("BLTH:0"); | ||||
| #endif | ||||
|   u8x8.setCursor(0, 4); | ||||
|   u8x8.printf("WIFI:0"); | ||||
|   u8x8.setCursor(0, 5); | ||||
|   u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit); | ||||
| 
 | ||||
| } // init_display
 | ||||
| 
 | ||||
| void refreshDisplay() { | ||||
| 
 | ||||
|   // set display on/off according to current device configuration
 | ||||
|   if (DisplayState != cfg.screenon) { | ||||
|     DisplayState = cfg.screenon; | ||||
|     u8x8.setPowerSave(!cfg.screenon); | ||||
|   } | ||||
| 
 | ||||
|   // if display is switched off we don't need to refresh it and save time
 | ||||
|   if (!DisplayState) | ||||
|     return; | ||||
| 
 | ||||
|   // update counter (lines 0-1)
 | ||||
|   char buff[16]; | ||||
|   snprintf( | ||||
|       buff, sizeof(buff), "PAX:%-4d", | ||||
|       (int)macs.size()); // convert 16-bit MAC counter to decimal counter value
 | ||||
|   u8x8.draw2x2String(0, 0, | ||||
|                      buff); // display number on unique macs total Wifi + BLE
 | ||||
| 
 | ||||
|   // update GPS status (line 2)
 | ||||
| #ifdef HAS_GPS | ||||
|   u8x8.setCursor(7, 2); | ||||
|   if (!gps.location.isValid()) // if no fix then display Sats value inverse
 | ||||
|   { | ||||
|     u8x8.setInverseFont(1); | ||||
|     u8x8.printf("Sats: %.3d", gps.satellites.value()); | ||||
|     u8x8.setInverseFont(0); | ||||
|   } else | ||||
|     u8x8.printf("Sats: %.3d", gps.satellites.value()); | ||||
| #endif | ||||
| 
 | ||||
|     // update bluetooth counter + LoRa SF (line 3)
 | ||||
| #ifdef BLECOUNTER | ||||
|   u8x8.setCursor(0, 3); | ||||
|   if (cfg.blescan) | ||||
|     u8x8.printf("BLTH:%-4d", macs_ble); | ||||
|   else | ||||
|     u8x8.printf("%s", "BLTH:off"); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef 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]); | ||||
|   if (cfg.adrmode) // switch off inverse if it was turned on
 | ||||
|     u8x8.setInverseFont(0); | ||||
| #endif // HAS_LORA
 | ||||
| 
 | ||||
|   // update wifi counter + channel display (line 4)
 | ||||
|   u8x8.setCursor(0, 4); | ||||
|   u8x8.printf("WIFI:%-4d", macs_wifi); | ||||
|   u8x8.setCursor(11, 4); | ||||
|   u8x8.printf("ch:%02d", channel); | ||||
| 
 | ||||
|   // update RSSI limiter status & free memory display (line 5)
 | ||||
|   u8x8.setCursor(0, 5); | ||||
|   u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); | ||||
|   u8x8.setCursor(10, 5); | ||||
|   u8x8.printf("%4dKB", ESP.getFreeHeap() / 1024); | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
|   // update LoRa status display (line 6)
 | ||||
|   u8x8.setCursor(0, 6); | ||||
|   u8x8.printf("%-16s", display_line6); | ||||
| 
 | ||||
|   // update LMiC event display (line 7)
 | ||||
|   u8x8.setCursor(0, 7); | ||||
|   u8x8.printf("%-16s", display_line7); | ||||
| #endif // HAS_LORA
 | ||||
| } // refreshDisplay()
 | ||||
| 
 | ||||
| #endif // HAS_DISPLAY
 | ||||
							
								
								
									
										10
									
								
								src/display.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/display.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| #ifndef DISPLAY_H | ||||
| #define DISPLAY_H | ||||
| 
 | ||||
| #include <U8x8lib.h> | ||||
| 
 | ||||
| void init_display(const char *Productname, const char *Version); | ||||
| void refreshDisplay(void); | ||||
| void DisplayKey(const uint8_t *key, uint8_t len, bool lsb); | ||||
| 
 | ||||
| #endif | ||||
| @ -6,39 +6,27 @@ | ||||
| #include <array> | ||||
| #include <algorithm> | ||||
| 
 | ||||
| // OLED Display
 | ||||
| #ifdef HAS_DISPLAY | ||||
| #include <U8x8lib.h> | ||||
| #endif | ||||
| 
 | ||||
| // GPS
 | ||||
| #ifdef HAS_GPS | ||||
| #include <TinyGPS++.h> | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
| // LMIC-Arduino LoRaWAN Stack
 | ||||
| #include <lmic.h> | ||||
| #include <hal/hal.h> | ||||
| #endif | ||||
| 
 | ||||
| // LED controls
 | ||||
| #ifdef HAS_RGB_LED | ||||
| #include <SmartLeds.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "rgb_led.h" | ||||
| #include "macsniff.h" | ||||
| // basics
 | ||||
| #include "main.h" | ||||
| #include "led.h" | ||||
| #include "macsniff.h" | ||||
| #include "payload.h" | ||||
| 
 | ||||
| extern configData_t cfg; | ||||
| extern char display_line6[], display_line7[]; | ||||
| extern uint64_t uptimecounter; | ||||
| extern int countermode, screensaver, adrmode, lorasf, txpower, rlim; | ||||
| extern uint8_t channel, DisplayState; | ||||
| extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters
 | ||||
| extern uint64_t uptimecounter; | ||||
| extern std::set<uint16_t> macs; | ||||
| extern hw_timer_t *channelSwitch, *sendCycle; | ||||
| extern portMUX_TYPE timerMux; | ||||
| 
 | ||||
| #if defined(CFG_eu868) | ||||
| const char lora_datarate[] = {"1211100908077BFSNA"}; | ||||
| #elif defined(CFG_us915) | ||||
| const char lora_datarate[] = {"100908078CNA121110090807"}; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_GPS | ||||
| extern gpsStatus_t gps_status; // struct for storing gps data
 | ||||
|  | ||||
							
								
								
									
										9
									
								
								src/gps.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/gps.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| #ifndef gps_H | ||||
| #define gps_H | ||||
| 
 | ||||
| #include <TinyGPS++.h> | ||||
| 
 | ||||
| void gps_read(void); | ||||
| void gps_loop(void *pvParameters); | ||||
| 
 | ||||
| #endif | ||||
| @ -1,4 +1,4 @@ | ||||
| // Hardware related definitions for lolin32 lite loraNode32 shield
 | ||||
| // Hardware related definitions for lolin32 lite with loraNode32 shield
 | ||||
| // See https://github.com/hallard/LoLin32-Lite-Lora
 | ||||
| 
 | ||||
| // disable brownout detection (avoid unexpected reset on some boards)
 | ||||
| @ -1,4 +1,4 @@ | ||||
| // Hardware related definitions for lolin32 loraNode32 shield
 | ||||
| // Hardware related definitions for lolin32 with loraNode32 shield
 | ||||
| // See https://github.com/hallard/LoLin32-Lora
 | ||||
| 
 | ||||
| // disable brownout detection (avoid unexpected reset on some boards)
 | ||||
| @ -15,7 +15,7 @@ | ||||
| #define RST   LMIC_UNUSED_PIN | ||||
| #define DIO0  GPIO_NUM_23 // LoRa IRQ
 | ||||
| #define DIO1  GPIO_NUM_23 // Pin tied via diode to DIO0
 | ||||
| #define DIO1  GPIO_NUM_23 // Pin tied via diode to DIO0
 | ||||
| #define DIO2  GPIO_NUM_23 // Pin tied via diode to DIO0
 | ||||
| 
 | ||||
| // select WIFI antenna (internal = onboard / external = u.fl socket)
 | ||||
| #define HAS_ANTENNA_SWITCH  21      // pin for switching wifi antenna
 | ||||
|  | ||||
							
								
								
									
										6
									
								
								src/hash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/hash.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| #ifndef hash_H | ||||
| #define hash_H | ||||
| 
 | ||||
| uint32_t rokkit(const char *data, int len); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										161
									
								
								src/led.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/led.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,161 @@ | ||||
| // Basic Config
 | ||||
| #include "globals.h" | ||||
| 
 | ||||
| led_states LEDState = LED_OFF; // LED state global for state machine
 | ||||
| led_states previousLEDState = | ||||
|     LED_ON; // This will force LED to be off at boot since State is OFF
 | ||||
| 
 | ||||
| uint16_t LEDColor = COLOR_NONE, LEDBlinkDuration = 0; // state machine variables
 | ||||
| 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); | ||||
| 
 | ||||
| float rgb_CalcColor(float p, float q, float t) { | ||||
|   if (t < 0.0f) | ||||
|     t += 1.0f; | ||||
|   if (t > 1.0f) | ||||
|     t -= 1.0f; | ||||
| 
 | ||||
|   if (t < 1.0f / 6.0f) | ||||
|     return p + (q - p) * 6.0f * t; | ||||
| 
 | ||||
|   if (t < 0.5f) | ||||
|     return q; | ||||
| 
 | ||||
|   if (t < 2.0f / 3.0f) | ||||
|     return p + ((q - p) * (2.0f / 3.0f - t) * 6.0f); | ||||
| 
 | ||||
|   return p; | ||||
| } | ||||
| 
 | ||||
| // ------------------------------------------------------------------------
 | ||||
| // Hue, Saturation, Lightness color members
 | ||||
| // HslColor using H, S, L values (0.0 - 1.0)
 | ||||
| // L should be limited to between (0.0 - 0.5)
 | ||||
| // ------------------------------------------------------------------------
 | ||||
| RGBColor rgb_hsl2rgb(float h, float s, float l) { | ||||
|   RGBColor RGB_color; | ||||
|   float r; | ||||
|   float g; | ||||
|   float b; | ||||
| 
 | ||||
|   if (s == 0.0f || l == 0.0f) { | ||||
|     r = g = b = l; // achromatic or black
 | ||||
|   } else { | ||||
|     float q = l < 0.5f ? l * (1.0f + s) : l + s - (l * s); | ||||
|     float p = 2.0f * l - q; | ||||
|     r = rgb_CalcColor(p, q, h + 1.0f / 3.0f); | ||||
|     g = rgb_CalcColor(p, q, h); | ||||
|     b = rgb_CalcColor(p, q, h - 1.0f / 3.0f); | ||||
|   } | ||||
| 
 | ||||
|   RGB_color.R = (uint8_t)(r * 255.0f); | ||||
|   RGB_color.G = (uint8_t)(g * 255.0f); | ||||
|   RGB_color.B = (uint8_t)(b * 255.0f); | ||||
| 
 | ||||
|   return RGB_color; | ||||
| } | ||||
| 
 | ||||
| void rgb_set_color(uint16_t hue) { | ||||
|   if (hue == COLOR_NONE) { | ||||
|     // Off
 | ||||
|     rgb_led[0] = Rgb(0, 0, 0); | ||||
|   } else { | ||||
|     // see http://www.workwithcolor.com/blue-color-hue-range-01.htm
 | ||||
|     // H (is color from 0..360) should be between 0.0 and 1.0
 | ||||
|     // S is saturation keep it to 1
 | ||||
|     // L is brightness should be between 0.0 and 0.5
 | ||||
|     // cfg.rgblum is between 0 and 100 (percent)
 | ||||
|     RGBColor target = rgb_hsl2rgb(hue / 360.0f, 1.0f, 0.005f * cfg.rgblum); | ||||
|     // uint32_t color = target.R<<16 | target.G<<8 | target.B;
 | ||||
|     rgb_led[0] = Rgb(target.R, target.G, target.B); | ||||
|   } | ||||
|   // Show
 | ||||
|   rgb_led.show(); | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| // No RGB LED empty functions
 | ||||
| void rgb_set_color(uint16_t hue) {} | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED) | ||||
| 
 | ||||
| void blink_LED(uint16_t set_color, uint16_t set_blinkduration) { | ||||
|   LEDColor = set_color;                 // set color for RGB LED
 | ||||
|   LEDBlinkDuration = set_blinkduration; // duration
 | ||||
|   LEDBlinkStarted = millis();           // Time Start here
 | ||||
|   LEDState = LED_ON;                    // Let main set LED on
 | ||||
| } | ||||
| 
 | ||||
| void led_loop() { | ||||
|   // Custom blink running always have priority other LoRaWAN led management
 | ||||
|   if (LEDBlinkStarted && LEDBlinkDuration) { | ||||
|     // Custom blink is finished, let this order, avoid millis() overflow
 | ||||
|     if ((millis() - LEDBlinkStarted) >= LEDBlinkDuration) { | ||||
|       // Led becomes off, and stop blink
 | ||||
|       LEDState = LED_OFF; | ||||
|       LEDBlinkStarted = 0; | ||||
|       LEDBlinkDuration = 0; | ||||
|       LEDColor = COLOR_NONE; | ||||
|     } else { | ||||
|       // In case of LoRaWAN led management blinked off
 | ||||
|       LEDState = LED_ON; | ||||
|     } | ||||
|     // No custom blink, check LoRaWAN state
 | ||||
|   } else { | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
|     // LED indicators for viusalizing LoRaWAN state
 | ||||
|     if (LMIC.opmode & (OP_JOINING | OP_REJOIN)) { | ||||
|       LEDColor = COLOR_YELLOW; | ||||
|       // quick blink 20ms on each 1/5 second
 | ||||
|       LEDState = ((millis() % 200) < 20) ? LED_ON : LED_OFF; // TX data pending
 | ||||
|     } else if (LMIC.opmode & (OP_TXDATA | OP_TXRXPEND)) { | ||||
|       LEDColor = COLOR_BLUE; | ||||
|       // small blink 10ms on each 1/2sec (not when joining)
 | ||||
|       LEDState = ((millis() % 500) < 10) ? LED_ON : LED_OFF; | ||||
|       // This should not happen so indicate a problem
 | ||||
|     } else if (LMIC.opmode & | ||||
|                ((OP_TXDATA | OP_TXRXPEND | OP_JOINING | OP_REJOIN) == 0)) { | ||||
|       LEDColor = COLOR_RED; | ||||
|       // heartbeat long blink 200ms on each 2 seconds
 | ||||
|       LEDState = ((millis() % 2000) < 200) ? LED_ON : LED_OFF; | ||||
|     } else | ||||
| #endif // HAS_LORA
 | ||||
|     { | ||||
|       // led off
 | ||||
|       LEDColor = COLOR_NONE; | ||||
|       LEDState = LED_OFF; | ||||
|     } | ||||
|   } | ||||
|   // led need to change state? avoid digitalWrite() for nothing
 | ||||
|   if (LEDState != previousLEDState) { | ||||
|     if (LEDState == LED_ON) { | ||||
|       rgb_set_color(LEDColor); | ||||
| 
 | ||||
| #ifdef LED_ACTIVE_LOW | ||||
|       digitalWrite(HAS_LED, LOW); | ||||
| #else | ||||
|       digitalWrite(HAS_LED, HIGH); | ||||
| #endif | ||||
| 
 | ||||
|     } else { | ||||
|       rgb_set_color(COLOR_NONE); | ||||
| 
 | ||||
| #ifdef LED_ACTIVE_LOW | ||||
|       digitalWrite(HAS_LED, HIGH); | ||||
| #else | ||||
|       digitalWrite(HAS_LED, LOW); | ||||
| #endif | ||||
|     } | ||||
|     previousLEDState = LEDState; | ||||
|   } | ||||
| }; // led_loop()
 | ||||
| 
 | ||||
| #endif // #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
 | ||||
| @ -1,5 +1,9 @@ | ||||
| 
 | ||||
| #pragma once | ||||
| //#pragma once
 | ||||
| 
 | ||||
| #ifdef HAS_RGB_LED | ||||
| #include <SmartLeds.h> | ||||
| #endif | ||||
| 
 | ||||
| // value for HSL color
 | ||||
| // see http://www.workwithcolor.com/blue-color-hue-range-01.htm
 | ||||
| @ -25,5 +29,9 @@ struct RGBColor { | ||||
|   uint8_t B; | ||||
| }; | ||||
| 
 | ||||
| enum led_states { LED_OFF, LED_ON }; | ||||
| 
 | ||||
| // Exported Functions
 | ||||
| void rgb_set_color(uint16_t hue); | ||||
| void blink_LED(uint16_t set_color, uint16_t set_blinkduration); | ||||
| void led_loop(); | ||||
| @ -2,11 +2,7 @@ | ||||
| 
 | ||||
| // Basic Config
 | ||||
| #include "globals.h" | ||||
| 
 | ||||
| // LMIC-Arduino LoRaWAN Stack
 | ||||
| #include "loraconf.h" | ||||
| #include <lmic.h> | ||||
| #include <hal/hal.h> | ||||
| #include "rcommand.h" | ||||
| 
 | ||||
| #ifdef MCP_24AA02E64_I2C_ADDRESS | ||||
| #include <Wire.h> // Needed for 24AA02E64, does not hurt anything if included and not used
 | ||||
| @ -15,10 +11,6 @@ | ||||
| // Local logging Tag
 | ||||
| static const char TAG[] = "lora"; | ||||
| 
 | ||||
| // functions defined in rcommand.cpp
 | ||||
| void rcommand(uint8_t cmd, uint8_t arg); | ||||
| void switch_lora(uint8_t sf, uint8_t tx); | ||||
| 
 | ||||
| // DevEUI generator using devices's MAC address
 | ||||
| void gen_lora_deveui(uint8_t *pdeveui) { | ||||
|   uint8_t *p = pdeveui, dmac[6]; | ||||
| @ -46,6 +38,33 @@ void RevBytes(unsigned char *b, size_t c) { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // LMIC callback functions
 | ||||
| void os_getDevKey(u1_t *buf) { memcpy(buf, APPKEY, 16); } | ||||
| 
 | ||||
| void os_getArtEui(u1_t *buf) { | ||||
|   memcpy(buf, APPEUI, 8); | ||||
|   RevBytes(buf, 8); // TTN requires it in LSB First order, so we swap bytes
 | ||||
| } | ||||
| 
 | ||||
| void os_getDevEui(u1_t *buf) { | ||||
|   int i = 0, k = 0; | ||||
|   memcpy(buf, DEVEUI, 8); // get fixed DEVEUI from loraconf.h
 | ||||
|   for (i = 0; i < 8; i++) { | ||||
|     k += buf[i]; | ||||
|   } | ||||
|   if (k) { | ||||
|     RevBytes(buf, 8); // use fixed DEVEUI and swap bytes to LSB format
 | ||||
|   } else { | ||||
|     gen_lora_deveui(buf); // generate DEVEUI from device's MAC
 | ||||
|   } | ||||
| 
 | ||||
| // Get MCP 24AA02E64 hardware DEVEUI (override default settings if found)
 | ||||
| #ifdef MCP_24AA02E64_I2C_ADDRESS | ||||
|   get_hard_deveui(buf); | ||||
|   RevBytes(buf, 8); // swap bytes to LSB format
 | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void get_hard_deveui(uint8_t *pdeveui) { | ||||
|   // read DEVEUI from Microchip 24AA02E64 2Kb serial eeprom if present
 | ||||
| #ifdef MCP_24AA02E64_I2C_ADDRESS | ||||
|  | ||||
| @ -1,13 +1,17 @@ | ||||
| #ifdef HAS_LORA | ||||
| 
 | ||||
| #ifndef LORAWAN_H | ||||
| #define LORAWAN_H | ||||
| 
 | ||||
| // LMIC-Arduino LoRaWAN Stack
 | ||||
| #include <lmic.h> | ||||
| #include <hal/hal.h> | ||||
| #include "loraconf.h" | ||||
| 
 | ||||
| void onEvent(ev_t ev); | ||||
| void gen_lora_deveui(uint8_t *pdeveui); | ||||
| void RevBytes(unsigned char *b, size_t c); | ||||
| void get_hard_deveui(uint8_t *pdeveui); | ||||
| void os_getDevKey(u1_t *buf); | ||||
| void os_getArtEui(u1_t *buf); | ||||
| void os_getDevEui(u1_t *buf); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #endif // HAS_LORA
 | ||||
| @ -9,9 +9,14 @@ | ||||
| // Local logging tag
 | ||||
| static const char TAG[] = "wifi"; | ||||
| 
 | ||||
| /* change for future Espressif v1.1.x
 | ||||
| static wifi_country_t wifi_country = {WIFI_MY_COUNTRY, WIFI_CHANNEL_MIN, | ||||
|                                       WIFI_CHANNEL_MAX, 0, | ||||
|                                       WIFI_COUNTRY_POLICY_MANUAL}; | ||||
| */ | ||||
| 
 | ||||
| static wifi_country_t wifi_country = {WIFI_MY_COUNTRY, WIFI_CHANNEL_MIN, | ||||
|                                       WIFI_CHANNEL_MAX, WIFI_COUNTRY_POLICY_MANUAL}; | ||||
| 
 | ||||
| // globals
 | ||||
| uint16_t salt; | ||||
|  | ||||
| @ -4,6 +4,8 @@ | ||||
| // ESP32 Functions
 | ||||
| #include <esp_wifi.h> | ||||
| 
 | ||||
| #include "hash.h" | ||||
| 
 | ||||
| #define MAC_SNIFF_WIFI 0 | ||||
| #define MAC_SNIFF_BLE 1 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										461
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										461
									
								
								src/main.cpp
									
									
									
									
									
								
							| @ -25,21 +25,6 @@ licenses. Refer to LICENSE.txt file in repository for more details. | ||||
| // Basic Config
 | ||||
| #include "globals.h" | ||||
| 
 | ||||
| // Does nothing and avoid any compilation error with I2C
 | ||||
| #include <Wire.h> | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
| // LMIC-Arduino LoRaWAN Stack
 | ||||
| #include "loraconf.h" | ||||
| #include <hal/hal.h> | ||||
| #include <lmic.h> | ||||
| #endif | ||||
| 
 | ||||
| // ESP32 lib Functions
 | ||||
| #include <esp32-hal-log.h>  // needed for ESP_LOGx on arduino framework
 | ||||
| #include <esp_event_loop.h> // needed for Wifi event handler
 | ||||
| #include <esp_spi_flash.h>  // needed for reading ESP32 chip attributes
 | ||||
| 
 | ||||
| // Initialize global variables
 | ||||
| configData_t cfg; // struct holds current device configuration
 | ||||
| char display_line6[16], display_line7[16]; // display buffers
 | ||||
| @ -48,12 +33,6 @@ uint8_t DisplayState = 0;                  // globals for state machine | ||||
| uint16_t macs_total = 0, macs_wifi = 0, | ||||
|          macs_ble = 0; // MAC counters globals for display
 | ||||
| uint8_t channel = 0;   // wifi channel rotation counter global for display
 | ||||
| led_states LEDState = LED_OFF; // LED state global for state machine
 | ||||
| led_states previousLEDState = | ||||
|     LED_ON; // This will force LED to be off at boot since State is OFF
 | ||||
| unsigned long LEDBlinkStarted = 0; // When (in millis() led blink started)
 | ||||
| uint16_t LEDBlinkDuration = 0;     // How long the blink need to be
 | ||||
| uint16_t LEDColor = COLOR_NONE; // state machine variable to set RGB LED color
 | ||||
| hw_timer_t *channelSwitch = NULL, *displaytimer = NULL, | ||||
|            *sendCycle = NULL; // configure hardware timer for cyclic tasks
 | ||||
| 
 | ||||
| @ -62,6 +41,10 @@ gpsStatus_t gps_status; // struct for storing gps data | ||||
| TinyGPSPlus gps;        // create TinyGPS++ instance
 | ||||
| #endif | ||||
| 
 | ||||
| // this variables will be changed in the ISR, and read in main loop
 | ||||
| static volatile int ButtonPressedIRQ = 0, ChannelTimerIRQ = 0, | ||||
|                     SendCycleTimerIRQ = 0, DisplayTimerIRQ = 0; | ||||
| 
 | ||||
| portMUX_TYPE timerMux = | ||||
|     portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying IRQ
 | ||||
|                                   // handler shared variables
 | ||||
| @ -80,10 +63,6 @@ CayenneLPP payload(PAYLOAD_BUFFER_SIZE); | ||||
| #error "No valid payload converter defined" | ||||
| #endif | ||||
| 
 | ||||
| // this variables will be changed in the ISR, and read in main loop
 | ||||
| static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0, | ||||
|                     ChannelTimerIRQ = 0, SendCycleTimerIRQ = 0; | ||||
| 
 | ||||
| // local Tag for logging
 | ||||
| static const char TAG[] = "main"; | ||||
| 
 | ||||
| @ -106,37 +85,6 @@ void reset_counters() { | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
| 
 | ||||
| #ifdef VERBOSE | ||||
| void printKeys(void); | ||||
| #endif // VERBOSE
 | ||||
| 
 | ||||
| // LMIC callback functions
 | ||||
| void os_getDevKey(u1_t *buf) { memcpy(buf, APPKEY, 16); } | ||||
| 
 | ||||
| void os_getArtEui(u1_t *buf) { | ||||
|   memcpy(buf, APPEUI, 8); | ||||
|   RevBytes(buf, 8); // TTN requires it in LSB First order, so we swap bytes
 | ||||
| } | ||||
| 
 | ||||
| void os_getDevEui(u1_t *buf) { | ||||
|   int i = 0, k = 0; | ||||
|   memcpy(buf, DEVEUI, 8); // get fixed DEVEUI from loraconf.h
 | ||||
|   for (i = 0; i < 8; i++) { | ||||
|     k += buf[i]; | ||||
|   } | ||||
|   if (k) { | ||||
|     RevBytes(buf, 8); // use fixed DEVEUI and swap bytes to LSB format
 | ||||
|   } else { | ||||
|     gen_lora_deveui(buf); // generate DEVEUI from device's MAC
 | ||||
|   } | ||||
| 
 | ||||
| // Get MCP 24AA02E64 hardware DEVEUI (override default settings if found)
 | ||||
| #ifdef MCP_24AA02E64_I2C_ADDRESS | ||||
|   get_hard_deveui(buf); | ||||
|   RevBytes(buf, 8); // swap bytes to LSB format
 | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // LMIC enhanced Pin mapping
 | ||||
| const lmic_pinmap lmic_pins = {.mosi = PIN_SPI_MOSI, | ||||
|                                .miso = PIN_SPI_MISO, | ||||
| @ -146,6 +94,16 @@ const lmic_pinmap lmic_pins = {.mosi = PIN_SPI_MOSI, | ||||
|                                .rst = RST, | ||||
|                                .dio = {DIO0, DIO1, DIO2}}; | ||||
| 
 | ||||
| #ifdef VERBOSE | ||||
| void printKeys(void); | ||||
| #endif // VERBOSE
 | ||||
| 
 | ||||
| // Get MCP 24AA02E64 hardware DEVEUI (override default settings if found)
 | ||||
| #ifdef MCP_24AA02E64_I2C_ADDRESS | ||||
| get_hard_deveui(buf); | ||||
| RevBytes(buf, 8); // swap bytes to LSB format
 | ||||
| #endif | ||||
| 
 | ||||
| // LMIC FreeRTos Task
 | ||||
| void lorawan_loop(void *pvParameters) { | ||||
| 
 | ||||
| @ -165,56 +123,62 @@ void lorawan_loop(void *pvParameters) { | ||||
| /* beginn hardware specific parts
 | ||||
|  * -------------------------------------------------------- */ | ||||
| 
 | ||||
| #ifdef HAS_DISPLAY | ||||
| 
 | ||||
| HAS_DISPLAY u8x8(OLED_RST, OLED_SCL, OLED_SDA); | ||||
| 
 | ||||
| // Display Refresh IRQ
 | ||||
| void IRAM_ATTR DisplayIRQ() { | ||||
|   portENTER_CRITICAL_ISR(&timerMux); | ||||
|   DisplayTimerIRQ++; | ||||
|   portEXIT_CRITICAL_ISR(&timerMux); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_ANTENNA_SWITCH | ||||
| // defined in antenna.cpp
 | ||||
| void antenna_init(); | ||||
| void antenna_select(const uint8_t _ant); | ||||
| #endif | ||||
| 
 | ||||
| #ifndef BLECOUNTER | ||||
| bool btstop = btStop(); | ||||
| #endif | ||||
| 
 | ||||
| // Button IRQ Handler Routine, IRAM_ATTR necessary here, see
 | ||||
| // Setup IRQ handler routines for button, channel rotation, send cycle´, display
 | ||||
| // attention, enable cache:
 | ||||
| // https://github.com/espressif/arduino-esp32/issues/855
 | ||||
| #ifdef HAS_BUTTON | ||||
| void IRAM_ATTR ButtonIRQ() { ButtonPressedIRQ++; } | ||||
| #endif | ||||
| 
 | ||||
| // Wifi Channel Rotation Timer IRQ Handler Routine
 | ||||
| void IRAM_ATTR ChannelSwitchIRQ() { | ||||
|   portENTER_CRITICAL(&timerMux); | ||||
|   ChannelTimerIRQ++; | ||||
|   portEXIT_CRITICAL(&timerMux); | ||||
| } | ||||
| 
 | ||||
| // Send Cycle Timer IRQ Handler Routine
 | ||||
| void IRAM_ATTR SendCycleIRQ() { | ||||
|   portENTER_CRITICAL(&timerMux); | ||||
|   SendCycleTimerIRQ++; | ||||
|   portEXIT_CRITICAL(&timerMux); | ||||
| } | ||||
| 
 | ||||
| #ifdef HAS_DISPLAY | ||||
| void IRAM_ATTR DisplayIRQ() { | ||||
|   portENTER_CRITICAL_ISR(&timerMux); | ||||
|   DisplayTimerIRQ++; | ||||
|   portEXIT_CRITICAL_ISR(&timerMux); | ||||
| } | ||||
| 
 | ||||
| void updateDisplay() { | ||||
|   // refresh display according to refresh cycle setting
 | ||||
|   if (DisplayTimerIRQ) { | ||||
|     portENTER_CRITICAL(&timerMux); | ||||
|     DisplayTimerIRQ = 0; | ||||
|     portEXIT_CRITICAL(&timerMux); | ||||
|     refreshDisplay(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_BUTTON | ||||
| void IRAM_ATTR ButtonIRQ() { ButtonPressedIRQ++; } | ||||
| 
 | ||||
| void readButton() { | ||||
|   if (ButtonPressedIRQ) { | ||||
|     portENTER_CRITICAL(&timerMux); | ||||
|     ButtonPressedIRQ = 0; | ||||
|     portEXIT_CRITICAL(&timerMux); | ||||
|     ESP_LOGI(TAG, "Button pressed"); | ||||
|     ESP_LOGI(TAG, "Button pressed, resetting device to factory defaults"); | ||||
|     eraseConfig(); | ||||
|     esp_restart(); | ||||
|   } | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /* end hardware specific parts
 | ||||
|  * -------------------------------------------------------- */ | ||||
| 
 | ||||
| /* begin wifi specific parts
 | ||||
|  * ---------------------------------------------------------- */ | ||||
| 
 | ||||
| // Sniffer Task
 | ||||
| void sniffer_loop(void *pvParameters) { | ||||
| // Wifi channel rotation task
 | ||||
| void wifi_channel_loop(void *pvParameters) { | ||||
| 
 | ||||
|   configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
 | ||||
| 
 | ||||
| @ -235,9 +199,6 @@ void sniffer_loop(void *pvParameters) { | ||||
|   } // end of infinite wifi channel rotation loop
 | ||||
| } | ||||
| 
 | ||||
| /* end wifi specific parts
 | ||||
|  * ------------------------------------------------------------ */ | ||||
| 
 | ||||
| // uptime counter 64bit to prevent millis() rollover after 49 days
 | ||||
| uint64_t uptime() { | ||||
|   static uint32_t low32, high32; | ||||
| @ -248,245 +209,7 @@ uint64_t uptime() { | ||||
|   return (uint64_t)high32 << 32 | low32; | ||||
| } | ||||
| 
 | ||||
| #ifdef HAS_DISPLAY | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
| // Print a key on display
 | ||||
| void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) { | ||||
|   const uint8_t *p; | ||||
|   for (uint8_t i = 0; i < len; i++) { | ||||
|     p = lsb ? key + len - i - 1 : key + i; | ||||
|     u8x8.printf("%02X", *p); | ||||
|   } | ||||
|   u8x8.printf("\n"); | ||||
| } | ||||
| #endif // HAS_LORA
 | ||||
| 
 | ||||
| void init_display(const char *Productname, const char *Version) { | ||||
|   uint8_t buf[32]; | ||||
|   u8x8.begin(); | ||||
|   u8x8.setFont(u8x8_font_chroma48medium8_r); | ||||
|   u8x8.clear(); | ||||
|   u8x8.setFlipMode(0); | ||||
|   u8x8.setInverseFont(1); | ||||
|   u8x8.draw2x2String(0, 0, Productname); | ||||
|   u8x8.setInverseFont(0); | ||||
|   u8x8.draw2x2String(2, 2, Productname); | ||||
|   delay(1500); | ||||
|   u8x8.clear(); | ||||
|   u8x8.setFlipMode(1); | ||||
|   u8x8.setInverseFont(1); | ||||
|   u8x8.draw2x2String(0, 0, Productname); | ||||
|   u8x8.setInverseFont(0); | ||||
|   u8x8.draw2x2String(2, 2, Productname); | ||||
|   delay(1500); | ||||
| 
 | ||||
|   u8x8.setFlipMode(0); | ||||
|   u8x8.clear(); | ||||
| 
 | ||||
| #ifdef DISPLAY_FLIP | ||||
|   u8x8.setFlipMode(1); | ||||
| #endif | ||||
| 
 | ||||
| // Display chip information
 | ||||
| #ifdef VERBOSE | ||||
|   esp_chip_info_t chip_info; | ||||
|   esp_chip_info(&chip_info); | ||||
|   u8x8.printf("ESP32 %d cores\nWiFi%s%s\n", chip_info.cores, | ||||
|               (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", | ||||
|               (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); | ||||
|   u8x8.printf("ESP Rev.%d\n", chip_info.revision); | ||||
|   u8x8.printf("%dMB %s Flash\n", spi_flash_get_chip_size() / (1024 * 1024), | ||||
|               (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext."); | ||||
| #endif // VERBOSE
 | ||||
| 
 | ||||
|   u8x8.print(Productname); | ||||
|   u8x8.print(" v"); | ||||
|   u8x8.println(PROGVERSION); | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
|   u8x8.println("DEVEUI:"); | ||||
|   os_getDevEui((u1_t *)buf); | ||||
|   DisplayKey(buf, 8, true); | ||||
| #endif // HAS_LORA
 | ||||
| 
 | ||||
|   delay(5000); | ||||
|   u8x8.clear(); | ||||
| } | ||||
| 
 | ||||
| void refreshDisplay() { | ||||
|   // update counter (lines 0-1)
 | ||||
|   char buff[16]; | ||||
|   snprintf( | ||||
|       buff, sizeof(buff), "PAX:%-4d", | ||||
|       (int)macs.size()); // convert 16-bit MAC counter to decimal counter value
 | ||||
|   u8x8.draw2x2String(0, 0, | ||||
|                      buff); // display number on unique macs total Wifi + BLE
 | ||||
| 
 | ||||
|   // update GPS status (line 2)
 | ||||
| #ifdef HAS_GPS | ||||
|   u8x8.setCursor(7, 2); | ||||
|   if (!gps.location.isValid()) // if no fix then display Sats value inverse
 | ||||
|   { | ||||
|     u8x8.setInverseFont(1); | ||||
|     u8x8.printf("Sats: %.3d", gps.satellites.value()); | ||||
|     u8x8.setInverseFont(0); | ||||
|   } else | ||||
|     u8x8.printf("Sats: %.3d", gps.satellites.value()); | ||||
| #endif | ||||
| 
 | ||||
|     // update bluetooth counter + LoRa SF (line 3)
 | ||||
| #ifdef BLECOUNTER | ||||
|   u8x8.setCursor(0, 3); | ||||
|   if (cfg.blescan) | ||||
|     u8x8.printf("BLTH:%-4d", macs_ble); | ||||
|   else | ||||
|     u8x8.printf("%s", "BLTH:off"); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef 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]); | ||||
|   if (cfg.adrmode) // switch off inverse if it was turned on
 | ||||
|     u8x8.setInverseFont(0); | ||||
| #endif // HAS_LORA
 | ||||
| 
 | ||||
|   // update wifi counter + channel display (line 4)
 | ||||
|   u8x8.setCursor(0, 4); | ||||
|   u8x8.printf("WIFI:%-4d", macs_wifi); | ||||
|   u8x8.setCursor(11, 4); | ||||
|   u8x8.printf("ch:%02d", channel); | ||||
| 
 | ||||
|   // update RSSI limiter status & free memory display (line 5)
 | ||||
|   u8x8.setCursor(0, 5); | ||||
|   u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); | ||||
|   u8x8.setCursor(10, 5); | ||||
|   u8x8.printf("%4dKB", ESP.getFreeHeap() / 1024); | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
|   // update LoRa status display (line 6)
 | ||||
|   u8x8.setCursor(0, 6); | ||||
|   u8x8.printf("%-16s", display_line6); | ||||
| 
 | ||||
|   // update LMiC event display (line 7)
 | ||||
|   u8x8.setCursor(0, 7); | ||||
|   u8x8.printf("%-16s", display_line7); | ||||
| #endif // HAS_LORA
 | ||||
| } | ||||
| 
 | ||||
| void updateDisplay() { | ||||
|   // refresh display according to refresh cycle setting
 | ||||
|   if (DisplayTimerIRQ) { | ||||
|     portENTER_CRITICAL(&timerMux); | ||||
|     DisplayTimerIRQ = 0; | ||||
|     portEXIT_CRITICAL(&timerMux); | ||||
| 
 | ||||
|     refreshDisplay(); | ||||
| 
 | ||||
|     // set display on/off according to current device configuration
 | ||||
|     if (DisplayState != cfg.screenon) { | ||||
|       DisplayState = cfg.screenon; | ||||
|       u8x8.setPowerSave(!cfg.screenon); | ||||
|     } | ||||
|   } | ||||
| } // updateDisplay()
 | ||||
| #endif // HAS_DISPLAY
 | ||||
| 
 | ||||
| #ifdef HAS_BUTTON | ||||
| void readButton() { | ||||
|   if (ButtonPressedIRQ) { | ||||
|     portENTER_CRITICAL(&timerMux); | ||||
|     ButtonPressedIRQ = 0; | ||||
|     portEXIT_CRITICAL(&timerMux); | ||||
|     ESP_LOGI(TAG, "Button pressed"); | ||||
|     ESP_LOGI(TAG, "Button pressed, resetting device to factory defaults"); | ||||
|     eraseConfig(); | ||||
|     esp_restart(); | ||||
|   } | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED) | ||||
| 
 | ||||
| void blink_LED(uint16_t set_color, uint16_t set_blinkduration) { | ||||
|   LEDColor = set_color;                 // set color for RGB LED
 | ||||
|   LEDBlinkDuration = set_blinkduration; // duration
 | ||||
|   LEDBlinkStarted = millis();           // Time Start here
 | ||||
|   LEDState = LED_ON;                    // Let main set LED on
 | ||||
| } | ||||
| 
 | ||||
| void led_loop() { | ||||
|   // Custom blink running always have priority other LoRaWAN led management
 | ||||
|   if (LEDBlinkStarted && LEDBlinkDuration) { | ||||
|     // Custom blink is finished, let this order, avoid millis() overflow
 | ||||
|     if ((millis() - LEDBlinkStarted) >= LEDBlinkDuration) { | ||||
|       // Led becomes off, and stop blink
 | ||||
|       LEDState = LED_OFF; | ||||
|       LEDBlinkStarted = 0; | ||||
|       LEDBlinkDuration = 0; | ||||
|       LEDColor = COLOR_NONE; | ||||
|     } else { | ||||
|       // In case of LoRaWAN led management blinked off
 | ||||
|       LEDState = LED_ON; | ||||
|     } | ||||
|     // No custom blink, check LoRaWAN state
 | ||||
|   } else { | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
|     // LED indicators for viusalizing LoRaWAN state
 | ||||
|     if (LMIC.opmode & (OP_JOINING | OP_REJOIN)) { | ||||
|       LEDColor = COLOR_YELLOW; | ||||
|       // quick blink 20ms on each 1/5 second
 | ||||
|       LEDState = ((millis() % 200) < 20) ? LED_ON : LED_OFF; // TX data pending
 | ||||
|     } else if (LMIC.opmode & (OP_TXDATA | OP_TXRXPEND)) { | ||||
|       LEDColor = COLOR_BLUE; | ||||
|       // small blink 10ms on each 1/2sec (not when joining)
 | ||||
|       LEDState = ((millis() % 500) < 10) ? LED_ON : LED_OFF; | ||||
|       // This should not happen so indicate a problem
 | ||||
|     } else if (LMIC.opmode & | ||||
|                ((OP_TXDATA | OP_TXRXPEND | OP_JOINING | OP_REJOIN) == 0)) { | ||||
|       LEDColor = COLOR_RED; | ||||
|       // heartbeat long blink 200ms on each 2 seconds
 | ||||
|       LEDState = ((millis() % 2000) < 200) ? LED_ON : LED_OFF; | ||||
|     } else | ||||
| #endif // HAS_LORA
 | ||||
|     { | ||||
|       // led off
 | ||||
|       LEDColor = COLOR_NONE; | ||||
|       LEDState = LED_OFF; | ||||
|     } | ||||
|   } | ||||
|   // led need to change state? avoid digitalWrite() for nothing
 | ||||
|   if (LEDState != previousLEDState) { | ||||
|     if (LEDState == LED_ON) { | ||||
|       rgb_set_color(LEDColor); | ||||
| 
 | ||||
| #ifdef LED_ACTIVE_LOW | ||||
|       digitalWrite(HAS_LED, LOW); | ||||
| #else | ||||
|       digitalWrite(HAS_LED, HIGH); | ||||
| #endif | ||||
| 
 | ||||
|     } else { | ||||
|       rgb_set_color(COLOR_NONE); | ||||
| 
 | ||||
| #ifdef LED_ACTIVE_LOW | ||||
|       digitalWrite(HAS_LED, HIGH); | ||||
| #else | ||||
|       digitalWrite(HAS_LED, LOW); | ||||
| #endif | ||||
|     } | ||||
|     previousLEDState = LEDState; | ||||
|   } | ||||
| }; // led_loop()
 | ||||
| 
 | ||||
| #endif // #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
 | ||||
| 
 | ||||
| void updatePayload() { | ||||
| void sendPayload() { | ||||
| 
 | ||||
|   if (SendCycleTimerIRQ) { | ||||
|     portENTER_CRITICAL(&timerMux); | ||||
| @ -521,7 +244,7 @@ void updatePayload() { | ||||
| 
 | ||||
|     senddata(PAYLOADPORT); | ||||
|   } | ||||
| } // updatePayload()
 | ||||
| } // sendPayload()
 | ||||
| 
 | ||||
| /* begin Aruino SETUP
 | ||||
|  * ------------------------------------------------------------ */ | ||||
| @ -607,6 +330,14 @@ void setup() { | ||||
| #ifdef HAS_ANTENNA_SWITCH | ||||
|   strcat_P(features, " ANT"); | ||||
|   antenna_init(); | ||||
|   antenna_select(cfg.wifiant); | ||||
| #endif | ||||
| 
 | ||||
| // switch off bluetooth on esp32 module, if not compiled
 | ||||
| #ifdef BLECOUNTER | ||||
|   strcat_P(features, " BLE"); | ||||
| #else | ||||
|   bool btstop = btStop(); | ||||
| #endif | ||||
| 
 | ||||
| // initialize gps if present
 | ||||
| @ -614,28 +345,13 @@ void setup() { | ||||
|   strcat_P(features, " GPS"); | ||||
| #endif | ||||
| 
 | ||||
| // initialize display if present
 | ||||
| #ifdef HAS_DISPLAY | ||||
|   strcat_P(features, " OLED"); | ||||
|   // initialize display
 | ||||
|   init_display(PROGNAME, PROGVERSION); | ||||
|   DisplayState = cfg.screenon; | ||||
|   u8x8.setPowerSave(!cfg.screenon); // set display off if disabled
 | ||||
|   u8x8.draw2x2String(0, 0, "PAX:0"); | ||||
| #ifdef BLECOUNTER | ||||
|   u8x8.setCursor(0, 3); | ||||
|   u8x8.printf("BLTH:0"); | ||||
| #endif | ||||
|   u8x8.setCursor(0, 4); | ||||
|   u8x8.printf("WIFI:0"); | ||||
|   u8x8.setCursor(0, 5); | ||||
|   u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit); | ||||
|   init_display(PROGNAME, PROGVERSION); | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
|   sprintf(display_line6, "Join wait"); | ||||
| #endif // HAS_LORA
 | ||||
| 
 | ||||
|   // setup display refresh trigger IRQ using esp32 hardware timer 0
 | ||||
|   // for explanation see
 | ||||
|   // setup display refresh trigger IRQ using esp32 hardware timer
 | ||||
|   // https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
 | ||||
|   displaytimer = timerBegin(0, 80, true); // prescaler 80 -> divides 80 MHz CPU
 | ||||
|                                           // freq to 1 MHz, timer 0, count up
 | ||||
| @ -693,10 +409,28 @@ void setup() { | ||||
|   // https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
 | ||||
| 
 | ||||
|   ESP_LOGI(TAG, "Starting Lora task on core 1"); | ||||
|   xTaskCreatePinnedToCore(lorawan_loop, "loratask", 2048, (void *)1, | ||||
|   xTaskCreatePinnedToCore(lorawan_loop, "loraloop", 2048, (void *)1, | ||||
|                           (5 | portPRIVILEGE_BIT), NULL, 1); | ||||
| #endif | ||||
| 
 | ||||
| // if device has GPS and it is enabled, start GPS reader task on core 0 with
 | ||||
| // higher priority than wifi channel rotation task since we process serial
 | ||||
| // streaming NMEA data
 | ||||
| #ifdef HAS_GPS | ||||
|   if (cfg.gpsmode) { | ||||
|     ESP_LOGI(TAG, "Starting GPS task on core 0"); | ||||
|     xTaskCreatePinnedToCore(gps_loop, "gpsloop", 2048, (void *)1, 2, NULL, 0); | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| // start BLE scan callback if BLE function is enabled in NVRAM configuration
 | ||||
| #ifdef BLECOUNTER | ||||
|   if (cfg.blescan) { | ||||
|     ESP_LOGI(TAG, "Starting BLE task on core 1"); | ||||
|     start_BLEscan(); | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
|   // start wifi in monitor mode and start channel rotation task on core 0
 | ||||
|   ESP_LOGI(TAG, "Starting Wifi task on core 0"); | ||||
|   wifi_sniffer_init(); | ||||
| @ -704,26 +438,9 @@ void setup() { | ||||
|   // arduino-esp32 core note: do this *after* wifi has started, since function
 | ||||
|   // gets it's seed from RF noise
 | ||||
|   reset_salt(); // get new 16bit for salting hashes
 | ||||
|   xTaskCreatePinnedToCore(sniffer_loop, "wifisniffer", 2048, (void *)1, 1, NULL, | ||||
|                           0); | ||||
| 
 | ||||
| // start BLE scan callback if BLE function is enabled in NVRAM configuration
 | ||||
| #ifdef BLECOUNTER | ||||
|   if (cfg.blescan) { | ||||
|     start_BLEscan(); | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| // if device has GPS and it is enabled, start GPS reader task on core 0
 | ||||
| // higher priority than wifi channel rotation task since we process serial
 | ||||
| // streaming NMEA data
 | ||||
| #ifdef HAS_GPS | ||||
|   if (cfg.gpsmode) { | ||||
|     ESP_LOGI(TAG, "Starting GPS task on core 0"); | ||||
|     xTaskCreatePinnedToCore(gps_loop, "gpsfeed", 2048, (void *)1, 2, NULL, 0); | ||||
|   } | ||||
| #endif | ||||
| } | ||||
|   xTaskCreatePinnedToCore(wifi_channel_loop, "wifiloop", 2048, (void *)1, 1, | ||||
|                           NULL, 0); | ||||
| } // setup
 | ||||
| 
 | ||||
| /* end Arduino SETUP
 | ||||
|  * ------------------------------------------------------------ */ | ||||
| @ -763,7 +480,7 @@ void loop() { | ||||
|     } | ||||
| 
 | ||||
|     // check send cycle and send payload if cycle is expired
 | ||||
|     updatePayload(); | ||||
|     sendPayload(); | ||||
| 
 | ||||
|     vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										54
									
								
								src/main.h
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								src/main.h
									
									
									
									
									
								
							| @ -1,15 +1,42 @@ | ||||
| 
 | ||||
| #include "configmanager.h" | ||||
| #include "macsniff.h" | ||||
| #include "senddata.h" | ||||
| 
 | ||||
| // Does nothing and avoid any compilation error with I2C
 | ||||
| #include <Wire.h> | ||||
| 
 | ||||
| // ESP32 lib Functions
 | ||||
| #include <esp32-hal-log.h>  // needed for ESP_LOGx on arduino framework | ||||
| #include <esp_event_loop.h> // needed for Wifi event handler | ||||
| #include <esp_spi_flash.h>  // needed for reading ESP32 chip attributes | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
| #include "lorawan.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_DISPLAY | ||||
| #include "display.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_GPS | ||||
| #include "gps.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BLECOUNTER | ||||
| #include "blescan.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_BATTERY_PROBE | ||||
| #include "battery.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_ANTENNA_SWITCH | ||||
| #include "antenna.h" | ||||
| #endif | ||||
| 
 | ||||
| // program version - note: increment version after modifications to configData_t
 | ||||
| // struct!!
 | ||||
| #define PROGVERSION "1.3.9" // use max 10 chars here!
 | ||||
| #define PROGVERSION "1.3.91" // use max 10 chars here!
 | ||||
| #define PROGNAME "PAXCNT" | ||||
| 
 | ||||
| //--- Declarations ---
 | ||||
| @ -46,29 +73,6 @@ extern gpsStatus_t gps_status; // struct for storing gps data | ||||
| extern TinyGPSPlus gps;        // Make TinyGPS++ instance globally availabe
 | ||||
| #endif | ||||
| 
 | ||||
| enum led_states { LED_OFF, LED_ON }; | ||||
| 
 | ||||
| #if defined(CFG_eu868) | ||||
| const char lora_datarate[] = {"1211100908077BFSNA"}; | ||||
| #elif defined(CFG_us915) | ||||
| const char lora_datarate[] = {"100908078CNA121110090807"}; | ||||
| #endif | ||||
| 
 | ||||
| //--- Prototypes ---
 | ||||
| 
 | ||||
| // defined in main.cpp
 | ||||
| void reset_counters(void); | ||||
| void blink_LED(uint16_t set_color, uint16_t set_blinkduration); | ||||
| void led_loop(void); | ||||
| 
 | ||||
| // defined in blescan.cpp
 | ||||
| #ifdef BLECOUNTER | ||||
| void start_BLEscan(void); | ||||
| void stop_BLEscan(void); | ||||
| #endif | ||||
| 
 | ||||
| // defined in gpsread.cpp
 | ||||
| #ifdef HAS_GPS | ||||
| void gps_read(void); | ||||
| void gps_loop(void *pvParameters); | ||||
| #endif | ||||
| @ -16,18 +16,8 @@ typedef struct { | ||||
|   const bool store; | ||||
| } cmd_t; | ||||
| 
 | ||||
| // function defined in antenna.cpp
 | ||||
| #ifdef HAS_ANTENNA_SWITCH | ||||
| void antenna_select(const uint8_t _ant); | ||||
| #endif | ||||
| 
 | ||||
| // function defined in adcread.cpp
 | ||||
| #ifdef HAS_BATTERY_PROBE | ||||
| uint16_t read_voltage(void); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_LORA | ||||
| // help function to assign LoRa datarates to numeric spreadfactor values
 | ||||
| // helper function to assign LoRa datarates to numeric spreadfactor values
 | ||||
| void switch_lora(uint8_t sf, uint8_t tx) { | ||||
|   if (tx > 20) | ||||
|     return; | ||||
|  | ||||
							
								
								
									
										7
									
								
								src/rcommand.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/rcommand.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| #ifndef rcommand_H | ||||
| #define rcommand_H | ||||
| 
 | ||||
| void rcommand(uint8_t cmd, uint8_t arg); | ||||
| void switch_lora(uint8_t sf, uint8_t tx); | ||||
| 
 | ||||
| #endif | ||||
| @ -1,78 +0,0 @@ | ||||
| // Basic Config
 | ||||
| #include "globals.h" | ||||
| 
 | ||||
| #ifdef HAS_RGB_LED | ||||
| 
 | ||||
| // RGB Led instance
 | ||||
| SmartLed rgb_led(LED_WS2812, 1, HAS_RGB_LED); | ||||
| 
 | ||||
| float rgb_CalcColor(float p, float q, float t) { | ||||
|   if (t < 0.0f) | ||||
|     t += 1.0f; | ||||
|   if (t > 1.0f) | ||||
|     t -= 1.0f; | ||||
| 
 | ||||
|   if (t < 1.0f / 6.0f) | ||||
|     return p + (q - p) * 6.0f * t; | ||||
| 
 | ||||
|   if (t < 0.5f) | ||||
|     return q; | ||||
| 
 | ||||
|   if (t < 2.0f / 3.0f) | ||||
|     return p + ((q - p) * (2.0f / 3.0f - t) * 6.0f); | ||||
| 
 | ||||
|   return p; | ||||
| } | ||||
| 
 | ||||
| // ------------------------------------------------------------------------
 | ||||
| // Hue, Saturation, Lightness color members
 | ||||
| // HslColor using H, S, L values (0.0 - 1.0)
 | ||||
| // L should be limited to between (0.0 - 0.5)
 | ||||
| // ------------------------------------------------------------------------
 | ||||
| RGBColor rgb_hsl2rgb(float h, float s, float l) { | ||||
|   RGBColor RGB_color; | ||||
|   float r; | ||||
|   float g; | ||||
|   float b; | ||||
| 
 | ||||
|   if (s == 0.0f || l == 0.0f) { | ||||
|     r = g = b = l; // achromatic or black
 | ||||
|   } else { | ||||
|     float q = l < 0.5f ? l * (1.0f + s) : l + s - (l * s); | ||||
|     float p = 2.0f * l - q; | ||||
|     r = rgb_CalcColor(p, q, h + 1.0f / 3.0f); | ||||
|     g = rgb_CalcColor(p, q, h); | ||||
|     b = rgb_CalcColor(p, q, h - 1.0f / 3.0f); | ||||
|   } | ||||
| 
 | ||||
|   RGB_color.R = (uint8_t)(r * 255.0f); | ||||
|   RGB_color.G = (uint8_t)(g * 255.0f); | ||||
|   RGB_color.B = (uint8_t)(b * 255.0f); | ||||
| 
 | ||||
|   return RGB_color; | ||||
| } | ||||
| 
 | ||||
| void rgb_set_color(uint16_t hue) { | ||||
|   if (hue == COLOR_NONE) { | ||||
|     // Off
 | ||||
|     rgb_led[0] = Rgb(0, 0, 0); | ||||
|   } else { | ||||
|     // see http://www.workwithcolor.com/blue-color-hue-range-01.htm
 | ||||
|     // H (is color from 0..360) should be between 0.0 and 1.0
 | ||||
|     // S is saturation keep it to 1
 | ||||
|     // L is brightness should be between 0.0 and 0.5
 | ||||
|     // cfg.rgblum is between 0 and 100 (percent)
 | ||||
|     RGBColor target = rgb_hsl2rgb(hue / 360.0f, 1.0f, 0.005f * cfg.rgblum); | ||||
|     // uint32_t color = target.R<<16 | target.G<<8 | target.B;
 | ||||
|     rgb_led[0] = Rgb(target.R, target.G, target.B); | ||||
|   } | ||||
|   // Show
 | ||||
|   rgb_led.show(); | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| // No RGB LED empty functions
 | ||||
| void rgb_set_color(uint16_t hue) {} | ||||
| 
 | ||||
| #endif | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user