diff --git a/.clang-format b/.clang-format deleted file mode 100644 index d368b346..00000000 --- a/.clang-format +++ /dev/null @@ -1,108 +0,0 @@ ---- -Language: Cpp -# BasedOnStyle: LLVM -AccessModifierOffset: -2 -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlines: Right -AlignOperands: true -AlignTrailingComments: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: false -BinPackArguments: true -BinPackParameters: true -BraceWrapping: - AfterClass: false - AfterControlStatement: false - AfterEnum: false - AfterFunction: false - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - BeforeCatch: false - BeforeElse: false - IndentBraces: false - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Attach -BreakBeforeInheritanceComma: false -BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeColon -BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: true -ColumnLimit: 80 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: true -ForEachMacros: - - foreach - - Q_FOREACH - - BOOST_FOREACH -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - - Regex: '.*' - Priority: 1 -IncludeIsMainRegex: '(Test)?$' -IndentCaseLabels: false -IndentWidth: 2 -IndentWrappedFunctionNames: false -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBlockIndentWidth: 2 -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Right -ReflowComments: true -SortIncludes: true -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceAfterTemplateKeyword: true -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 -TabWidth: 8 -UseTab: Never -... - diff --git a/src/adcread.cpp b/src/adcread.cpp index 84b1313d..1dc46776 100644 --- a/src/adcread.cpp +++ b/src/adcread.cpp @@ -5,57 +5,52 @@ #include #include -#define DEFAULT_VREF \ - 1100 // to be done: use adc2_vref_to_gpio() to obtain a better estimate -#define NO_OF_SAMPLES 64 // we do multisampling +#define DEFAULT_VREF 1100 // to be done: use adc2_vref_to_gpio() to obtain a better estimate +#define NO_OF_SAMPLES 64 // we do multisampling // Local logging tag static const char TAG[] = "main"; -static void print_char_val_type(esp_adc_cal_value_t val_type) { - 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"); - } +static void print_char_val_type(esp_adc_cal_value_t val_type) +{ + 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"); + } } -uint16_t read_voltage(void) { - static const adc1_channel_t channel = HAS_BATTERY_PROBE; - static const adc_atten_t atten = ADC_ATTEN_DB_11; - static const adc_unit_t unit = ADC_UNIT_1; +uint16_t read_voltage(void) +{ + static const adc1_channel_t channel = HAS_BATTERY_PROBE; + static const adc_atten_t atten = ADC_ATTEN_DB_11; + static const adc_unit_t unit = ADC_UNIT_1; - // configure ADC1 - ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12)); - ESP_ERROR_CHECK(adc1_config_channel_atten(channel, atten)); + //configure ADC1 + ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12)); + ESP_ERROR_CHECK(adc1_config_channel_atten(channel, atten)); - // calibrate ADC1 - esp_adc_cal_characteristics_t *adc_chars = - (esp_adc_cal_characteristics_t *)calloc( - 1, sizeof(esp_adc_cal_characteristics_t)); - esp_adc_cal_value_t val_type = esp_adc_cal_characterize( - unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars); - print_char_val_type(val_type); + //calibrate ADC1 + esp_adc_cal_characteristics_t *adc_chars = (esp_adc_cal_characteristics_t *) calloc(1, sizeof(esp_adc_cal_characteristics_t)); + esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars); + print_char_val_type(val_type); - // multisample ADC1 - uint32_t adc_reading = 0; - for (int i = 0; i < NO_OF_SAMPLES; i++) { - adc_reading += adc1_get_raw(channel); - } + //multisample ADC1 + uint32_t adc_reading = 0; + for (int i = 0; i < NO_OF_SAMPLES; i++) { + adc_reading += adc1_get_raw(channel); + } - adc_reading /= NO_OF_SAMPLES; + adc_reading /= NO_OF_SAMPLES; - // Convert adc_reading to voltage in mV - uint16_t voltage = - (uint16_t)esp_adc_cal_raw_to_voltage(adc_reading, adc_chars); -#ifdef BATT_FACTOR - voltage *= BATT_FACTOR; -#endif - ESP_LOGI(TAG, "Raw: %d / Voltage: %dmV", adc_reading, voltage); - return voltage; + //Convert adc_reading to voltage in mV + uint16_t voltage = (uint16_t) esp_adc_cal_raw_to_voltage(adc_reading, adc_chars); + #ifdef BATT_FACTOR + voltage *= BATT_FACTOR; + #endif + ESP_LOGI(TAG,"Raw: %d / Voltage: %dmV", adc_reading, voltage); + return voltage; } #endif // HAS_BATTERY_PROBE \ No newline at end of file diff --git a/src/antenna.cpp b/src/antenna.cpp index b8d044dd..402a313b 100644 --- a/src/antenna.cpp +++ b/src/antenna.cpp @@ -1,5 +1,4 @@ -/* switches wifi antenna, if board has switch to select internal and external - * antenna */ +/* switches wifi antenna, if board has switch to select internal and external antenna */ #ifdef HAS_ANTENNA_SWITCH @@ -8,32 +7,35 @@ // Local logging tag static const char TAG[] = "wifi"; -typedef enum { ANTENNA_INT = 0, ANTENNA_EXT } antenna_type_t; +typedef enum { + ANTENNA_INT = 0, + ANTENNA_EXT +} antenna_type_t; void antenna_init(void) { - gpio_config_t gpioconf = {.pin_bit_mask = 1ull << HAS_ANTENNA_SWITCH, - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE}; - gpio_config(&gpioconf); + gpio_config_t gpioconf = {.pin_bit_mask = 1ull << HAS_ANTENNA_SWITCH, + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE}; + gpio_config(&gpioconf); } -void antenna_select(const uint8_t _ant) { - if (HAS_ANTENNA_SWITCH < 32) { - if (_ant == ANTENNA_EXT) { - GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << HAS_ANTENNA_SWITCH); - } else { - GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << HAS_ANTENNA_SWITCH); - } - } else { - if (_ant == ANTENNA_EXT) { - GPIO_REG_WRITE(GPIO_OUT1_W1TS_REG, 1 << (HAS_ANTENNA_SWITCH & 31)); - } else { - GPIO_REG_WRITE(GPIO_OUT1_W1TC_REG, 1 << (HAS_ANTENNA_SWITCH & 31)); - } - } - ESP_LOGI(TAG, "Wifi Antenna switched to %s", _ant ? "external" : "internal"); +void antenna_select (const uint8_t _ant) { + if (HAS_ANTENNA_SWITCH < 32) { + if (_ant == ANTENNA_EXT) { + GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << HAS_ANTENNA_SWITCH); + } else { + GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << HAS_ANTENNA_SWITCH); + } + } else { + if (_ant == ANTENNA_EXT) { + GPIO_REG_WRITE(GPIO_OUT1_W1TS_REG, 1 << (HAS_ANTENNA_SWITCH & 31)); + } else { + GPIO_REG_WRITE(GPIO_OUT1_W1TC_REG, 1 << (HAS_ANTENNA_SWITCH & 31)); + } + } + ESP_LOGI(TAG, "Wifi Antenna switched to %s", _ant ? "external" : "internal"); } #endif \ No newline at end of file diff --git a/src/blecsan.cpp b/src/blecsan.cpp index af3e725d..c7f4f9b4 100644 --- a/src/blecsan.cpp +++ b/src/blecsan.cpp @@ -8,14 +8,13 @@ https://github.com/nkolban/esp32-snippets/tree/master/BLE/scanner #include "globals.h" // Bluetooth specific includes -#include -#include // needed for BLE_ADDR types, do not remove #include #include #include +#include // needed for BLE_ADDR types, do not remove +#include -#define BT_BD_ADDR_HEX(addr) \ - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] +#define BT_BD_ADDR_HEX(addr) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] // local Tag for logging static const char TAG[] = "bluetooth"; @@ -24,256 +23,208 @@ static const char TAG[] = "bluetooth"; bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type); const char *bt_addr_t_to_string(esp_ble_addr_type_t type) { - switch (type) { - case BLE_ADDR_TYPE_PUBLIC: - return "BLE_ADDR_TYPE_PUBLIC"; - case BLE_ADDR_TYPE_RANDOM: - return "BLE_ADDR_TYPE_RANDOM"; - case BLE_ADDR_TYPE_RPA_PUBLIC: - return "BLE_ADDR_TYPE_RPA_PUBLIC"; - case BLE_ADDR_TYPE_RPA_RANDOM: - return "BLE_ADDR_TYPE_RPA_RANDOM"; - default: - return "Unknown addr_t"; - } + switch(type) { + case BLE_ADDR_TYPE_PUBLIC: + return "BLE_ADDR_TYPE_PUBLIC"; + case BLE_ADDR_TYPE_RANDOM: + return "BLE_ADDR_TYPE_RANDOM"; + case BLE_ADDR_TYPE_RPA_PUBLIC: + return "BLE_ADDR_TYPE_RPA_PUBLIC"; + case BLE_ADDR_TYPE_RPA_RANDOM: + return "BLE_ADDR_TYPE_RPA_RANDOM"; + default: + return "Unknown addr_t"; + } } // bt_addr_t_to_string const char *btsig_gap_type(uint32_t gap_type) { - switch (gap_type) { - case 0x01: - return "Flags"; - case 0x02: - return "Incomplete List of 16-bit Service Class UUIDs"; - case 0x03: - return "Complete List of 16-bit Service Class UUIDs"; - case 0x04: - return "Incomplete List of 32-bit Service Class UUIDs"; - case 0x05: - return "Complete List of 32-bit Service Class UUIDs"; - case 0x06: - return "Incomplete List of 128-bit Service Class UUIDs"; - case 0x07: - return "Complete List of 128-bit Service Class UUIDs"; - case 0x08: - return "Shortened Local Name"; - case 0x09: - return "Complete Local Name"; - case 0x0A: - return "Tx Power Level"; - case 0x0D: - return "Class of Device"; - case 0x0E: - return "Simple Pairing Hash C/C-192"; - case 0x0F: - return "Simple Pairing Randomizer R/R-192"; - case 0x10: - return "Device ID/Security Manager TK Value"; - case 0x11: - return "Security Manager Out of Band Flags"; - case 0x12: - return "Slave Connection Interval Range"; - case 0x14: - return "List of 16-bit Service Solicitation UUIDs"; - case 0x1F: - return "List of 32-bit Service Solicitation UUIDs"; - case 0x15: - return "List of 128-bit Service Solicitation UUIDs"; - case 0x16: - return "Service Data - 16-bit UUID"; - case 0x20: - return "Service Data - 32-bit UUID"; - case 0x21: - return "Service Data - 128-bit UUID"; - case 0x22: - return "LE Secure Connections Confirmation Value"; - case 0x23: - return "LE Secure Connections Random Value"; - case 0x24: - return "URI"; - case 0x25: - return "Indoor Positioning"; - case 0x26: - return "Transport Discovery Data"; - case 0x17: - return "Public Target Address"; - case 0x18: - return "Random Target Address"; - case 0x19: - return "Appearance"; - case 0x1A: - return "Advertising Interval"; - case 0x1B: - return "LE Bluetooth Device Address"; - case 0x1C: - return "LE Role"; - case 0x1D: - return "Simple Pairing Hash C-256"; - case 0x1E: - return "Simple Pairing Randomizer R-256"; - case 0x3D: - return "3D Information Data"; - case 0xFF: - return "Manufacturer Specific Data"; - - default: - return "Unknown type"; - } + switch (gap_type) + { + case 0x01: return "Flags"; + case 0x02: return "Incomplete List of 16-bit Service Class UUIDs"; + case 0x03: return "Complete List of 16-bit Service Class UUIDs"; + case 0x04: return "Incomplete List of 32-bit Service Class UUIDs"; + case 0x05: return "Complete List of 32-bit Service Class UUIDs"; + case 0x06: return "Incomplete List of 128-bit Service Class UUIDs"; + case 0x07: return "Complete List of 128-bit Service Class UUIDs"; + case 0x08: return "Shortened Local Name"; + case 0x09: return "Complete Local Name"; + case 0x0A: return "Tx Power Level"; + case 0x0D: return "Class of Device"; + case 0x0E: return "Simple Pairing Hash C/C-192"; + case 0x0F: return "Simple Pairing Randomizer R/R-192"; + case 0x10: return "Device ID/Security Manager TK Value"; + case 0x11: return "Security Manager Out of Band Flags"; + case 0x12: return "Slave Connection Interval Range"; + case 0x14: return "List of 16-bit Service Solicitation UUIDs"; + case 0x1F: return "List of 32-bit Service Solicitation UUIDs"; + case 0x15: return "List of 128-bit Service Solicitation UUIDs"; + case 0x16: return "Service Data - 16-bit UUID"; + case 0x20: return "Service Data - 32-bit UUID"; + case 0x21: return "Service Data - 128-bit UUID"; + case 0x22: return "LE Secure Connections Confirmation Value"; + case 0x23: return "LE Secure Connections Random Value"; + case 0x24: return "URI"; + case 0x25: return "Indoor Positioning"; + case 0x26: return "Transport Discovery Data"; + case 0x17: return "Public Target Address"; + case 0x18: return "Random Target Address"; + case 0x19: return "Appearance"; + case 0x1A: return "Advertising Interval"; + case 0x1B: return "LE Bluetooth Device Address"; + case 0x1C: return "LE Role"; + case 0x1D: return "Simple Pairing Hash C-256"; + case 0x1E: return "Simple Pairing Randomizer R-256"; + case 0x3D: return "3D Information Data"; + case 0xFF: return "Manufacturer Specific Data"; + + default: + return "Unknown type"; + } } // btsig_gap_type // using IRAM_:ATTR here to speed up callback function -IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event, - esp_ble_gap_cb_param_t *param) { - esp_ble_gap_cb_param_t *p = (esp_ble_gap_cb_param_t *)param; +IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + esp_ble_gap_cb_param_t *p = (esp_ble_gap_cb_param_t *)param; + + ESP_LOGD(TAG, "BT payload rcvd -> type: 0x%.2x -> %s", *p->scan_rst.ble_adv, btsig_gap_type(*p->scan_rst.ble_adv)); - ESP_LOGD(TAG, "BT payload rcvd -> type: 0x%.2x -> %s", *p->scan_rst.ble_adv, - btsig_gap_type(*p->scan_rst.ble_adv)); + switch (event) + { + case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: + // restart scan + ESP_ERROR_CHECK(esp_ble_gap_start_scanning(BLESCANTIME)); + break; + + case ESP_GAP_BLE_SCAN_RESULT_EVT: + // evaluate scan results + if ( p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) // Inquiry complete, scan is done + { // restart scan + ESP_ERROR_CHECK(esp_ble_gap_start_scanning(BLESCANTIME)); + return; + } + + if (p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) // Inquiry result for a peer device + { // evaluate sniffed packet + ESP_LOGD(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", BT_BD_ADDR_HEX(p->scan_rst.bda)); + ESP_LOGD(TAG, "Addr_type : %s", bt_addr_t_to_string(p->scan_rst.ble_addr_type)); + ESP_LOGD(TAG, "RSSI : %d", p->scan_rst.rssi); - switch (event) { - case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: - // restart scan - ESP_ERROR_CHECK(esp_ble_gap_start_scanning(BLESCANTIME)); - break; + if ((cfg.rssilimit) && (p->scan_rst.rssi < cfg.rssilimit )) { // rssi is negative value + ESP_LOGI(TAG, "BLTH RSSI %d -> ignoring (limit: %d)", p->scan_rst.rssi, cfg.rssilimit); + break; + } - case ESP_GAP_BLE_SCAN_RESULT_EVT: - // evaluate scan results - if (p->scan_rst.search_evt == - ESP_GAP_SEARCH_INQ_CMPL_EVT) // Inquiry complete, scan is done - { // restart scan - ESP_ERROR_CHECK(esp_ble_gap_start_scanning(BLESCANTIME)); - return; - } + #ifdef VENDORFILTER + + if ((p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RANDOM) || (p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RPA_RANDOM)) { + ESP_LOGD(TAG, "BT device filtered"); + break; + } - if (p->scan_rst.search_evt == - ESP_GAP_SEARCH_INQ_RES_EVT) // Inquiry result for a peer device - { // evaluate sniffed packet - ESP_LOGD(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", - BT_BD_ADDR_HEX(p->scan_rst.bda)); - ESP_LOGD(TAG, "Addr_type : %s", - bt_addr_t_to_string(p->scan_rst.ble_addr_type)); - ESP_LOGD(TAG, "RSSI : %d", p->scan_rst.rssi); + #endif - if ((cfg.rssilimit) && - (p->scan_rst.rssi < cfg.rssilimit)) { // rssi is negative value - ESP_LOGI(TAG, "BLTH RSSI %d -> ignoring (limit: %d)", p->scan_rst.rssi, - cfg.rssilimit); + // add this device and show new count total if it was not previously added + mac_add((uint8_t *) p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE); + + /* to be improved in vendorfilter if: + + // you can search for elements in the payload using the + // function esp_ble_resolve_adv_data() + // + // Like this, that scans for the "Complete name" (looking inside the payload buffer) + // uint8_t len; + // uint8_t *data = esp_ble_resolve_adv_data(p->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &len); + + filter BLE devices using their advertisements to get filter alternative to vendor OUI + if vendorfiltering is on, we ... + - want to count: mobile phones and tablets + - don't want to count: beacons, peripherals (earphones, headsets, printers), cars and machines + see + https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/src/BLEAdvertisedDevice.cpp + + http://www.libelium.com/products/meshlium/smartphone-detection/ + + https://www.question-defense.com/2013/01/12/bluetooth-cod-bluetooth-class-of-deviceclass-of-service-explained + + https://www.bluetooth.com/specifications/assigned-numbers/baseband + + "The Class of Device (CoD) in case of Bluetooth which allows us to differentiate the type of + device (smartphone, handsfree, computer, LAN/network AP). With this parameter we can + differentiate among pedestrians and vehicles." + + */ + + } // evaluate sniffed packet + break; + + default: break; - } - -#ifdef VENDORFILTER - - if ((p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RANDOM) || - (p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RPA_RANDOM)) { - ESP_LOGD(TAG, "BT device filtered"); - break; - } - -#endif - - // add this device and show new count total if it was not previously added - mac_add((uint8_t *)p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE); - - /* to be improved in vendorfilter if: - - // you can search for elements in the payload using the - // function esp_ble_resolve_adv_data() - // - // Like this, that scans for the "Complete name" (looking inside the - payload buffer) - // uint8_t len; - // uint8_t *data = esp_ble_resolve_adv_data(p->scan_rst.ble_adv, - ESP_BLE_AD_TYPE_NAME_CMPL, &len); - - filter BLE devices using their advertisements to get filter alternative to - vendor OUI if vendorfiltering is on, we ... - - want to count: mobile phones and tablets - - don't want to count: beacons, peripherals (earphones, headsets, - printers), cars and machines see - https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/src/BLEAdvertisedDevice.cpp - - http://www.libelium.com/products/meshlium/smartphone-detection/ - - https://www.question-defense.com/2013/01/12/bluetooth-cod-bluetooth-class-of-deviceclass-of-service-explained - - https://www.bluetooth.com/specifications/assigned-numbers/baseband - - "The Class of Device (CoD) in case of Bluetooth which allows us to - differentiate the type of device (smartphone, handsfree, computer, - LAN/network AP). With this parameter we can differentiate among - pedestrians and vehicles." - - */ - - } // evaluate sniffed packet - break; - - default: - break; - } + } } // gap_callback_handler + esp_err_t register_ble_callback(void) { - ESP_LOGI(TAG, "Register GAP callback"); + ESP_LOGI(TAG, "Register GAP callback"); + + // This function is called to occur gap event, such as scan result. + //register the scan callback function to the gap module + ESP_ERROR_CHECK(esp_ble_gap_register_callback(&gap_callback_handler)); - // This function is called to occur gap event, such as scan result. - // register the scan callback function to the gap module - ESP_ERROR_CHECK(esp_ble_gap_register_callback(&gap_callback_handler)); + static esp_ble_scan_params_t ble_scan_params = + { + .scan_type = BLE_SCAN_TYPE_PASSIVE, + .own_addr_type = BLE_ADDR_TYPE_RANDOM, + + #ifdef VENDORFILTER + .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR, + // ADV_IND, ADV_NONCONN_IND, ADV_SCAN_IND packets are used for broadcasting + // data in broadcast applications (e.g., Beacons), so we don't want them in vendorfilter mode + #else + .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, + #endif - static esp_ble_scan_params_t ble_scan_params = { - .scan_type = BLE_SCAN_TYPE_PASSIVE, - .own_addr_type = BLE_ADDR_TYPE_RANDOM, + .scan_interval = (uint16_t) (cfg.blescantime * 10 / 0.625), // Time = N * 0.625 msec + .scan_window = (uint16_t) (BLESCANWINDOW / 0.625) // Time = N * 0.625 msec + }; -#ifdef VENDORFILTER - .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR, - // ADV_IND, ADV_NONCONN_IND, ADV_SCAN_IND packets are used for broadcasting - // data in broadcast applications (e.g., Beacons), so we don't want them in - // vendorfilter mode -#else - .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, -#endif + ESP_LOGI(TAG, "Set GAP scan parameters"); - .scan_interval = - (uint16_t)(cfg.blescantime * 10 / 0.625), // Time = N * 0.625 msec - .scan_window = (uint16_t)(BLESCANWINDOW / 0.625) // Time = N * 0.625 msec - }; - - ESP_LOGI(TAG, "Set GAP scan parameters"); - - // This function is called to set scan parameters. - ESP_ERROR_CHECK(esp_ble_gap_set_scan_params(&ble_scan_params)); - - return ESP_OK; + // This function is called to set scan parameters. + ESP_ERROR_CHECK(esp_ble_gap_set_scan_params(&ble_scan_params)); + + return ESP_OK; } // register_ble_callback -void start_BLEscan(void) { - ESP_LOGI(TAG, "Initializing bluetooth scanner ..."); +void start_BLEscan(void){ + ESP_LOGI(TAG, "Initializing bluetooth scanner ..."); - // Initialize BT controller to allocate task and other resource. - esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - bt_cfg.controller_task_stack_size = - BLESTACKSIZE; // set BT stack size to value configured in paxcounter.conf - ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); - ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BTDM)); + // Initialize BT controller to allocate task and other resource. + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + bt_cfg.controller_task_stack_size = BLESTACKSIZE; // set BT stack size to value configured in paxcounter.conf + ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); + ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BTDM)); - // Init and alloc the resource for bluetooth stack, must be done prior to - // every bluetooth stuff - ESP_ERROR_CHECK(esp_bluedroid_init()); - ESP_ERROR_CHECK(esp_bluedroid_enable()); + // Init and alloc the resource for bluetooth stack, must be done prior to every bluetooth stuff + ESP_ERROR_CHECK(esp_bluedroid_init()); + ESP_ERROR_CHECK(esp_bluedroid_enable()); - // Register callback function for capturing bluetooth packets - ESP_ERROR_CHECK(register_ble_callback()); + // Register callback function for capturing bluetooth packets + ESP_ERROR_CHECK(register_ble_callback()); - ESP_LOGI(TAG, "Bluetooth scanner started"); + ESP_LOGI(TAG, "Bluetooth scanner started"); } // start_BLEscan -void stop_BLEscan(void) { - ESP_LOGI(TAG, "Shutting down bluetooth scanner ..."); - ESP_ERROR_CHECK(esp_ble_gap_register_callback(NULL)); - ESP_ERROR_CHECK(esp_bluedroid_disable()); - ESP_ERROR_CHECK(esp_bluedroid_deinit()); - ESP_ERROR_CHECK(esp_bt_controller_disable()); - ESP_ERROR_CHECK(esp_bt_controller_deinit()); - ESP_LOGI(TAG, "Bluetooth scanner stopped"); +void stop_BLEscan(void){ + ESP_LOGI(TAG, "Shutting down bluetooth scanner ..."); + ESP_ERROR_CHECK(esp_ble_gap_register_callback(NULL)); + ESP_ERROR_CHECK(esp_bluedroid_disable()); + ESP_ERROR_CHECK(esp_bluedroid_deinit()); + ESP_ERROR_CHECK(esp_bt_controller_disable()); + ESP_ERROR_CHECK(esp_bt_controller_deinit()); + ESP_LOGI(TAG, "Bluetooth scanner stopped"); } // stop_BLEscan #endif // BLECOUNTER \ No newline at end of file diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 39cd707e..867a071f 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -13,152 +13,130 @@ esp_err_t err; // defined in antenna.cpp #ifdef HAS_ANTENNA_SWITCH -void antenna_select(const uint8_t _ant); + void antenna_select(const uint8_t _ant); #endif // populate cfg vars with factory settings void defaultConfig() { - cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora spreadfactor defined in - // paxcounter.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 = SEND_SECS; // payload send cycle [seconds/2] - cfg.wifichancycle = - WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100] - cfg.blescantime = - BLESCANINTERVAL / - 10; // BT channel scan cycle duration [seconds/100], default 1 (= 10ms) - cfg.blescan = 1; // 0=disabled, 1=enabled - cfg.wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) - cfg.vendorfilter = 1; // 0=disabled, 1=enabled - cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) - cfg.gpsmode = 1; // 0=disabled, 1=enabled + cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora spreadfactor defined in paxcounter.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 = SEND_SECS; // payload send cycle [seconds/2] + cfg.wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100] + cfg.blescantime = BLESCANINTERVAL / 10; // BT channel scan cycle duration [seconds/100], default 1 (= 10ms) + cfg.blescan = 1; // 0=disabled, 1=enabled + cfg.wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) + cfg.vendorfilter = 1; // 0=disabled, 1=enabled + cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) + cfg.gpsmode = 1; // 0=disabled, 1=enabled - strncpy(cfg.version, PROGVERSION, sizeof(cfg.version) - 1); + strncpy( cfg.version, PROGVERSION, sizeof(cfg.version)-1 ); } void open_storage() { - err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - // NVS partition was truncated and needs to be erased - // Retry nvs_flash_init - ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); - } - ESP_ERROR_CHECK(err); + if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + // NVS partition was truncated and needs to be erased + // Retry nvs_flash_init + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK( err ); - // Open - ESP_LOGI(TAG, "Opening NVS"); - err = nvs_open("config", NVS_READWRITE, &my_handle); - if (err != ESP_OK) - ESP_LOGI(TAG, "Error (%d) opening NVS handle", err); - else - ESP_LOGI(TAG, "Done"); + // Open + ESP_LOGI(TAG, "Opening NVS"); + err = nvs_open("config", NVS_READWRITE, &my_handle); + if (err != ESP_OK) + ESP_LOGI(TAG, "Error (%d) opening NVS handle", err); + else + ESP_LOGI(TAG, "Done"); } // erase all keys and values in NVRAM void eraseConfig() { - ESP_LOGI(TAG, "Clearing settings in NVS"); - open_storage(); - if (err == ESP_OK) { - nvs_erase_all(my_handle); - nvs_commit(my_handle); - nvs_close(my_handle); - ESP_LOGI(TAG, "Done"); - } else { - ESP_LOGW(TAG, "NVS erase failed"); - } + ESP_LOGI(TAG, "Clearing settings in NVS"); + open_storage(); + if (err == ESP_OK) { + nvs_erase_all(my_handle); + nvs_commit(my_handle); + nvs_close(my_handle); + ESP_LOGI(TAG, "Done");} + else { + ESP_LOGW(TAG, "NVS erase failed"); } } // save current configuration from RAM to NVRAM void saveConfig() { - ESP_LOGI(TAG, "Storing settings in NVS"); - open_storage(); - if (err == ESP_OK) { - int8_t flash8 = 0; - int16_t flash16 = 0; - size_t required_size; - char storedversion[10]; + ESP_LOGI(TAG, "Storing settings in NVS"); + open_storage(); + if (err == ESP_OK) { + int8_t flash8 = 0; + int16_t flash16 = 0; + size_t required_size; + char storedversion[10]; - if (nvs_get_str(my_handle, "version", storedversion, &required_size) != - ESP_OK || - strcmp(storedversion, cfg.version) != 0) - nvs_set_str(my_handle, "version", cfg.version); + if( nvs_get_str(my_handle, "version", storedversion, &required_size) != ESP_OK || 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, "lorasf", &flash8) != ESP_OK || flash8 != cfg.lorasf ) + nvs_set_i8(my_handle, "lorasf", cfg.lorasf); - if (nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK || - flash8 != cfg.txpower) - nvs_set_i8(my_handle, "txpower", cfg.txpower); + if( nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK || flash8 != cfg.txpower ) + nvs_set_i8(my_handle, "txpower", cfg.txpower); - if (nvs_get_i8(my_handle, "adrmode", &flash8) != ESP_OK || - flash8 != cfg.adrmode) - nvs_set_i8(my_handle, "adrmode", cfg.adrmode); + if( nvs_get_i8(my_handle, "adrmode", &flash8) != ESP_OK || flash8 != cfg.adrmode ) + nvs_set_i8(my_handle, "adrmode", cfg.adrmode); - if (nvs_get_i8(my_handle, "screensaver", &flash8) != ESP_OK || - flash8 != cfg.screensaver) - nvs_set_i8(my_handle, "screensaver", cfg.screensaver); + if( nvs_get_i8(my_handle, "screensaver", &flash8) != ESP_OK || flash8 != cfg.screensaver ) + nvs_set_i8(my_handle, "screensaver", cfg.screensaver); - if (nvs_get_i8(my_handle, "screenon", &flash8) != ESP_OK || - flash8 != cfg.screenon) - nvs_set_i8(my_handle, "screenon", cfg.screenon); + if( nvs_get_i8(my_handle, "screenon", &flash8) != ESP_OK || flash8 != cfg.screenon ) + nvs_set_i8(my_handle, "screenon", cfg.screenon); - if (nvs_get_i8(my_handle, "countermode", &flash8) != ESP_OK || - flash8 != cfg.countermode) - nvs_set_i8(my_handle, "countermode", cfg.countermode); + if( nvs_get_i8(my_handle, "countermode", &flash8) != ESP_OK || flash8 != cfg.countermode ) + nvs_set_i8(my_handle, "countermode", cfg.countermode); - if (nvs_get_i8(my_handle, "sendcycle", &flash8) != ESP_OK || - flash8 != cfg.sendcycle) - nvs_set_i8(my_handle, "sendcycle", cfg.sendcycle); + if( nvs_get_i8(my_handle, "sendcycle", &flash8) != ESP_OK || flash8 != cfg.sendcycle ) + nvs_set_i8(my_handle, "sendcycle", cfg.sendcycle); - if (nvs_get_i8(my_handle, "wifichancycle", &flash8) != ESP_OK || - flash8 != cfg.wifichancycle) - nvs_set_i8(my_handle, "wifichancycle", cfg.wifichancycle); + if( nvs_get_i8(my_handle, "wifichancycle", &flash8) != ESP_OK || flash8 != cfg.wifichancycle ) + nvs_set_i8(my_handle, "wifichancycle", cfg.wifichancycle); - if (nvs_get_i8(my_handle, "blescantime", &flash8) != ESP_OK || - flash8 != cfg.blescantime) - nvs_set_i8(my_handle, "blescantime", cfg.blescantime); + if( nvs_get_i8(my_handle, "blescantime", &flash8) != ESP_OK || flash8 != cfg.blescantime ) + nvs_set_i8(my_handle, "blescantime", cfg.blescantime); - if (nvs_get_i8(my_handle, "blescanmode", &flash8) != ESP_OK || - flash8 != cfg.blescan) - nvs_set_i8(my_handle, "blescanmode", cfg.blescan); + if( nvs_get_i8(my_handle, "blescanmode", &flash8) != ESP_OK || flash8 != cfg.blescan ) + nvs_set_i8(my_handle, "blescanmode", cfg.blescan); - if (nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK || - flash8 != cfg.wifiant) - nvs_set_i8(my_handle, "wifiant", cfg.wifiant); + if( nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK || flash8 != cfg.wifiant ) + nvs_set_i8(my_handle, "wifiant", cfg.wifiant); - if (nvs_get_i8(my_handle, "vendorfilter", &flash8) != ESP_OK || - flash8 != cfg.vendorfilter) - nvs_set_i8(my_handle, "vendorfilter", cfg.vendorfilter); + if( nvs_get_i8(my_handle, "vendorfilter", &flash8) != ESP_OK || flash8 != cfg.vendorfilter ) + nvs_set_i8(my_handle, "vendorfilter", cfg.vendorfilter); - if (nvs_get_i8(my_handle, "rgblum", &flash8) != ESP_OK || - flash8 != cfg.rgblum) - nvs_set_i8(my_handle, "rgblum", cfg.rgblum); + if( nvs_get_i8(my_handle, "rgblum", &flash8) != ESP_OK || flash8 != cfg.rgblum ) + nvs_set_i8(my_handle, "rgblum", cfg.rgblum); - if (nvs_get_i8(my_handle, "gpsmode", &flash8) != ESP_OK || - flash8 != cfg.gpsmode) + if( nvs_get_i8(my_handle, "gpsmode", &flash8) != ESP_OK || flash8 != cfg.gpsmode ) nvs_set_i8(my_handle, "gpsmode", cfg.gpsmode); - if (nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || - flash16 != cfg.rssilimit) - nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit); + if( nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || flash16 != cfg.rssilimit ) + nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit); - err = nvs_commit(my_handle); - nvs_close(my_handle); - if (err == ESP_OK) { - ESP_LOGI(TAG, "Done"); + err = nvs_commit(my_handle); + nvs_close(my_handle); + if ( err == ESP_OK ) { + ESP_LOGI(TAG, "Done"); + } else { + ESP_LOGW(TAG, "NVS config write failed"); + } } else { - ESP_LOGW(TAG, "NVS config write failed"); + ESP_LOGW(TAG, "Error (%d) opening NVS handle", err); } - } else { - ESP_LOGW(TAG, "Error (%d) opening NVS handle", err); - } } // set and save cfg.version @@ -174,33 +152,31 @@ void loadConfig() { ESP_LOGI(TAG, "Reading settings from NVS"); open_storage(); if (err != ESP_OK) { - ESP_LOGW(TAG, "Error (%d) opening NVS handle, storing defaults", err); - saveConfig(); - } // saves factory settings to NVRAM + ESP_LOGW(TAG,"Error (%d) opening NVS handle, storing defaults", err); + saveConfig(); } // saves factory settings to NVRAM else { - int8_t flash8 = 0; + int8_t flash8 = 0; int16_t flash16 = 0; size_t required_size; // check if configuration stored in NVRAM matches PROGVERSION - if (nvs_get_str(my_handle, "version", NULL, &required_size) == ESP_OK) { + if( nvs_get_str(my_handle, "version", NULL, &required_size) == ESP_OK ) { nvs_get_str(my_handle, "version", cfg.version, &required_size); ESP_LOGI(TAG, "NVRAM settings version = %s", cfg.version); if (strcmp(cfg.version, PROGVERSION)) { - ESP_LOGI(TAG, "migrating NVRAM settings to new version %s", - PROGVERSION); + ESP_LOGI(TAG, "migrating NVRAM settings to new version %s", PROGVERSION); nvs_close(my_handle); migrateVersion(); } } else { - ESP_LOGI(TAG, "new version %s, deleting NVRAM settings", PROGVERSION); - nvs_close(my_handle); - eraseConfig(); - migrateVersion(); + ESP_LOGI(TAG, "new version %s, deleting NVRAM settings", PROGVERSION); + nvs_close(my_handle); + eraseConfig(); + migrateVersion(); } // overwrite defaults with valid values from NVRAM - if (nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK ) { cfg.lorasf = flash8; ESP_LOGI(TAG, "lorasf = %d", flash8); } else { @@ -208,7 +184,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "txpower", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "txpower", &flash8) == ESP_OK ) { cfg.txpower = flash8; ESP_LOGI(TAG, "txpower = %d", flash8); } else { @@ -216,7 +192,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "adrmode", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "adrmode", &flash8) == ESP_OK ) { cfg.adrmode = flash8; ESP_LOGI(TAG, "adrmode = %d", flash8); } else { @@ -224,7 +200,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "screensaver", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "screensaver", &flash8) == ESP_OK ) { cfg.screensaver = flash8; ESP_LOGI(TAG, "screensaver = %d", flash8); } else { @@ -232,7 +208,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "screenon", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "screenon", &flash8) == ESP_OK ) { cfg.screenon = flash8; ESP_LOGI(TAG, "screenon = %d", flash8); } else { @@ -240,7 +216,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "countermode", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "countermode", &flash8) == ESP_OK ) { cfg.countermode = flash8; ESP_LOGI(TAG, "countermode = %d", flash8); } else { @@ -248,7 +224,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "sendcycle", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "sendcycle", &flash8) == ESP_OK ) { cfg.sendcycle = flash8; ESP_LOGI(TAG, "sendcycle = %d", flash8); } else { @@ -256,7 +232,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "wifichancycle", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "wifichancycle", &flash8) == ESP_OK ) { cfg.wifichancycle = flash8; ESP_LOGI(TAG, "wifichancycle = %d", flash8); } else { @@ -264,7 +240,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "wifiant", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "wifiant", &flash8) == ESP_OK ) { cfg.wifiant = flash8; ESP_LOGI(TAG, "wifiantenna = %d", flash8); } else { @@ -272,7 +248,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "vendorfilter", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "vendorfilter", &flash8) == ESP_OK ) { cfg.vendorfilter = flash8; ESP_LOGI(TAG, "vendorfilter = %d", flash8); } else { @@ -280,7 +256,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "rgblum", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "rgblum", &flash8) == ESP_OK ) { cfg.rgblum = flash8; ESP_LOGI(TAG, "rgbluminosity = %d", flash8); } else { @@ -288,7 +264,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "blescantime", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "blescantime", &flash8) == ESP_OK ) { cfg.blescantime = flash8; ESP_LOGI(TAG, "blescantime = %d", flash8); } else { @@ -296,7 +272,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "blescanmode", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "blescanmode", &flash8) == ESP_OK ) { cfg.blescan = flash8; ESP_LOGI(TAG, "BLEscanmode = %d", flash8); } else { @@ -304,7 +280,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i16(my_handle, "rssilimit", &flash16) == ESP_OK) { + if( nvs_get_i16(my_handle, "rssilimit", &flash16) == ESP_OK ) { cfg.rssilimit = flash16; ESP_LOGI(TAG, "rssilimit = %d", flash16); } else { @@ -312,7 +288,7 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "gpsmode", &flash8) == ESP_OK) { + if( nvs_get_i8(my_handle, "gpsmode", &flash8) == ESP_OK ) { cfg.gpsmode = flash8; ESP_LOGI(TAG, "GPSmode = %d", flash8); } else { @@ -324,9 +300,9 @@ void loadConfig() { ESP_LOGI(TAG, "Done"); // put actions to be triggered after config loaded here - -#ifdef HAS_ANTENNA_SWITCH // set antenna type, if device has one - antenna_select(cfg.wifiant); -#endif - } + + #ifdef HAS_ANTENNA_SWITCH // set antenna type, if device has one + antenna_select(cfg.wifiant); + #endif + } } diff --git a/src/globals.h b/src/globals.h index 72b1c735..04ef15d7 100644 --- a/src/globals.h +++ b/src/globals.h @@ -2,63 +2,63 @@ #include // std::set for unified array functions -#include -#include #include +#include +#include // OLED Display #ifdef HAS_DISPLAY -#include + #include #endif -// GPS +//GPS #ifdef HAS_GPS -#include + #include #endif // LMIC-Arduino LoRaWAN Stack -#include #include +#include // LED controls #ifdef HAS_RGB_LED -#include + #include #endif +#include "rgb_led.h" #include "macsniff.h" #include "main.h" -#include "rgb_led.h" // Struct holding devices's runtime configuration typedef struct { - uint8_t lorasf; // 7-12, lora spreadfactor - uint8_t txpower; // 2-15, lora tx power - uint8_t adrmode; // 0=disabled, 1=enabled - uint8_t screensaver; // 0=disabled, 1=enabled - uint8_t screenon; // 0=disabled, 1=enabled - uint8_t countermode; // 0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed - int16_t rssilimit; // threshold for rssilimiter, negative value! - uint8_t sendcycle; // payload send cycle [seconds/2] - uint8_t wifichancycle; // wifi channel switch cycle [seconds/100] - uint8_t blescantime; // BLE scan cycle duration [seconds] - uint8_t blescan; // 0=disabled, 1=enabled - uint8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4) - uint8_t vendorfilter; // 0=disabled, 1=enabled - uint8_t rgblum; // RGB Led luminosity (0..100%) - uint8_t gpsmode; // 0=disabled, 1=enabled - char version[10]; // Firmware version -} configData_t; + uint8_t lorasf; // 7-12, lora spreadfactor + uint8_t txpower; // 2-15, lora tx power + uint8_t adrmode; // 0=disabled, 1=enabled + uint8_t screensaver; // 0=disabled, 1=enabled + uint8_t screenon; // 0=disabled, 1=enabled + uint8_t countermode; // 0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed + int16_t rssilimit; // threshold for rssilimiter, negative value! + uint8_t sendcycle; // payload send cycle [seconds/2] + uint8_t wifichancycle; // wifi channel switch cycle [seconds/100] + uint8_t blescantime; // BLE scan cycle duration [seconds] + uint8_t blescan; // 0=disabled, 1=enabled + uint8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4) + uint8_t vendorfilter; // 0=disabled, 1=enabled + uint8_t rgblum; // RGB Led luminosity (0..100%) + uint8_t gpsmode; // 0=disabled, 1=enabled + char version[10]; // Firmware version + } configData_t; #ifdef HAS_GPS -typedef struct { - uint32_t latitude; - uint32_t longitude; - uint8_t satellites; - uint16_t hdop; - uint16_t altitude; -} gpsStatus_t; -extern gpsStatus_t gps_status; // struct for storing gps data -extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe + typedef struct { + uint32_t latitude; + uint32_t longitude; + uint8_t satellites; + uint16_t hdop; + uint16_t altitude; + } gpsStatus_t; + extern gpsStatus_t gps_status; // struct for storing gps data + extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe #endif extern configData_t cfg; @@ -68,7 +68,6 @@ extern char display_lora[], display_lmic[]; extern int countermode, screensaver, adrmode, lorasf, txpower, rlim; extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters extern std::set macs; -extern hw_timer_t - *channelSwitch; // hardware timer used for wifi channel switching -extern xref2u1_t rcmd_data; // buffer for rcommand results size -extern u1_t rcmd_data_size; // buffer for rcommand results size +extern hw_timer_t * channelSwitch; // hardware timer used for wifi channel switching +extern xref2u1_t rcmd_data; // buffer for rcommand results size +extern u1_t rcmd_data_size; // buffer for rcommand results size diff --git a/src/gpsread.cpp b/src/gpsread.cpp index ebe16999..eb38eb73 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -7,73 +7,74 @@ static const char TAG[] = "main"; // read GPS data and cast to global struct void gps_read() { - gps_status.latitude = (uint32_t)(gps.location.lat() * 1000000); - gps_status.longitude = (uint32_t)(gps.location.lng() * 1000000); - gps_status.satellites = (uint8_t)gps.satellites.value(); - gps_status.hdop = (uint16_t)gps.hdop.value(); - gps_status.altitude = (uint16_t)gps.altitude.meters(); + gps_status.latitude = (uint32_t) (gps.location.lat() * 1000000); + gps_status.longitude = (uint32_t) (gps.location.lng() * 1000000); + gps_status.satellites = (uint8_t) gps.satellites.value(); + gps_status.hdop = (uint16_t) gps.hdop.value(); + gps_status.altitude = (uint16_t) gps.altitude.meters(); } // GPS serial feed FreeRTos Task -void gps_loop(void *pvParameters) { +void gps_loop(void * pvParameters) { - configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check + configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check -// initialize and, if needed, configure, GPS -#if defined GPS_SERIAL - HardwareSerial GPS_Serial(1); -#elif defined GPS_I2C - // to be done -#endif + // initialize and, if needed, configure, GPS + #if defined GPS_SERIAL + HardwareSerial GPS_Serial(1); + #elif defined GPS_I2C + // to be done + #endif - while (1) { + while(1) { - if (cfg.gpsmode) { -#if defined GPS_SERIAL + if (cfg.gpsmode) + { + #if defined GPS_SERIAL + + // serial connect to GPS device + GPS_Serial.begin(GPS_SERIAL); + + while(cfg.gpsmode) { + // feed GPS decoder with serial NMEA data from GPS device + while (GPS_Serial.available()) { + gps.encode(GPS_Serial.read()); + } + vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog + } + // after GPS function was disabled, close connect to GPS device + GPS_Serial.end(); - // serial connect to GPS device - GPS_Serial.begin(GPS_SERIAL); + #elif defined GPS_I2C + + // I2C connect to GPS device with 100 kHz + Wire.begin(GPS_I2C_PINS, 100000); + Wire.beginTransmission(GPS_I2C_ADDRESS_WRITE); + Wire.write(0x00); - while (cfg.gpsmode) { - // feed GPS decoder with serial NMEA data from GPS device - while (GPS_Serial.available()) { - gps.encode(GPS_Serial.read()); + i2c_ret == Wire.beginTransmission(GPS_I2C_ADDRESS_READ); + if (i2c_ret == 0) { // check if device seen on i2c bus + while(cfg.gpsmode) { + // feed GPS decoder with serial NMEA data from GPS device + while (Wire.available()) { + Wire.requestFrom(GPS_I2C_ADDRESS_READ, 255); + gps.encode(Wire.read()); + vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog + } + } + // after GPS function was disabled, close connect to GPS device + + Wire.endTransmission(); + Wire.setClock(400000); // Set back to 400KHz to speed up OLED + } + + #endif } - vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog - } - // after GPS function was disabled, close connect to GPS device - GPS_Serial.end(); + + vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog -#elif defined GPS_I2C - - // I2C connect to GPS device with 100 kHz - Wire.begin(GPS_I2C_PINS, 100000); - Wire.beginTransmission(GPS_I2C_ADDRESS_WRITE); - Wire.write(0x00); - - i2c_ret == Wire.beginTransmission(GPS_I2C_ADDRESS_READ); - if (i2c_ret == 0) { // check if device seen on i2c bus - while (cfg.gpsmode) { - // feed GPS decoder with serial NMEA data from GPS device - while (Wire.available()) { - Wire.requestFrom(GPS_I2C_ADDRESS_READ, 255); - gps.encode(Wire.read()); - vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog - } - } - // after GPS function was disabled, close connect to GPS device - - Wire.endTransmission(); - Wire.setClock(400000); // Set back to 400KHz to speed up OLED - } - -#endif - } - - vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog - - } // end of infinite loop + } // end of infinite loop } // gps_loop() - + #endif // HAS_GPS \ No newline at end of file diff --git a/src/hal/fipy.h b/src/hal/fipy.h index 25128d2b..9f88928d 100644 --- a/src/hal/fipy.h +++ b/src/hal/fipy.h @@ -1,19 +1,19 @@ // Hardware related definitions for Pycom FiPy Board #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_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 // Hardware pin definitions for Pycom FiPy board -#define PIN_SPI_SS GPIO_NUM_18 -#define PIN_SPI_MOSI GPIO_NUM_27 -#define PIN_SPI_MISO GPIO_NUM_19 -#define PIN_SPI_SCK GPIO_NUM_5 -#define RST LMIC_UNUSED_PIN -#define DIO0 GPIO_NUM_23 // LoRa IRQ -#define DIO1 GPIO_NUM_23 // workaround -#define DIO2 LMIC_UNUSED_PIN +#define PIN_SPI_SS GPIO_NUM_18 +#define PIN_SPI_MOSI GPIO_NUM_27 +#define PIN_SPI_MISO GPIO_NUM_19 +#define PIN_SPI_SCK GPIO_NUM_5 +#define RST LMIC_UNUSED_PIN +#define DIO0 GPIO_NUM_23 // LoRa IRQ +#define DIO1 GPIO_NUM_23 // workaround +#define DIO2 LMIC_UNUSED_PIN // select WIFI antenna (internal = onboard / external = u.fl socket) -#define HAS_ANTENNA_SWITCH GPIO_NUM_21 // pin for switching wifi antenna -#define WIFI_ANTENNA 0 // 0 = internal, 1 = external +#define HAS_ANTENNA_SWITCH GPIO_NUM_21 // pin for switching wifi antenna +#define WIFI_ANTENNA 0 // 0 = internal, 1 = external diff --git a/src/hal/heltec.h b/src/hal/heltec.h index 15c43c95..74bdb89a 100644 --- a/src/hal/heltec.h +++ b/src/hal/heltec.h @@ -4,36 +4,22 @@ #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board //#define DISPLAY_FLIP 1 // uncomment this for rotated display -#define HAS_LED GPIO_NUM_25 // white LED on board +#define HAS_LED GPIO_NUM_25 // white LED on board #define HAS_BUTTON GPIO_NUM_0 // button "PROG" on board // re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS \ - GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select - // Input -#define PIN_SPI_MOSI \ - GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO \ - GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK \ - GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input +#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select Input +#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input +#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output +#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input // non arduino pin definitions -#define RST \ - GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger - // Input -#define DIO0 \ - GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for - // detecting LoRa RX_Done & TX_Done -#define DIO1 \ - GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for - // detecting LoRa RX_Timeout -#define DIO2 \ - LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by - // LMIC for LoRa (Timeout for FSK only) +#define RST GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input +#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done +#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout +#define DIO2 LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) -// Hardware pin definitions for Heltec LoRa-32 Board with OLED SSD1306 I2C -// Display +// Hardware pin definitions for Heltec LoRa-32 Board with OLED SSD1306 I2C Display #define OLED_RST GPIO_NUM_16 // ESP32 GPIO16 (Pin16) -- SD1306 RST #define OLED_SDA GPIO_NUM_4 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 #define OLED_SCL GPIO_NUM_15 // ESP32 GPIO15 (Pin15) -- SD1306 D0 diff --git a/src/hal/lolin32_lora.h b/src/hal/lolin32_lora.h index 1c3e7676..ca5929af 100644 --- a/src/hal/lolin32_lora.h +++ b/src/hal/lolin32_lora.h @@ -6,50 +6,33 @@ #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board //#define DISPLAY_FLIP 1 // uncomment this for rotated display -#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_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield -#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown +#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_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield +#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown #define CFG_sx1276_radio 1 // RFM95 module // re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS \ - 5 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input -#define PIN_SPI_MOSI \ - 23 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO \ - 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK \ - 18 // ESP32 GPIO18 (Pin18 -- SX1276 SCK (Pin16) SPI Clock Input +#define PIN_SPI_SS 5 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input +#define PIN_SPI_MOSI 23 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input +#define PIN_SPI_MISO 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output +#define PIN_SPI_SCK 18 // ESP32 GPIO18 (Pin18 -- SX1276 SCK (Pin16) SPI Clock Input // non arduino pin definitions -#define RST \ - 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input -#define DIO0 \ - 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting - // LoRa RX_Done & TX_Done -#define DIO1 \ - 26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting - // LoRa RX_Timeout -#define DIO2 \ - LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by - // LMIC for LoRa (Timeout for FSK only) -#define DIO5 \ - LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC - // for LoRa (Timeout for FSK only) +#define RST 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input +#define DIO0 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done +#define DIO1 26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout +#define DIO2 LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) +#define DIO5 LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) // Hardware pin definitions for LoRaNode32 Board with OLED I2C Display -#define OLED_RST U8X8_PIN_NONE // Not reset pin -#define OLED_SDA 21 // ESP32 GPIO21 (Pin21) -- OLED SDA -#define OLED_SCL 22 // ESP32 GPIO22 (Pin22) -- OLED SCL +#define OLED_RST U8X8_PIN_NONE // Not reset pin +#define OLED_SDA 21 // ESP32 GPIO21 (Pin21) -- OLED SDA +#define OLED_SCL 22 // ESP32 GPIO22 (Pin22) -- OLED SCL // I2C config for Microchip 24AA02E64 DEVEUI unique address -#define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64 +#define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64 #define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits diff --git a/src/hal/lolin32lite_lora.h b/src/hal/lolin32lite_lora.h index 99bf740e..51cd6f10 100644 --- a/src/hal/lolin32lite_lora.h +++ b/src/hal/lolin32lite_lora.h @@ -6,45 +6,32 @@ #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board //#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_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield -#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown +#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_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield +#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown #define CFG_sx1276_radio 1 // RFM95 module // re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS \ - 5 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input -#define PIN_SPI_MOSI \ - 23 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO \ - 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK \ - 18 // ESP32 GPIO18 (Pin18 -- SX1276 SCK (Pin16) SPI Clock Input +#define PIN_SPI_SS 5 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input +#define PIN_SPI_MOSI 23 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input +#define PIN_SPI_MISO 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output +#define PIN_SPI_SCK 18 // ESP32 GPIO18 (Pin18 -- SX1276 SCK (Pin16) SPI Clock Input // non arduino pin definitions -#define RST \ - 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input -#define DIO0 \ - 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting - // LoRa RX_Done & TX_Done -#define DIO1 \ - 26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting - // LoRa RX_Timeout -#define DIO2 \ - LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by - // LMIC for LoRa (Timeout for FSK only) -#define DIO5 \ - LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC - // for LoRa (Timeout for FSK only) +#define RST 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input +#define DIO0 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done +#define DIO1 26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout +#define DIO2 LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) +#define DIO5 LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) // Hardware pin definitions for LoRaNode32 Board with OLED I2C Display -#define OLED_RST U8X8_PIN_NONE // Not reset pin -#define OLED_SDA 14 // ESP32 GPIO14 (Pin14) -- OLED SDA -#define OLED_SCL 12 // ESP32 GPIO12 (Pin12) -- OLED SCL +#define OLED_RST U8X8_PIN_NONE // Not reset pin +#define OLED_SDA 14 // ESP32 GPIO14 (Pin14) -- OLED SDA +#define OLED_SCL 12 // ESP32 GPIO12 (Pin12) -- OLED SCL // I2C config for Microchip 24AA02E64 DEVEUI unique address -#define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64 +#define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64 #define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits diff --git a/src/hal/lopy.h b/src/hal/lopy.h index 0f64fa94..d54004f6 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -1,14 +1,12 @@ // Hardware related definitions for Pycom LoPy Board (not: LoPy4) #define CFG_sx1272_radio 1 -#define HAS_LED \ - NOT_A_PIN // LoPy4 has no on board LED, so we use RGB LED on LoPy4 -#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 +#define HAS_LED NOT_A_PIN // LoPy4 has no on board LED, so we use RGB LED on LoPy4 +#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 // !!EXPERIMENTAL - not tested yet!! // uncomment this only if your LoPy lives on a Pytrack expansion board with GPS -// see -// http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf +// see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf //#define HAS_GPS 1 //#define GPS_I2C_PINS GPIO_NUM_9, GPIO_NUM_8 // SDA, SCL //#define GPS_I2C_ADDRESS_READ 0x21 @@ -16,15 +14,15 @@ //#define HAS_BUTTON GPIO_NUM_4 // Hardware pin definitions for Pycom LoPy board -#define PIN_SPI_SS GPIO_NUM_17 -#define PIN_SPI_MOSI GPIO_NUM_27 -#define PIN_SPI_MISO GPIO_NUM_19 -#define PIN_SPI_SCK GPIO_NUM_5 -#define RST GPIO_NUM_18 -#define DIO0 GPIO_NUM_23 // LoRa IRQ -#define DIO1 GPIO_NUM_23 // workaround -#define DIO2 LMIC_UNUSED_PIN +#define PIN_SPI_SS GPIO_NUM_17 +#define PIN_SPI_MOSI GPIO_NUM_27 +#define PIN_SPI_MISO GPIO_NUM_19 +#define PIN_SPI_SCK GPIO_NUM_5 +#define RST GPIO_NUM_18 +#define DIO0 GPIO_NUM_23 // LoRa IRQ +#define DIO1 GPIO_NUM_23 // workaround +#define DIO2 LMIC_UNUSED_PIN // select WIFI antenna (internal = onboard / external = u.fl socket) -#define HAS_ANTENNA_SWITCH 16 // pin for switching wifi antenna -#define WIFI_ANTENNA 0 // 0 = internal, 1 = external +#define HAS_ANTENNA_SWITCH 16 // pin for switching wifi antenna +#define WIFI_ANTENNA 0 // 0 = internal, 1 = external diff --git a/src/hal/lopy4.h b/src/hal/lopy4.h index 8e3acc6e..708a861d 100644 --- a/src/hal/lopy4.h +++ b/src/hal/lopy4.h @@ -1,14 +1,12 @@ // Hardware related definitions for Pycom LoPy Board (not: LoPy4) #define CFG_sx1276_radio 1 -#define HAS_LED \ - NOT_A_PIN // LoPy4 has no on board LED, so we use RGB LED on LoPy4 -#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 +#define HAS_LED NOT_A_PIN // LoPy4 has no on board LED, so we use RGB LED on LoPy4 +#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 // !!EXPERIMENTAL - not tested yet!!f // uncomment this only if your LoPy lives on a Pytrack expansion board with GPS -// see -// http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf +// see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf //#define HAS_GPS 1 //#define GPS_I2C_PINS GPIO_NUM_9, GPIO_NUM_8 // SDA, SCL //#define GPS_I2C_ADDRESS_READ 0x21 @@ -16,15 +14,15 @@ //#define HAS_BUTTON GPIO_NUM_4 // Hardware pin definitions for Pycom LoPy4 board -#define PIN_SPI_SS GPIO_NUM_18 -#define PIN_SPI_MOSI GPIO_NUM_27 -#define PIN_SPI_MISO GPIO_NUM_19 -#define PIN_SPI_SCK GPIO_NUM_5 -#define RST LMIC_UNUSED_PIN -#define DIO0 GPIO_NUM_23 // LoRa IRQ -#define DIO1 GPIO_NUM_23 // workaround -#define DIO2 LMIC_UNUSED_PIN +#define PIN_SPI_SS GPIO_NUM_18 +#define PIN_SPI_MOSI GPIO_NUM_27 +#define PIN_SPI_MISO GPIO_NUM_19 +#define PIN_SPI_SCK GPIO_NUM_5 +#define RST LMIC_UNUSED_PIN +#define DIO0 GPIO_NUM_23 // LoRa IRQ +#define DIO1 GPIO_NUM_23 // workaround +#define DIO2 LMIC_UNUSED_PIN // select WIFI antenna (internal = onboard / external = u.fl socket) -#define HAS_ANTENNA_SWITCH 21 // pin for switching wifi antenna -#define WIFI_ANTENNA 0 // 0 = internal, 1 = external \ No newline at end of file +#define HAS_ANTENNA_SWITCH 21 // pin for switching wifi antenna +#define WIFI_ANTENNA 0 // 0 = internal, 1 = external \ No newline at end of file diff --git a/src/hal/ttgobeam.h b/src/hal/ttgobeam.h index f1d24830..aafbb3a9 100644 --- a/src/hal/ttgobeam.h +++ b/src/hal/ttgobeam.h @@ -3,31 +3,20 @@ #define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define HAS_LED GPIO_NUM_21 // on board green LED_G1 -//#define HAS_BUTTON GPIO_NUM_39 // on board button "BOOT" (next to reset -// button) !! seems not to work!! -#define HAS_BATTERY_PROBE \ - ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 +//#define HAS_BUTTON GPIO_NUM_39 // on board button "BOOT" (next to reset button) !! seems not to work!! +#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 #define BATT_FACTOR 2 // voltage divider 100k/100k on board -#define HAS_GPS 1 // use on board GPS -#define GPS_SERIAL \ - 9600, SERIAL_8N1, GPIO_NUM_12, \ - GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration +#define HAS_GPS 1 // use on board GPS +#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration // 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_MOSI \ - GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input -#define PIN_SPI_MISO \ - GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output -#define PIN_SPI_SCK \ - GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input +#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input +#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input +#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output +#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input // non arduino pin definitions -#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0 -#define DIO1 GPIO_NUM_33 // Lora1 <-> HPD13A IO1 // !! NEEDS EXTERNAL WIRING !! -#define DIO2 \ - LMIC_UNUSED_PIN // Lora2 <-> HPD13A IO2 // needs external wiring, but not - // necessary for LoRa, only FSK +#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN +#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0 +#define DIO1 GPIO_NUM_33 // Lora1 <-> HPD13A IO1 // !! NEEDS EXTERNAL WIRING !! +#define DIO2 LMIC_UNUSED_PIN // Lora2 <-> HPD13A IO2 // needs external wiring, but not necessary for LoRa, only FSK diff --git a/src/hal/ttgov1.h b/src/hal/ttgov1.h index 0d175957..df5735b5 100644 --- a/src/hal/ttgov1.h +++ b/src/hal/ttgov1.h @@ -4,34 +4,21 @@ #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board //#define DISPLAY_FLIP 1 // uncomment this for rotated display -#define HAS_LED GPIO_NUM_2 // white LED on board -#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW +#define HAS_LED GPIO_NUM_2 // white LED on board +#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW #define HAS_BUTTON GPIO_NUM_0 // button "PRG" on board // re-define pin definitions of pins_arduino.h -#define PIN_SPI_SS \ - GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select - // Input -#define PIN_SPI_MOSI \ - GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input -#define PIN_SPI_MISO \ - GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output -#define PIN_SPI_SCK \ - GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input +#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select Input +#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input +#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output +#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input // non arduino pin definitions -#define RST \ - GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger - // Input -#define DIO0 \ - GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for - // detecting LoRa RX_Done & TX_Done -#define DIO1 \ - GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for - // detecting LoRa RX_Timeout -#define DIO2 \ - LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by - // LMIC for LoRa (Timeout for FSK only) +#define RST GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input +#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done +#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout +#define DIO2 LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) // Hardware pin definitions for TTGOv1 Board with OLED SSD1306 I2C Display #define OLED_RST GPIO_NUM_16 // ESP32 GPIO16 (Pin16) -- SD1306 Reset diff --git a/src/hal/ttgov2.h b/src/hal/ttgov2.h index 38c313fc..e4bb49b4 100644 --- a/src/hal/ttgov2.h +++ b/src/hal/ttgov2.h @@ -4,37 +4,28 @@ #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C //#define DISPLAY_FLIP 1 // uncomment this for rotated display -#define HAS_LED \ - NOT_A_PIN // on-board LED is wired to SCL (used by display) therefore totally - // useless +#define HAS_LED NOT_A_PIN // on-board LED is wired to SCL (used by display) therefore totally useless // disable brownout detection (needed on TTGOv2 for battery powered operation) #define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature // 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_MOSI \ - GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input -#define PIN_SPI_MISO \ - GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output -#define PIN_SPI_SCK \ - GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input +#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input +#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input +#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output +#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input // non arduino pin definitions -#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 wired on PCB to HPD13A -#define DIO1 GPIO_NUM_33 // HPDIO1 on pcb, needs to be wired external to GPIO33 -#define DIO2 \ - LMIC_UNUSED_PIN // 32 HPDIO2 on pcb, needs to be wired external to GPIO32 (not - // necessary for LoRa, only FSK) +#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN +#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 wired on PCB to HPD13A +#define DIO1 GPIO_NUM_33 // HPDIO1 on pcb, needs to be wired external to GPIO33 +#define DIO2 LMIC_UNUSED_PIN // 32 HPDIO2 on pcb, needs to be wired external to GPIO32 (not necessary for LoRa, only FSK) -// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C -// Display +// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display #define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN -#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 -#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO15 (Pin15) -- SD1306 D0 +#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 +#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO15 (Pin15) -- SD1306 D0 + /* ESP32 LoRa module (SPI) OLED display (I2C) @@ -57,6 +48,6 @@ {2} Must be manually wired! DIO2 is wired to a separate pin but is not wired on-board to pin/GPIO32. Explicitly wire board pin labeled DIO2 to pin 32 (see TTGO V2.0 pinout). - {3} The on-board LED is wired to SCL (used by display) therefore totally - useless! + {3} The on-board LED is wired to SCL (used by display) therefore totally useless! */ + diff --git a/src/hal/ttgov21.h b/src/hal/ttgov21.h index 59aaf41d..1e3b38ec 100644 --- a/src/hal/ttgov21.h +++ b/src/hal/ttgov21.h @@ -3,32 +3,24 @@ #define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C -#define DISPLAY_FLIP 1 // rotated display -#define HAS_LED \ - GPIO_NUM_23 // green on board LED_G3 (not in initial board version) -#define HAS_BATTERY_PROBE \ - ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 +#define DISPLAY_FLIP 1 // rotated display +#define HAS_LED GPIO_NUM_23 // green on board LED_G3 (not in initial board version) +#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 #define BATT_FACTOR 2 // voltage divider 100k/100k on board // 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_MOSI \ - GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input -#define PIN_SPI_MISO \ - GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output -#define PIN_SPI_SCK \ - GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input +#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input +#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input +#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output +#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input // non arduino pin definitions -#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN -#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0 -#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1 -#define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2 +#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN +#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0 +#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1 +#define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2 -// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C -// Display +// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display #define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN -#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 -#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO15 (Pin15) -- SD1306 D0 \ No newline at end of file +#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 +#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO15 (Pin15) -- SD1306 D0 \ No newline at end of file diff --git a/src/loraconf.sample.h b/src/loraconf.sample.h index 9cb04154..ec816959 100644 --- a/src/loraconf.sample.h +++ b/src/loraconf.sample.h @@ -1,31 +1,28 @@ /************************************************************ * LMIC LoRaWAN configuration - * + * * Read the values from TTN console (or whatever applies), insert them here, * and rename this file to src/loraconf.h - * + * * Note that DEVEUI, APPEUI and APPKEY should all be specified in MSB format. - * (This is different from standard LMIC-Arduino which expects DEVEUI and APPEUI - in LSB format.) + * (This is different from standard LMIC-Arduino which expects DEVEUI and APPEUI in LSB format.) - * Set your DEVEUI here, if you have one. You can leave this untouched, + * Set your DEVEUI here, if you have one. You can leave this untouched, * then the DEVEUI will be generated during runtime from device's MAC adress * and will be displayed on device's screen as well as on serial console. - * - * NOTE: Use MSB format (as displayed in TTN console, so you can cut & paste - from there) + * + * NOTE: Use MSB format (as displayed in TTN console, so you can cut & paste from there) * For TTN, APPEUI in MSB format always starts with 0x70, 0xB3, 0xD5 * * Note: If using a board with Microchip 24AA02E64 Uinique ID for deveui, * the DEVEUI will be overwriten by the one contained in the Microchip module - * + * ************************************************************/ #include -static const u1_t DEVEUI[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const u1_t DEVEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static const u1_t APPEUI[8] = {0x70, 0xB3, 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const u1_t APPEUI[8]={ 0x70, 0xB3, 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static const u1_t APPKEY[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; \ No newline at end of file +static const u1_t APPKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; \ No newline at end of file diff --git a/src/lorawan.cpp b/src/lorawan.cpp index a9260bc9..b832b311 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -3,11 +3,11 @@ // LMIC-Arduino LoRaWAN Stack #include "loraconf.h" -#include #include +#include #ifdef MCP_24AA02E64_I2C_ADDRESS -#include // Needed for 24AA02E64, does not hurt anything if included and not used + #include // Needed for 24AA02E64, does not hurt anything if included and not used #endif // Local logging Tag @@ -19,257 +19,219 @@ 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]; - int i = 0; - esp_efuse_mac_get_default(dmac); - // deveui is LSB, we reverse it so TTN DEVEUI display - // will remain the same as MAC address - // MAC is 6 bytes, devEUI 8, set first 2 ones - // with an arbitrary value - *p++ = 0xFF; - *p++ = 0xFE; - // Then next 6 bytes are mac address reversed - for (i = 0; i < 6; i++) { - *p++ = dmac[5 - i]; - } + uint8_t *p = pdeveui, dmac[6]; + int i = 0; + esp_efuse_mac_get_default(dmac); + // deveui is LSB, we reverse it so TTN DEVEUI display + // will remain the same as MAC address + // MAC is 6 bytes, devEUI 8, set first 2 ones + // with an arbitrary value + *p++ = 0xFF; + *p++ = 0xFE; + // Then next 6 bytes are mac address reversed + for ( i=0; i<6 ; i++) { + *p++ = dmac[5-i]; + } } // Function to do a byte swap in a byte array -void RevBytes(unsigned char *b, size_t c) { +void RevBytes(unsigned char* b, size_t c) +{ u1_t i; - for (i = 0; i < c / 2; i++) { - unsigned char t = b[i]; + for (i = 0; i < c / 2; i++) + { unsigned char t = b[i]; b[i] = b[c - 1 - i]; - b[c - 1 - i] = t; - } + b[c - 1 - i] = t; } } void get_hard_deveui(uint8_t *pdeveui) { -// read DEVEUI from Microchip 24AA02E64 2Kb serial eeprom if present + // read DEVEUI from Microchip 24AA02E64 2Kb serial eeprom if present #ifdef MCP_24AA02E64_I2C_ADDRESS - uint8_t i2c_ret; - // Init this just in case, no more to 100KHz - Wire.begin(OLED_SDA, OLED_SCL, 100000); - Wire.beginTransmission(MCP_24AA02E64_I2C_ADDRESS); - Wire.write(MCP_24AA02E64_MAC_ADDRESS); - i2c_ret = Wire.endTransmission(); - // check if device seen on i2c bus - if (i2c_ret == 0) { - char deveui[32] = ""; - uint8_t data; + uint8_t i2c_ret; + // Init this just in case, no more to 100KHz + Wire.begin(OLED_SDA, OLED_SCL, 100000); Wire.beginTransmission(MCP_24AA02E64_I2C_ADDRESS); - Wire.write(MCP_24AA02E64_MAC_ADDRESS); - Wire.requestFrom(MCP_24AA02E64_I2C_ADDRESS, 8); - while (Wire.available()) { - data = Wire.read(); - sprintf(deveui + strlen(deveui), "%02X ", data); - *pdeveui++ = data; - } + Wire.write(MCP_24AA02E64_MAC_ADDRESS); i2c_ret = Wire.endTransmission(); - ESP_LOGI(TAG, "Serial EEPROM 24AA02E64 found, read DEVEUI %s", deveui); - } else { - ESP_LOGI(TAG, "Serial EEPROM 24AA02E64 not found ret=%d", i2c_ret); - } - // Set back to 400KHz to speed up OLED - Wire.setClock(400000); -#endif // MCP 24AA02E64 + // check if device seen on i2c bus + if (i2c_ret == 0) { + char deveui[32]=""; + uint8_t data; + Wire.beginTransmission(MCP_24AA02E64_I2C_ADDRESS); + Wire.write(MCP_24AA02E64_MAC_ADDRESS); + Wire.requestFrom(MCP_24AA02E64_I2C_ADDRESS, 8); + while (Wire.available()) { + data = Wire.read(); + sprintf(deveui+strlen(deveui), "%02X ", data); + *pdeveui++ = data; + } + i2c_ret = Wire.endTransmission(); + ESP_LOGI(TAG, "Serial EEPROM 24AA02E64 found, read DEVEUI %s", deveui); + } else { + ESP_LOGI(TAG, "Serial EEPROM 24AA02E64 not found ret=%d", i2c_ret); + } + // Set back to 400KHz to speed up OLED + Wire.setClock(400000); +#endif // MCP 24AA02E64 } #ifdef VERBOSE // Display a key -void printKey(const char *name, const uint8_t *key, uint8_t len, bool lsb) { - const uint8_t *p; - char keystring[len + 1] = "", keybyte[3]; - for (uint8_t i = 0; i < len; i++) { - p = lsb ? key + len - i - 1 : key + i; - sprintf(keybyte, "%02X", *p); - strncat(keystring, keybyte, 2); - } +void printKey(const char * name, const uint8_t * key, uint8_t len, bool lsb) { + const uint8_t * p ; + char keystring[len+1] = "", keybyte[3]; + for (uint8_t i=0; i> 8; - mydata[1] = macs_wifi & 0xff; + mydata[0] = (macs_wifi & 0xff00) >> 8; + mydata[1] = macs_wifi & 0xff; + + if (cfg.blescan) { + // append sum of unique BLE MACs seen to payload + mydata[2] = (macs_ble & 0xff00) >> 8; + mydata[3] = macs_ble & 0xff; + } else { + mydata[2] = 0; + mydata[3] = 0; + } - if (cfg.blescan) { - // append sum of unique BLE MACs seen to payload - mydata[2] = (macs_ble & 0xff00) >> 8; - mydata[3] = macs_ble & 0xff; - } else { - mydata[2] = 0; - mydata[3] = 0; - } + #ifdef HAS_GPS + static uint8_t gpsdata[18]; + if (cfg.gpsmode && gps.location.isValid()) { + gps_read(); + memcpy (gpsdata, mydata, 4); + memcpy (gpsdata+4, &gps_status, sizeof(gps_status)); + ESP_LOGI(TAG, "lat=%.6f / lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%u m", \ + gps_status.latitude / (float) 1000000, \ + gps_status.longitude / (float) 1000000, \ + gps_status.satellites, \ + gps_status.hdop / (float) 100, \ + gps_status.altitude); + LMIC_setTxData2(COUNTERPORT, gpsdata, sizeof(gpsdata), (cfg.countermode & 0x02)); + ESP_LOGI(TAG, "%d bytes queued to send", sizeof(gpsdata)); + } + else { + #endif + LMIC_setTxData2(COUNTERPORT, mydata, sizeof(mydata), (cfg.countermode & 0x02)); + ESP_LOGI(TAG, "%d bytes queued to send", sizeof(mydata)); + sprintf(display_lmic, "PACKET QUEUED"); -#ifdef HAS_GPS - static uint8_t gpsdata[18]; - if (cfg.gpsmode && gps.location.isValid()) { - gps_read(); - memcpy(gpsdata, mydata, 4); - memcpy(gpsdata + 4, &gps_status, sizeof(gps_status)); - ESP_LOGI(TAG, "lat=%.6f / lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%u m", - gps_status.latitude / (float)1000000, - gps_status.longitude / (float)1000000, gps_status.satellites, - gps_status.hdop / (float)100, gps_status.altitude); - LMIC_setTxData2(COUNTERPORT, gpsdata, sizeof(gpsdata), - (cfg.countermode & 0x02)); - ESP_LOGI(TAG, "%d bytes queued to send", sizeof(gpsdata)); - } else { -#endif - LMIC_setTxData2(COUNTERPORT, mydata, sizeof(mydata), - (cfg.countermode & 0x02)); - ESP_LOGI(TAG, "%d bytes queued to send", sizeof(mydata)); - sprintf(display_lmic, "PACKET QUEUED"); + #ifdef HAS_GPS + } + #endif + + // clear counter if not in cumulative counter mode + if (cfg.countermode != 1) { + reset_counters(); // clear macs container and reset all counters + reset_salt(); // get new salt for salting hashes + ESP_LOGI(TAG, "Counter cleared (countermode = %d)", cfg.countermode); + } -#ifdef HAS_GPS - } -#endif - - // clear counter if not in cumulative counter mode - if (cfg.countermode != 1) { - reset_counters(); // clear macs container and reset all counters - reset_salt(); // get new salt for salting hashes - ESP_LOGI(TAG, "Counter cleared (countermode = %d)", cfg.countermode); - } - -// Schedule next transmission -end: - os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(cfg.sendcycle * 2), - do_send); + // Schedule next transmission + end: + os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(cfg.sendcycle * 2), do_send); } // do_send() -void onEvent(ev_t ev) { - char buff[24] = ""; +void onEvent (ev_t ev) { + char buff[24]=""; - switch (ev) { - case EV_SCAN_TIMEOUT: - strcpy_P(buff, PSTR("SCAN TIMEOUT")); - break; - case EV_BEACON_FOUND: - strcpy_P(buff, PSTR("BEACON FOUND")); - break; - case EV_BEACON_MISSED: - strcpy_P(buff, PSTR("BEACON MISSED")); - break; - case EV_BEACON_TRACKED: - strcpy_P(buff, PSTR("BEACON TRACKED")); - break; - case EV_JOINING: - strcpy_P(buff, PSTR("JOINING")); - break; - case EV_LOST_TSYNC: - strcpy_P(buff, PSTR("LOST TSYNC")); - break; - case EV_RESET: - strcpy_P(buff, PSTR("RESET")); - break; - case EV_RXCOMPLETE: - strcpy_P(buff, PSTR("RX COMPLETE")); - break; - case EV_LINK_DEAD: - strcpy_P(buff, PSTR("LINK DEAD")); - break; - case EV_LINK_ALIVE: - strcpy_P(buff, PSTR("LINK ALIVE")); - break; - case EV_RFU1: - strcpy_P(buff, PSTR("RFUI")); - break; - case EV_JOIN_FAILED: - strcpy_P(buff, PSTR("JOIN FAILED")); - break; - case EV_REJOIN_FAILED: - strcpy_P(buff, PSTR("REJOIN FAILED")); - break; + switch(ev) { + case EV_SCAN_TIMEOUT: strcpy_P(buff, PSTR("SCAN TIMEOUT")); break; + case EV_BEACON_FOUND: strcpy_P(buff, PSTR("BEACON FOUND")); break; + case EV_BEACON_MISSED: strcpy_P(buff, PSTR("BEACON MISSED")); break; + case EV_BEACON_TRACKED: strcpy_P(buff, PSTR("BEACON TRACKED")); break; + case EV_JOINING: strcpy_P(buff, PSTR("JOINING")); break; + case EV_LOST_TSYNC: strcpy_P(buff, PSTR("LOST TSYNC")); break; + case EV_RESET: strcpy_P(buff, PSTR("RESET")); break; + case EV_RXCOMPLETE: strcpy_P(buff, PSTR("RX COMPLETE")); break; + case EV_LINK_DEAD: strcpy_P(buff, PSTR("LINK DEAD")); break; + case EV_LINK_ALIVE: strcpy_P(buff, PSTR("LINK ALIVE")); break; + case EV_RFU1: strcpy_P(buff, PSTR("RFUI")); break; + case EV_JOIN_FAILED: strcpy_P(buff, PSTR("JOIN FAILED")); break; + case EV_REJOIN_FAILED: strcpy_P(buff, PSTR("REJOIN FAILED")); break; + + case EV_JOINED: - case EV_JOINED: + strcpy_P(buff, PSTR("JOINED")); + sprintf(display_lora, " "); // clear previous lmic status message from display - strcpy_P(buff, PSTR("JOINED")); - sprintf(display_lora, - " "); // clear previous lmic status message from display + // set data rate adaptation + LMIC_setAdrMode(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 + ESP_LOGI(TAG, "ADR=%d, SF=%d, TXPOWER=%d", cfg.adrmode, cfg.lorasf, cfg.txpower); + break; - // set data rate adaptation - LMIC_setAdrMode(cfg.adrmode); - // Set data rate and transmit power (note: txpower seems to be ignored by - // the library) - switch_lora(cfg.lorasf, cfg.txpower); + case EV_TXCOMPLETE: - // show effective LoRa parameters after join - ESP_LOGI(TAG, "ADR=%d, SF=%d, TXPOWER=%d", cfg.adrmode, cfg.lorasf, - cfg.txpower); - break; + strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED ACK") : PSTR("TX COMPLETE")); + sprintf(display_lora, " "); // clear previous lmic status message from display + + if (LMIC.dataLen) { + ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", LMIC.dataLen, LMIC.rssi, (signed char)LMIC.snr / 4); + // LMIC.snr = SNR twos compliment [dB] * 4 + // LMIC.rssi = RSSI [dBm] (-196...+63) + sprintf(display_lora, "RSSI %d SNR %d", LMIC.rssi, (signed char)LMIC.snr / 4 ); - case EV_TXCOMPLETE: + // check if payload received on command port, then call remote command interpreter + if ( (LMIC.txrxFlags & TXRX_PORT) && (LMIC.frame[LMIC.dataBeg-1] == RCMDPORT ) ) { + // caution: buffering LMIC values here because rcommand() can modify LMIC.frame + unsigned char* buffer = new unsigned char[MAX_LEN_FRAME]; + memcpy(buffer, LMIC.frame, MAX_LEN_FRAME); //Copy data from cfg to char* + int i, k = LMIC.dataBeg, l = LMIC.dataBeg+LMIC.dataLen-2; + for (i=k; i<=l; i+=2) { + rcommand(buffer[i], buffer[i+1]); + } + delete[] buffer; //free memory + } + } + break; - strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED ACK") - : PSTR("TX COMPLETE")); - sprintf(display_lora, - " "); // clear previous lmic status message from display - - if (LMIC.dataLen) { - ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", - LMIC.dataLen, LMIC.rssi, (signed char)LMIC.snr / 4); - // LMIC.snr = SNR twos compliment [dB] * 4 - // LMIC.rssi = RSSI [dBm] (-196...+63) - sprintf(display_lora, "RSSI %d SNR %d", LMIC.rssi, - (signed char)LMIC.snr / 4); - - // check if payload received on command port, then call remote command - // interpreter - if ((LMIC.txrxFlags & TXRX_PORT) && - (LMIC.frame[LMIC.dataBeg - 1] == RCMDPORT)) { - // caution: buffering LMIC values here because rcommand() can modify - // LMIC.frame - unsigned char *buffer = new unsigned char[MAX_LEN_FRAME]; - memcpy(buffer, LMIC.frame, MAX_LEN_FRAME); // Copy data from cfg to - // char* - int i, k = LMIC.dataBeg, l = LMIC.dataBeg + LMIC.dataLen - 2; - for (i = k; i <= l; i += 2) { - rcommand(buffer[i], buffer[i + 1]); - } - delete[] buffer; // free memory - } + default: sprintf_P(buff, PSTR("UNKNOWN EVENT %d"), ev); break; } - break; - - default: - sprintf_P(buff, PSTR("UNKNOWN EVENT %d"), ev); - break; - } - - // Log & Display if asked - if (*buff) { - ESP_LOGI(TAG, "EV_%s", buff); - sprintf(display_lmic, buff); - } + // Log & Display if asked + if (*buff) { + ESP_LOGI(TAG, "EV_%s", buff); + sprintf(display_lmic, buff); + } + } // onEvent() + diff --git a/src/lorawan.h b/src/lorawan.h index eda04be7..de54b6e8 100644 --- a/src/lorawan.h +++ b/src/lorawan.h @@ -2,9 +2,9 @@ #define LORAWAN_H void onEvent(ev_t ev); -void do_send(osjob_t *j); -void gen_lora_deveui(uint8_t *pdeveui); -void RevBytes(unsigned char *b, size_t c); +void do_send(osjob_t* j); +void gen_lora_deveui(uint8_t * pdeveui); +void RevBytes(unsigned char* b, size_t c); void get_hard_deveui(uint8_t *pdeveui); #endif \ No newline at end of file diff --git a/src/macsniff.cpp b/src/macsniff.cpp index 0e681d94..8403e701 100644 --- a/src/macsniff.cpp +++ b/src/macsniff.cpp @@ -3,136 +3,114 @@ #include "globals.h" #ifdef VENDORFILTER -#include "vendor_array.h" + #include "vendor_array.h" #endif // Local logging tag static const char TAG[] = "wifi"; -static wifi_country_t wifi_country = {.cc = WIFI_MY_COUNTRY, - .schan = WIFI_CHANNEL_MIN, - .nchan = WIFI_CHANNEL_MAX, - .policy = WIFI_COUNTRY_POLICY_MANUAL}; +static wifi_country_t wifi_country = {.cc=WIFI_MY_COUNTRY, .schan=WIFI_CHANNEL_MIN, .nchan=WIFI_CHANNEL_MAX, .policy=WIFI_COUNTRY_POLICY_MANUAL}; // globals uint16_t salt; uint16_t reset_salt(void) { - salt = random( - 65536); // get new 16bit random for salting hashes and set global salt var - return salt; + salt = random(65536); // get new 16bit random for salting hashes and set global salt var + return salt; } bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) { - char buff[16]; // temporary buffer for printf - bool added = false; - uint32_t addr2int, vendor2int; // temporary buffer for MAC and Vendor OUI - uint16_t hashedmac; // temporary buffer for generated hash value + char buff[16]; // temporary buffer for printf + bool added = false; + uint32_t addr2int, vendor2int; // temporary buffer for MAC and Vendor OUI + uint16_t hashedmac; // temporary buffer for generated hash value - // only last 3 MAC Address bytes are used for MAC address anonymization - // but since it's uint32 we take 4 bytes to avoid 1st value to be 0 - addr2int = ((uint32_t)paddr[2]) | ((uint32_t)paddr[3] << 8) | - ((uint32_t)paddr[4] << 16) | ((uint32_t)paddr[5] << 24); + // only last 3 MAC Address bytes are used for MAC address anonymization + // but since it's uint32 we take 4 bytes to avoid 1st value to be 0 + addr2int = ( (uint32_t)paddr[2] ) | ( (uint32_t)paddr[3] << 8 ) | ( (uint32_t)paddr[4] << 16 ) | ( (uint32_t)paddr[5] << 24 ); -#ifdef VENDORFILTER - vendor2int = ((uint32_t)paddr[2]) | ((uint32_t)paddr[1] << 8) | - ((uint32_t)paddr[0] << 16); - // use OUI vendor filter list only on Wifi, not on BLE - if ((sniff_type == MAC_SNIFF_BLE) || - std::find(vendors.begin(), vendors.end(), vendor2int) != vendors.end()) { -#endif + #ifdef VENDORFILTER + vendor2int = ( (uint32_t)paddr[2] ) | ( (uint32_t)paddr[1] << 8 ) | ( (uint32_t)paddr[0] << 16 ); + // use OUI vendor filter list only on Wifi, not on BLE + if ( (sniff_type==MAC_SNIFF_BLE) || std::find(vendors.begin(), vendors.end(), vendor2int) != vendors.end() ) + { + #endif - // salt and hash MAC, and if new unique one, store identifier in container - // and increment counter on display - // https://en.wikipedia.org/wiki/MAC_Address_Anonymization - - addr2int += (uint32_t)salt; // add 16-bit salt to pseudo MAC - snprintf( - buff, sizeof(buff), "%08X", - addr2int); // convert unsigned 32-bit salted MAC to 8 digit hex string - hashedmac = rokkit(&buff[3], 5); // hash MAC last string value, use 5 chars - // to fit hash in uint16_t container - auto newmac = macs.insert( - hashedmac); // add hashed MAC to total container if new unique - added = newmac.second ? true - : false; // true if hashed MAC is unique in container + // salt and hash MAC, and if new unique one, store identifier in container and increment counter on display + // https://en.wikipedia.org/wiki/MAC_Address_Anonymization + + addr2int += (uint32_t)salt; // add 16-bit salt to pseudo MAC + snprintf(buff, sizeof(buff), "%08X", addr2int); // convert unsigned 32-bit salted MAC to 8 digit hex string + hashedmac = rokkit(&buff[3], 5); // hash MAC last string value, use 5 chars to fit hash in uint16_t container + auto newmac = macs.insert(hashedmac); // add hashed MAC to total container if new unique + added = newmac.second ? true:false; // true if hashed MAC is unique in container // Count only if MAC was not yet seen if (added) { - // increment counter and one blink led - if (sniff_type == MAC_SNIFF_WIFI) { - macs_wifi++; // increment Wifi MACs counter -#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED) - blink_LED(COLOR_GREEN, 50); -#endif - } -#ifdef BLECOUNTER - else if (sniff_type == MAC_SNIFF_BLE) { - macs_ble++; // increment BLE Macs counter -#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED) - blink_LED(COLOR_MAGENTA, 50); -#endif - } -#endif - } + // increment counter and one blink led + if (sniff_type == MAC_SNIFF_WIFI ) { + macs_wifi++; // increment Wifi MACs counter + #if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED) + blink_LED(COLOR_GREEN, 50); + #endif + } + #ifdef BLECOUNTER + else if (sniff_type == MAC_SNIFF_BLE ) { + macs_ble++; // increment BLE Macs counter + #if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED) + blink_LED(COLOR_MAGENTA, 50); + #endif + } + #endif + } // Log scan result - ESP_LOGI(TAG, - "%s %s RSSI %ddBi -> MAC %s -> Hash %04X -> WiFi:%d BLTH:%d -> " - "%d Bytes left", - added ? "new " : "known", - sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH", rssi, buff, - hashedmac, macs_wifi, macs_ble, ESP.getFreeHeap()); + ESP_LOGI(TAG, "%s %s RSSI %ddBi -> MAC %s -> Hash %04X -> WiFi:%d BLTH:%d -> %d Bytes left", + added ? "new " : "known", + sniff_type==MAC_SNIFF_WIFI ? "WiFi":"BLTH", + rssi, buff, hashedmac, macs_wifi, macs_ble, + ESP.getFreeHeap()); -#ifdef VENDORFILTER - } else { - // Very noisy - // ESP_LOGD(TAG, "Filtered MAC %02X:%02X:%02X:%02X:%02X:%02X", - // paddr[0],paddr[1],paddr[2],paddr[3],paddr[5],paddr[5]); - } -#endif + #ifdef VENDORFILTER + } else { + // Very noisy + // ESP_LOGD(TAG, "Filtered MAC %02X:%02X:%02X:%02X:%02X:%02X", paddr[0],paddr[1],paddr[2],paddr[3],paddr[5],paddr[5]); + } + #endif - // True if MAC WiFi/BLE was new - return added; // function returns bool if a new and unique Wifi or BLE mac was - // counted (true) or not (false) + // True if MAC WiFi/BLE was new + return added; // function returns bool if a new and unique Wifi or BLE mac was counted (true) or not (false) } void wifi_sniffer_init(void) { - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM - wifi_promiscuous_filter_t filter = { - .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg - ESP_ERROR_CHECK( - esp_wifi_set_country(&wifi_country)); // set locales for RF and channels - 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_promiscuous_filter(&filter)); // set MAC 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 + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM + wifi_promiscuous_filter_t filter = {.filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg + ESP_ERROR_CHECK(esp_wifi_set_country(&wifi_country)); // set locales for RF and channels + 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_promiscuous_filter(&filter)); // set MAC 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 } void wifi_sniffer_set_channel(uint8_t channel) { - esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); + esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); } // using IRAM_:ATTR here to speed up callback function -IRAM_ATTR void wifi_sniffer_packet_handler(void *buff, - wifi_promiscuous_pkt_type_t type) { - const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff; - const wifi_ieee80211_packet_t *ipkt = - (wifi_ieee80211_packet_t *)ppkt->payload; - const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr; - - if ((cfg.rssilimit) && - (ppkt->rx_ctrl.rssi < cfg.rssilimit)) { // rssi is negative value - ESP_LOGI(TAG, "WiFi RSSI %d -> ignoring (limit: %d)", ppkt->rx_ctrl.rssi, - cfg.rssilimit); - } else { - uint8_t *p = (uint8_t *)hdr->addr2; - mac_add(p, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI); - } +IRAM_ATTR void wifi_sniffer_packet_handler(void* buff, wifi_promiscuous_pkt_type_t type) { + const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff; + const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload; + const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr; + + if ((cfg.rssilimit) && (ppkt->rx_ctrl.rssi < cfg.rssilimit )) { // rssi is negative value + ESP_LOGI(TAG, "WiFi RSSI %d -> ignoring (limit: %d)", ppkt->rx_ctrl.rssi, cfg.rssilimit); + } else { + uint8_t *p = (uint8_t *) hdr->addr2; + mac_add(p, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI) ; + } } + diff --git a/src/macsniff.h b/src/macsniff.h index 5e7a0c96..5eb07f30 100644 --- a/src/macsniff.h +++ b/src/macsniff.h @@ -5,21 +5,21 @@ #include #define MAC_SNIFF_WIFI 0 -#define MAC_SNIFF_BLE 1 +#define MAC_SNIFF_BLE 1 typedef struct { - unsigned frame_ctrl : 16; - unsigned duration_id : 16; - uint8_t addr1[6]; /* receiver address */ - uint8_t addr2[6]; /* sender address */ - uint8_t addr3[6]; /* filtering address */ - unsigned sequence_ctrl : 16; - uint8_t addr4[6]; /* optional */ + unsigned frame_ctrl:16; + unsigned duration_id:16; + uint8_t addr1[6]; /* receiver address */ + uint8_t addr2[6]; /* sender address */ + uint8_t addr3[6]; /* filtering address */ + unsigned sequence_ctrl:16; + uint8_t addr4[6]; /* optional */ } wifi_ieee80211_mac_hdr_t; typedef struct { - wifi_ieee80211_mac_hdr_t hdr; - uint8_t payload[0]; /* network data ended with 4 bytes csum (CRC32) */ + wifi_ieee80211_mac_hdr_t hdr; + uint8_t payload[0]; /* network data ended with 4 bytes csum (CRC32) */ } wifi_ieee80211_packet_t; uint16_t reset_salt(void); @@ -28,6 +28,6 @@ void wifi_sniffer_set_channel(uint8_t channel); void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type); // function defined in rokkithash.cpp -uint32_t rokkit(const char *, int); +uint32_t rokkit(const char * , int ); #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index a83f9ca3..a6216a3c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ /* - + Copyright 2018 Oliver Brandmueller Copyright 2018 Klaus Wilting @@ -15,9 +15,9 @@ Copyright 2018 Klaus Wilting 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. +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. */ @@ -25,654 +25,619 @@ licenses. Refer to LICENSE.txt file in repository for more details. #include "globals.h" // Does nothing and avoid any compilation error with I2C -#include +#include // LMIC-Arduino LoRaWAN Stack #include "loraconf.h" -#include #include +#include // ESP32 lib Functions -#include // needed for ESP_LOGx on arduino framework -#include // needed for Wifi event handler -#include // needed for reading ESP32 chip attributes +#include // needed for Wifi event handler +#include // needed for reading ESP32 chip attributes +#include // needed for ESP_LOGx on arduino framework // Initialize global variables -configData_t cfg; // struct holds current device configuration -osjob_t sendjob, rcmdjob; // LMIC job handler -uint64_t uptimecounter = 0; // timer global for uptime counter -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 +configData_t cfg; // struct holds current device configuration +osjob_t sendjob, rcmdjob; // LMIC job handler +uint64_t uptimecounter = 0; // timer global for uptime counter +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 char display_lora[16], display_lmic[16]; // display buffers -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 *displaytimer = - NULL; // configure hardware timer used for cyclic display refresh -hw_timer_t *channelSwitch = - NULL; // configure hardware timer used for wifi channel switching -xref2u1_t rcmd_data; // buffer for rcommand results size -u1_t rcmd_data_size; // buffer for rcommand results size +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 * displaytimer = NULL; // configure hardware timer used for cyclic display refresh +hw_timer_t * channelSwitch = NULL; // configure hardware timer used for wifi channel switching +xref2u1_t rcmd_data; // buffer for rcommand results size +u1_t rcmd_data_size; // buffer for rcommand results size #ifdef HAS_GPS -gpsStatus_t gps_status; // struct for storing gps data -TinyGPSPlus gps; // create TinyGPS++ instance + gpsStatus_t gps_status; // struct for storing gps data + TinyGPSPlus gps; // create TinyGPS++ instance #endif -portMUX_TYPE timerMux = - portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying IRQ - // handler shared variables +portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying IRQ handler shared variables -std::set macs; // associative container holds total of unique MAC - // adress hashes (Wifi + BLE) +std::set macs; // associative container holds total of unique MAC adress hashes (Wifi + BLE) // this variables will be changed in the ISR, and read in main loop -static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0, - ChannelTimerIRQ = 0; +static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0, ChannelTimerIRQ = 0; // local Tag for logging static const char TAG[] = "main"; #ifndef VERBOSE -int redirect_log(const char *fmt, va_list args) { - // do nothing - return 0; +int redirect_log(const char * fmt, va_list args) { + //do nothing + return 0; } #endif void reset_counters() { - macs.clear(); // clear all macs container - macs_total = 0; // reset all counters - macs_wifi = 0; - macs_ble = 0; + macs.clear(); // clear all macs container + macs_total = 0; // reset all counters + macs_wifi = 0; + macs_ble = 0; } - /* begin LMIC specific parts - * ------------------------------------------------------------ */ +/* begin LMIC specific parts ------------------------------------------------------------ */ + #ifdef VERBOSE -void printKeys(void); + 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_getDevKey (u1_t *buf) { + memcpy(buf, APPKEY, 16); } -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 - } +void os_getArtEui (u1_t *buf) { + memcpy(buf, APPEUI, 8); + RevBytes(buf, 8); // TTN requires it in LSB First order, so we swap bytes +} -// 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 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, - .sck = PIN_SPI_SCK, - .nss = PIN_SPI_SS, - .rxtx = LMIC_UNUSED_PIN, - .rst = RST, - .dio = {DIO0, DIO1, DIO2}}; +const lmic_pinmap lmic_pins = { + .mosi = PIN_SPI_MOSI, + .miso = PIN_SPI_MISO, + .sck = PIN_SPI_SCK, + .nss = PIN_SPI_SS, + .rxtx = LMIC_UNUSED_PIN, + .rst = RST, + .dio = {DIO0, DIO1, DIO2} +}; + // LMIC FreeRTos Task -void lorawan_loop(void *pvParameters) { +void lorawan_loop(void * pvParameters) { - configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check + configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check - while (1) { - os_runloop_once(); // execute LMIC jobs - vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog - } + while(1) { + os_runloop_once(); // execute LMIC jobs + vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog + } } - /* end LMIC specific parts - * --------------------------------------------------------------- */ +/* end LMIC specific parts --------------------------------------------------------------- */ - /* beginn hardware specific parts - * -------------------------------------------------------- */ +/* 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); -} + 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); + // defined in antenna.cpp + void antenna_init(); + void antenna_select(const uint8_t _ant); #endif #ifndef BLECOUNTER -bool btstop = btStop(); + bool btstop = btStop(); #endif -// Button IRQ Handler Routine, IRAM_ATTR necessary here, see -// https://github.com/espressif/arduino-esp32/issues/855 +// Button IRQ Handler Routine, IRAM_ATTR necessary here, see https://github.com/espressif/arduino-esp32/issues/855 #ifdef HAS_BUTTON -void IRAM_ATTR ButtonIRQ() { ButtonPressedIRQ++; } + void IRAM_ATTR ButtonIRQ() { + ButtonPressedIRQ++; + } #endif // Wifi Channel Rotation Timer IRQ Handler Routine void IRAM_ATTR ChannelSwitchIRQ() { - portENTER_CRITICAL(&timerMux); - ChannelTimerIRQ++; - portEXIT_CRITICAL(&timerMux); + portENTER_CRITICAL(&timerMux); + ChannelTimerIRQ++; + portEXIT_CRITICAL(&timerMux); } -/* end hardware specific parts - * -------------------------------------------------------- */ +/* end hardware specific parts -------------------------------------------------------- */ -/* begin wifi specific parts - * ---------------------------------------------------------- */ + +/* begin wifi specific parts ---------------------------------------------------------- */ // Sniffer Task -void sniffer_loop(void *pvParameters) { +void sniffer_loop(void * pvParameters) { - configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check + configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check - while (1) { + while (1) { - if (ChannelTimerIRQ) { - portENTER_CRITICAL(&timerMux); - ChannelTimerIRQ--; - portEXIT_CRITICAL(&timerMux); - // rotates variable channel 1..WIFI_CHANNEL_MAX - channel = (channel % WIFI_CHANNEL_MAX) + 1; - wifi_sniffer_set_channel(channel); - ESP_LOGD(TAG, "Wifi set channel %d", channel); + if (ChannelTimerIRQ) { + portENTER_CRITICAL(&timerMux); + ChannelTimerIRQ--; + portEXIT_CRITICAL(&timerMux); + // rotates variable channel 1..WIFI_CHANNEL_MAX + channel = (channel % WIFI_CHANNEL_MAX) + 1; + wifi_sniffer_set_channel(channel); + ESP_LOGD(TAG, "Wifi set channel %d", channel); - vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog - } + vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog + } - } // end of infinite wifi channel rotation loop + } // end of infinite wifi channel rotation loop } -/* end wifi specific parts - * ------------------------------------------------------------ */ +/* end wifi specific parts ------------------------------------------------------------ */ // uptime counter 64bit to prevent millis() rollover after 49 days uint64_t uptime() { - static uint32_t low32, high32; - uint32_t new_low32 = millis(); - if (new_low32 < low32) - high32++; - low32 = new_low32; - return (uint64_t)high32 << 32 | low32; + static uint32_t low32, high32; + uint32_t new_low32 = millis(); + if (new_low32 < low32) high32++; + low32 = new_low32; + return (uint64_t) high32 << 32 | low32; } #ifdef HAS_DISPLAY -// 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"); -} - -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); - u8x8.println("DEVEUI:"); - os_getDevEui((u1_t *)buf); - DisplayKey(buf, 8, true); - delay(5000); - u8x8.clear(); -} - -void refreshDisplay() { - // update counter display (lines 0-4) - 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 - u8x8.setCursor(0, 4); - u8x8.printf("WIFI:%-4d", macs_wifi); - -#ifdef BLECOUNTER - u8x8.setCursor(0, 3); - if (cfg.blescan) - u8x8.printf("BLTH:%-4d", macs_ble); - else - u8x8.printf("%s", "BLTH:off"); -#endif - - // update LoRa SF display (line 3) - 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); - - // update wifi channel display (line 4) - 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); - - // update LoRa status display (line 6) - u8x8.setCursor(0, 6); - u8x8.printf("%-16s", display_lora); - - // update LMiC event display (line 7) - u8x8.setCursor(0, 7); - u8x8.printf("%-16s", display_lmic); -} - -void updateDisplay() { - // refresh display according to refresh cycle setting - if (DisplayTimerIRQ) { - portENTER_CRITICAL(&timerMux); - DisplayTimerIRQ--; - portEXIT_CRITICAL(&timerMux); - - refreshDisplay(); - - // set display on/off according to current device configuration - if (DisplayState != cfg.screenon) { - DisplayState = cfg.screenon; - u8x8.setPowerSave(!cfg.screenon); + // 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= 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; + 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 } - // No custom blink, check LoRaWAN state - } else { + void led_loop() { + // Custom blink running always have priority other LoRaWAN led management + if ( LEDBlinkStarted && LEDBlinkDuration) { - // 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) < 20) ? 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 { - // led off - LEDColor = COLOR_NONE; - LEDState = LED_OFF; - } - } + //ESP_LOGI(TAG, "Start=%ld for %g",LEDBlinkStarted, LEDBlinkDuration ); - // ESP_LOGI(TAG, "state=%d previous=%d Color=%d",LEDState, previousLEDState, - // LEDColor ); - // 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() + // 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 { -#endif + // 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) < 20) ? 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 { + // led off + LEDColor = COLOR_NONE; + LEDState = LED_OFF; + } + } -/* begin Aruino SETUP - * ------------------------------------------------------------ */ + //ESP_LOGI(TAG, "state=%d previous=%d Color=%d",LEDState, previousLEDState, LEDColor ); + // 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 + +/* begin Aruino SETUP ------------------------------------------------------------ */ void setup() { - char features[64] = ""; + char features[64] = ""; - // disable brownout detection + // disable brownout detection #ifdef DISABLE_BROWNOUT - // register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4 - (*((volatile uint32_t *)ETS_UNCACHED_ADDR((DR_REG_RTCCNTL_BASE + 0xd4)))) = 0; + // register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4 + (*((volatile uint32_t *)ETS_UNCACHED_ADDR((DR_REG_RTCCNTL_BASE+0xd4)))) = 0; #endif - // setup debug output or silence device + // setup debug output or silence device #ifdef VERBOSE - Serial.begin(115200); - esp_log_level_set("*", ESP_LOG_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); + // mute logs completely by redirecting them to silence function + esp_log_level_set("*", ESP_LOG_NONE); + esp_log_set_vprintf(redirect_log); #endif + + ESP_LOGI(TAG, "Starting %s %s", PROGNAME, PROGVERSION); + + // initialize system event handler for wifi task, needed for wifi_sniffer_init() + esp_event_loop_init(NULL, NULL); - ESP_LOGI(TAG, "Starting %s %s", PROGNAME, PROGVERSION); - - // initialize system event handler for wifi task, needed for - // wifi_sniffer_init() - esp_event_loop_init(NULL, NULL); - - // print chip information on startup if in verbose mode + // 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_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()); #endif #ifdef HAS_GPS - ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); + ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); #endif - // read settings from NVRAM - loadConfig(); // includes initialize if necessary + // read settings from NVRAM + loadConfig(); // includes initialize if necessary - // initialize led if needed -#if (HAS_LED != NOT_A_PIN) - pinMode(HAS_LED, OUTPUT); - strcat(features, " LED"); + // initialize led if needed +#if (HAS_LED != NOT_A_PIN) + pinMode(HAS_LED, OUTPUT); + strcat(features, " LED"); #endif #ifdef HAS_RGB_LED - rgb_set_color(COLOR_PINK); - strcat(features, " RGB"); + rgb_set_color(COLOR_PINK); + strcat(features, " RGB"); #endif - // initialize button handling if needed + // initialize button handling if needed #ifdef HAS_BUTTON - strcat(features, " BTN_"); -#ifdef BUTTON_PULLUP - strcat(features, "PU"); - // install button interrupt (pullup mode) - pinMode(HAS_BUTTON, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING); -#else - strcat(features, "PD"); - // install button interrupt (pulldown mode) - pinMode(HAS_BUTTON, INPUT_PULLDOWN); - attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING); -#endif + strcat(features, " BTN_"); + #ifdef BUTTON_PULLUP + strcat(features, "PU"); + // install button interrupt (pullup mode) + pinMode(HAS_BUTTON, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING); + #else + strcat(features, "PD"); + // install button interrupt (pulldown mode) + pinMode(HAS_BUTTON, INPUT_PULLDOWN); + attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING); + #endif #endif - // initialize wifi antenna if needed + // initialize wifi antenna if needed #ifdef HAS_ANTENNA_SWITCH - strcat(features, " ANT"); - antenna_init(); + strcat(features, " ANT"); + antenna_init(); #endif // initialize gps if present #ifdef HAS_GPS - strcat(features, " GPS"); + strcat(features, " GPS"); #endif #ifdef HAS_DISPLAY - strcat(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"); - u8x8.setCursor(0, 4); - u8x8.printf("WIFI:0"); -#ifdef BLECOUNTER - u8x8.setCursor(0, 3); - u8x8.printf("BLTH:0"); -#endif - u8x8.setCursor(0, 5); - u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit); + strcat(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"); + u8x8.setCursor(0,4); + u8x8.printf("WIFI:0"); + #ifdef BLECOUNTER + u8x8.setCursor(0,3); + u8x8.printf("BLTH:0"); + #endif + u8x8.setCursor(0,5); + u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit); + + sprintf(display_lora, "Join wait"); - sprintf(display_lora, "Join wait"); - - // setup display refresh trigger IRQ using esp32 hardware timer 0 - // for explanation see - // 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 - timerAttachInterrupt(displaytimer, &DisplayIRQ, - true); // interrupt handler DisplayIRQ, triggered by edge - timerAlarmWrite( - displaytimer, DISPLAYREFRESH_MS * 1000, - true); // reload interrupt after each trigger of display refresh cycle - timerAlarmEnable(displaytimer); // enable display interrupt + // setup display refresh trigger IRQ using esp32 hardware timer 0 + // for explanation see 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 + timerAttachInterrupt(displaytimer, &DisplayIRQ, true); // interrupt handler DisplayIRQ, triggered by edge + timerAlarmWrite(displaytimer, DISPLAYREFRESH_MS * 1000, true); // reload interrupt after each trigger of display refresh cycle + timerAlarmEnable(displaytimer); // enable display interrupt #endif - // setup channel rotation trigger IRQ using esp32 hardware timer 1 - channelSwitch = timerBegin(1, 80, true); - timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true); - timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true); - timerAlarmEnable(channelSwitch); +// setup channel rotation trigger IRQ using esp32 hardware timer 1 +channelSwitch = timerBegin(1, 80, true); +timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true); +timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true); +timerAlarmEnable(channelSwitch); - // show compiled features - ESP_LOGI(TAG, "Features %s", features); +// show compiled features +ESP_LOGI(TAG, "Features %s", features); // output LoRaWAN keys to console #ifdef VERBOSE - printKeys(); + printKeys(); #endif - // initialize LoRaWAN LMIC run-time environment - os_init(); - // reset LMIC MAC state - LMIC_reset(); - // This tells LMIC to make the receive windows bigger, in case your clock is - // 1% faster or slower. - LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100); +// initialize LoRaWAN LMIC run-time environment +os_init(); +// reset LMIC MAC state +LMIC_reset(); +// This tells LMIC to make the receive windows bigger, in case your clock is 1% faster or slower. +LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100); - // start lmic runloop in rtos task on core 1 (note: arduino main loop runs on - // core 1, too) - // https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/ +// start lmic runloop in rtos task on core 1 (note: arduino main loop runs on core 1, too) +// 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, - (5 | portPRIVILEGE_BIT), NULL, 1); +ESP_LOGI(TAG, "Starting Lora task on core 1"); +xTaskCreatePinnedToCore(lorawan_loop, "loratask", 2048, ( void * ) 1, ( 5 | portPRIVILEGE_BIT ), NULL, 1); - // 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(); - // initialize salt value using esp_random() called by random() in - // 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 wifi in monitor mode and start channel rotation task on core 0 +ESP_LOGI(TAG, "Starting Wifi task on core 0"); +wifi_sniffer_init(); +// initialize salt value using esp_random() called by random() in 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(); - } + if (cfg.blescan) { + start_BLEscan(); + } #endif -// if device has GPS and GPS function is enabled, start GPS reader task on core -// 0 +// if device has GPS and GPS function is enabled, start GPS reader task on core 0 #ifdef HAS_GPS - if (cfg.gpsmode) { - ESP_LOGI(TAG, "Starting GPS task on core 0"); - xTaskCreatePinnedToCore(gps_loop, "gpsfeed", 2048, (void *)1, 1, NULL, 0); - } + if (cfg.gpsmode) { + ESP_LOGI(TAG, "Starting GPS task on core 0"); + xTaskCreatePinnedToCore(gps_loop, "gpsfeed", 2048, ( void * ) 1, 1, NULL, 0); + } #endif - // kickoff sendjob -> joins network and rescedules sendjob for cyclic - // transmitting payload - do_send(&sendjob); +// kickoff sendjob -> joins network and rescedules sendjob for cyclic transmitting payload +do_send(&sendjob); + } -/* end Arduino SETUP - * ------------------------------------------------------------ */ +/* end Arduino SETUP ------------------------------------------------------------ */ -/* begin Arduino main loop - * ------------------------------------------------------ */ +/* begin Arduino main loop ------------------------------------------------------ */ void loop() { - while (1) { + while (1) { - // simple state machine for controlling uptime, display, LED, button, - // memory. + // simple state machine for controlling uptime, display, LED, button, memory. - uptimecounter = uptime() / 1000; // counts uptime in seconds (64bit) + uptimecounter = uptime() / 1000; // counts uptime in seconds (64bit) -#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED) - led_loop(); -#endif + #if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED) + led_loop(); + #endif + + #ifdef HAS_BUTTON + readButton(); + #endif -#ifdef HAS_BUTTON - readButton(); -#endif + #ifdef HAS_DISPLAY + updateDisplay(); + #endif -#ifdef HAS_DISPLAY - updateDisplay(); -#endif + // check free memory + if (esp_get_minimum_free_heap_size() <= MEM_LOW) { + ESP_LOGI(TAG, "Memory full, counter cleared (heap low water mark = %d Bytes / free heap = %d bytes)", \ + esp_get_minimum_free_heap_size(), ESP.getFreeHeap()); + do_send(&sendjob); // send count + reset_counters(); // clear macs container and reset all counters + reset_salt(); // get new salt for salting hashes + } - // check free memory - if (esp_get_minimum_free_heap_size() <= MEM_LOW) { - ESP_LOGI(TAG, - "Memory full, counter cleared (heap low water mark = %d Bytes / " - "free heap = %d bytes)", - esp_get_minimum_free_heap_size(), ESP.getFreeHeap()); - do_send(&sendjob); // send count - reset_counters(); // clear macs container and reset all counters - reset_salt(); // get new salt for salting hashes - } + #ifdef HAS_GPS + // log NMEA status every 30 seconds, useful for debugging GPS connection + if ( (uptime() % 30000) == 0 ) + ESP_LOGD(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d", gps.passedChecksum(), gps.failedChecksum(), gps.sentencesWithFix()); + #endif -#ifdef HAS_GPS - // log NMEA status every 30 seconds, useful for debugging GPS connection - if ((uptime() % 30000) == 0) - ESP_LOGD(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d", - gps.passedChecksum(), gps.failedChecksum(), - gps.sentencesWithFix()); -#endif + vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog - vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog - - } // end of infinite main loop + } // end of infinite main loop } -/* end Arduino main loop - * ------------------------------------------------------------ */ +/* end Arduino main loop ------------------------------------------------------------ */ diff --git a/src/main.h b/src/main.h index 2d8c9dce..a2e0eeb0 100644 --- a/src/main.h +++ b/src/main.h @@ -3,19 +3,21 @@ #include "lorawan.h" #include "macsniff.h" -// program version - note: increment version after modifications to configData_t -// struct!! -#define PROGVERSION "1.3.8" // use max 10 chars here! -#define PROGNAME "PAXCNT" +// program version - note: increment version after modifications to configData_t struct!! +#define PROGVERSION "1.3.8" // use max 10 chars here! +#define PROGNAME "PAXCNT" //--- Declarations --- -enum led_states { LED_OFF, LED_ON }; +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"}; + const char lora_datarate[] = {"1211100908077BFSNA"}; +#elif defined(CFG_us915) + const char lora_datarate[] = {"100908078CNA121110090807"}; #endif //--- Prototypes --- @@ -25,14 +27,15 @@ 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); + void start_BLEscan(void); + void stop_BLEscan(void); #endif -// defined in gpsread.cpp +//defined in gpsread.cpp #ifdef HAS_GPS -void gps_read(void); -void gps_loop(void *pvParameters); + void gps_read(void); + void gps_loop(void * pvParameters); #endif \ No newline at end of file diff --git a/src/rcommand.cpp b/src/rcommand.cpp index f1bfea94..fa061f9f 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -1,365 +1,310 @@ // remote command interpreter -// parses multiple number of command / value pairs from LoRaWAN remote command -// port (RCMDPORT) checks commands and executes each command with 1 argument per -// command +// parses multiple number of command / value pairs from LoRaWAN remote command port (RCMDPORT) +// checks commands and executes each command with 1 argument per command // Basic Config #include "globals.h" // LMIC-Arduino LoRaWAN Stack -#include #include +#include // Local logging tag static const char TAG[] = "main"; // table of remote commands and assigned functions typedef struct { - const uint8_t nam; - void (*func)(uint8_t); - const bool store; + const uint8_t nam; + void (*func)(uint8_t); + const bool store; } cmd_t; // function defined in antenna.cpp #ifdef HAS_ANTENNA_SWITCH -void antenna_select(const uint8_t _ant); + void antenna_select(const uint8_t _ant); #endif // function defined in adcread.cpp #ifdef HAS_BATTERY_PROBE -uint32_t read_voltage(void); + uint32_t read_voltage(void); #endif // function sends result of get commands to LoRaWAN network -void do_transmit(osjob_t *j) { - // check if there is a pending TX/RX job running, if yes then reschedule - // transmission - if (LMIC.opmode & OP_TXRXPEND) { - ESP_LOGI(TAG, "LoRa busy, rescheduling"); - sprintf(display_lmic, "LORA BUSY"); - os_setTimedCallback(&rcmdjob, os_getTime() + sec2osticks(RETRANSMIT_RCMD), - do_transmit); - } - LMIC_setTxData2(RCMDPORT, rcmd_data, rcmd_data_size, - 0); // send data unconfirmed on RCMD Port - ESP_LOGI(TAG, "%d bytes queued to send", rcmd_data_size); - sprintf(display_lmic, "PACKET QUEUED"); +void do_transmit(osjob_t* j){ + // check if there is a pending TX/RX job running, if yes then reschedule transmission + if (LMIC.opmode & OP_TXRXPEND) { + ESP_LOGI(TAG, "LoRa busy, rescheduling"); + sprintf(display_lmic, "LORA BUSY"); + os_setTimedCallback(&rcmdjob, os_getTime()+sec2osticks(RETRANSMIT_RCMD), do_transmit); + } + LMIC_setTxData2(RCMDPORT, rcmd_data, rcmd_data_size, 0); // send data unconfirmed on RCMD Port + ESP_LOGI(TAG, "%d bytes queued to send", rcmd_data_size); + sprintf(display_lmic, "PACKET QUEUED"); } -// help function to transmit result of get commands, since callback function -// do_transmit() cannot have params -void transmit(xref2u1_t mydata, u1_t mydata_size) { - rcmd_data = mydata; - rcmd_data_size = mydata_size; - do_transmit(&rcmdjob); +// help function to transmit result of get commands, since callback function do_transmit() cannot have params +void transmit(xref2u1_t mydata, u1_t mydata_size){ + rcmd_data = mydata; + rcmd_data_size = mydata_size; + do_transmit(&rcmdjob); } // help 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_eu868) - LMIC_setDrTxpow(DR_SF11, tx); - cfg.lorasf = sf; - break; -#elif defined(CFG_us915) - LMIC_setDrTxpow(DR_SF11CR, tx); - cfg.lorasf = sf; - break; -#endif - case 12: -#if defined(CFG_eu868) - LMIC_setDrTxpow(DR_SF12, tx); - cfg.lorasf = sf; - break; -#elif defined(CFG_us915) - LMIC_setDrTxpow(DR_SF12CR, tx); - cfg.lorasf = sf; - break; -#endif - default: - break; - } +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_eu868) + LMIC_setDrTxpow(DR_SF11,tx); cfg.lorasf=sf; break; + #elif defined(CFG_us915) + LMIC_setDrTxpow(DR_SF11CR,tx); cfg.lorasf=sf; break; + #endif + case 12: + #if defined(CFG_eu868) + LMIC_setDrTxpow(DR_SF12,tx); cfg.lorasf=sf; break; + #elif defined(CFG_us915) + LMIC_setDrTxpow(DR_SF12CR,tx); cfg.lorasf=sf; break; + #endif + default: break; + } } // set of functions that can be triggered by remote commands void set_reset(uint8_t val) { - switch (val) { - case 0: // restart device - ESP_LOGI(TAG, "Remote command: restart device"); - sprintf(display_lora, "Reset pending"); - vTaskDelay( - 10000 / - portTICK_PERIOD_MS); // wait for LMIC to confirm LoRa downlink to server - esp_restart(); - break; - case 1: // reset MAC counter - ESP_LOGI(TAG, "Remote command: reset MAC counter"); - reset_counters(); // clear macs - reset_salt(); // get new salt - sprintf(display_lora, "Reset counter"); - break; - case 2: // reset device to factory settings - ESP_LOGI(TAG, "Remote command: reset device to factory settings"); - sprintf(display_lora, "Factory reset"); - eraseConfig(); - break; - } + switch (val) { + case 0: // restart device + ESP_LOGI(TAG, "Remote command: restart device"); + sprintf(display_lora, "Reset pending"); + vTaskDelay(10000/portTICK_PERIOD_MS); // wait for LMIC to confirm LoRa downlink to server + esp_restart(); + break; + case 1: // reset MAC counter + ESP_LOGI(TAG, "Remote command: reset MAC counter"); + reset_counters(); // clear macs + reset_salt(); // get new salt + sprintf(display_lora, "Reset counter"); + break; + case 2: // reset device to factory settings + ESP_LOGI(TAG, "Remote command: reset device to factory settings"); + sprintf(display_lora, "Factory reset"); + eraseConfig(); + break; + } }; void set_rssi(uint8_t val) { - cfg.rssilimit = val * -1; - ESP_LOGI(TAG, "Remote command: set RSSI limit to %d", cfg.rssilimit); -}; + cfg.rssilimit = val * -1; + ESP_LOGI(TAG, "Remote command: set RSSI limit to %d", cfg.rssilimit); +}; void set_sendcycle(uint8_t val) { - cfg.sendcycle = val; - ESP_LOGI(TAG, "Remote command: set payload send cycle to %d seconds", - cfg.sendcycle * 2); -}; + cfg.sendcycle = val; + ESP_LOGI(TAG, "Remote command: set payload send cycle to %d seconds", cfg.sendcycle*2); +}; void set_wifichancycle(uint8_t val) { - cfg.wifichancycle = val; - // modify wifi channel rotation IRQ - timerAlarmWrite( - channelSwitch, cfg.wifichancycle * 10000, - true); // reload interrupt after each trigger of channel switch cycle - ESP_LOGI(TAG, - "Remote command: set Wifi channel switch interval to %.1f seconds", - cfg.wifichancycle / float(100)); -}; + cfg.wifichancycle = val; + // modify wifi channel rotation IRQ + timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true); // reload interrupt after each trigger of channel switch cycle + ESP_LOGI(TAG, "Remote command: set Wifi channel switch interval to %.1f seconds", cfg.wifichancycle/float(100)); +}; void set_blescantime(uint8_t val) { - cfg.blescantime = val; - ESP_LOGI(TAG, "Remote command: set BLE scan time to %.1f seconds", - cfg.blescantime / float(100)); -#ifdef BLECOUNTER - // stop & restart BLE scan task to apply new parameter - if (cfg.blescan) { - stop_BLEscan(); - start_BLEscan(); - } -#endif + cfg.blescantime = val; + ESP_LOGI(TAG, "Remote command: set BLE scan time to %.1f seconds", cfg.blescantime/float(100)); + #ifdef BLECOUNTER + // stop & restart BLE scan task to apply new parameter + if (cfg.blescan) + { + stop_BLEscan(); + start_BLEscan(); + } + #endif }; void set_countmode(uint8_t val) { - switch (val) { - case 0: // cyclic unconfirmed - cfg.countermode = 0; - ESP_LOGI(TAG, "Remote command: set counter mode to cyclic unconfirmed"); - break; - case 1: // cumulative - cfg.countermode = 1; - ESP_LOGI(TAG, "Remote command: set counter mode to cumulative"); - break; - default: // cyclic confirmed - cfg.countermode = 2; - ESP_LOGI(TAG, "Remote command: set counter mode to cyclic confirmed"); - break; - } + switch (val) { + case 0: // cyclic unconfirmed + cfg.countermode = 0; + ESP_LOGI(TAG, "Remote command: set counter mode to cyclic unconfirmed"); + break; + case 1: // cumulative + cfg.countermode = 1; + ESP_LOGI(TAG, "Remote command: set counter mode to cumulative"); + break; + default: // cyclic confirmed + cfg.countermode = 2; + ESP_LOGI(TAG, "Remote command: set counter mode to cyclic confirmed"); + break; + } }; void set_screensaver(uint8_t val) { - ESP_LOGI(TAG, "Remote command: set screen saver to %s ", val ? "on" : "off"); - switch (val) { - case 1: - cfg.screensaver = val; - break; - default: - cfg.screensaver = 0; - break; - } + ESP_LOGI(TAG, "Remote command: set screen saver to %s ", val ? "on" : "off"); + switch (val) { + case 1: cfg.screensaver = val; break; + default: cfg.screensaver = 0; break; + } }; void set_display(uint8_t val) { - ESP_LOGI(TAG, "Remote command: set screen to %s", val ? "on" : "off"); - switch (val) { - case 1: - cfg.screenon = val; - break; - default: - cfg.screenon = 0; - break; - } + ESP_LOGI(TAG, "Remote command: set screen to %s", val ? "on" : "off"); + switch (val) { + case 1: cfg.screenon = val; break; + default: cfg.screenon = 0; break; + } }; void set_gps(uint8_t val) { - ESP_LOGI(TAG, "Remote command: set GPS to %s", val ? "on" : "off"); - switch (val) { - case 1: - cfg.gpsmode = val; - break; - default: - cfg.gpsmode = 0; - break; - } + ESP_LOGI(TAG, "Remote command: set GPS to %s", val ? "on" : "off"); + switch (val) { + case 1: cfg.gpsmode = val; break; + default: cfg.gpsmode = 0; break; + } }; void set_lorasf(uint8_t val) { - ESP_LOGI(TAG, "Remote command: set LoRa SF to %d", val); - switch_lora(val, cfg.txpower); + ESP_LOGI(TAG, "Remote command: set LoRa SF to %d", val); + switch_lora(val, cfg.txpower); }; void set_loraadr(uint8_t val) { - ESP_LOGI(TAG, "Remote command: set LoRa ADR mode to %s", val ? "on" : "off"); - switch (val) { - case 1: - cfg.adrmode = val; - break; - default: - cfg.adrmode = 0; - break; - } - LMIC_setAdrMode(cfg.adrmode); + ESP_LOGI(TAG, "Remote command: set LoRa ADR mode to %s", val ? "on" : "off"); + switch (val) { + case 1: cfg.adrmode = val; break; + default: cfg.adrmode = 0; break; + } + LMIC_setAdrMode(cfg.adrmode); }; void set_blescan(uint8_t val) { - ESP_LOGI(TAG, "Remote command: set BLE scanner to %s", val ? "on" : "off"); - switch (val) { - case 0: - cfg.blescan = 0; - macs_ble = 0; // clear BLE counter -#ifdef BLECOUNTER - stop_BLEscan(); -#endif - break; - default: - cfg.blescan = 1; -#ifdef BLECOUNTER - start_BLEscan(); -#endif - break; - } + ESP_LOGI(TAG, "Remote command: set BLE scanner to %s", val ? "on" : "off"); + switch (val) { + case 0: + cfg.blescan = 0; + macs_ble = 0; // clear BLE counter + #ifdef BLECOUNTER + stop_BLEscan(); + #endif + break; + default: + cfg.blescan = 1; + #ifdef BLECOUNTER + start_BLEscan(); + #endif + break; + } }; void set_wifiant(uint8_t val) { - ESP_LOGI(TAG, "Remote command: set Wifi antenna to %s", - val ? "external" : "internal"); - switch (val) { - case 1: - cfg.wifiant = val; - break; - default: - cfg.wifiant = 0; - break; - } -#ifdef HAS_ANTENNA_SWITCH - antenna_select(cfg.wifiant); -#endif + ESP_LOGI(TAG, "Remote command: set Wifi antenna to %s", val ? "external" : "internal"); + switch (val) { + case 1: cfg.wifiant = val; break; + default: cfg.wifiant = 0; break; + } + #ifdef HAS_ANTENNA_SWITCH + antenna_select(cfg.wifiant); + #endif }; void set_vendorfilter(uint8_t val) { - ESP_LOGI(TAG, "Remote command: set vendorfilter mode to %s", - val ? "on" : "off"); - switch (val) { - case 1: - cfg.vendorfilter = val; - break; - default: - cfg.vendorfilter = 0; - break; - } + ESP_LOGI(TAG, "Remote command: set vendorfilter mode to %s", val ? "on" : "off"); + switch (val) { + case 1: cfg.vendorfilter = val; break; + default: cfg.vendorfilter = 0; break; + } }; void set_rgblum(uint8_t val) { - // Avoid wrong parameters - cfg.rgblum = (val >= 0 && val <= 100) ? (uint8_t)val : RGBLUMINOSITY; - ESP_LOGI(TAG, "Remote command: set RGB Led luminosity %d", cfg.rgblum); + // Avoid wrong parameters + cfg.rgblum = (val>=0 && val<=100) ? (uint8_t) val : RGBLUMINOSITY; + ESP_LOGI(TAG, "Remote command: set RGB Led luminosity %d", cfg.rgblum); }; void set_lorapower(uint8_t val) { - ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %d", val); - switch_lora(cfg.lorasf, val); + ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %d", val); + switch_lora(cfg.lorasf, val); }; -void get_config(uint8_t val) { - ESP_LOGI(TAG, "Remote command: get configuration"); - transmit((byte *)&cfg, sizeof(cfg)); +void get_config (uint8_t val) { + ESP_LOGI(TAG, "Remote command: get configuration"); + transmit((byte*)&cfg, sizeof(cfg)); }; -void get_uptime(uint8_t val) { - ESP_LOGI(TAG, "Remote command: get uptime"); - transmit((byte *)&uptimecounter, sizeof(uptimecounter)); +void get_uptime (uint8_t val) { + ESP_LOGI(TAG, "Remote command: get uptime"); + transmit((byte*)&uptimecounter, sizeof(uptimecounter)); }; -void get_cputemp(uint8_t val) { - ESP_LOGI(TAG, "Remote command: get cpu temperature"); - float temp = temperatureRead(); - transmit((byte *)&temp, sizeof(temp)); +void get_cputemp (uint8_t val) { + ESP_LOGI(TAG, "Remote command: get cpu temperature"); + float temp = temperatureRead(); + transmit((byte*)&temp, sizeof(temp)); }; -void get_voltage(uint8_t val) { - ESP_LOGI(TAG, "Remote command: get battery voltage"); -#ifdef HAS_BATTERY_PROBE - uint16_t voltage = read_voltage(); -#else - uint16_t voltage = 0; -#endif - transmit((byte *)&voltage, sizeof(voltage)); +void get_voltage (uint8_t val) { + ESP_LOGI(TAG, "Remote command: get battery voltage"); + #ifdef HAS_BATTERY_PROBE + uint16_t voltage = read_voltage(); + #else + uint16_t voltage = 0; + #endif + transmit((byte*)&voltage, sizeof(voltage)); }; -void get_gps(uint8_t val) { - ESP_LOGI(TAG, "Remote command: get gps status"); -#ifdef HAS_GPS - gps_read(); - transmit((byte *)&gps_status, sizeof(gps_status)); - ESP_LOGI(TAG, "lat=%f / lon=%f | Sats=%u | HDOP=%u | Alti=%u", - gps_status.latitude / 1000000, gps_status.longitude / 1000000, - gps_status.satellites, gps_status.hdop, gps_status.altitude); -#else - ESP_LOGE(TAG, "GPS not present"); -#endif +void get_gps (uint8_t val) { + ESP_LOGI(TAG, "Remote command: get gps status"); + #ifdef HAS_GPS + gps_read(); + transmit((byte*)&gps_status, sizeof(gps_status)); + ESP_LOGI(TAG, "lat=%f / lon=%f | Sats=%u | HDOP=%u | Alti=%u", gps_status.latitude / 1000000, gps_status.longitude / 1000000, gps_status.satellites, gps_status.hdop, gps_status.altitude); + #else + ESP_LOGE(TAG, "GPS not present"); + #endif }; // assign previously defined functions to set of numeric remote commands // format: opcode, function, flag (1 = do make settings persistent / 0 = don't) -// -cmd_t table[] = {{0x01, set_rssi, true}, {0x02, set_countmode, true}, - {0x03, set_gps, true}, {0x04, set_display, true}, - {0x05, set_lorasf, true}, {0x06, set_lorapower, true}, - {0x07, set_loraadr, true}, {0x08, set_screensaver, true}, - {0x09, set_reset, false}, {0x0a, set_sendcycle, true}, - {0x0b, set_wifichancycle, true}, {0x0c, set_blescantime, true}, - {0x0d, set_vendorfilter, false}, {0x0e, set_blescan, true}, - {0x0f, set_wifiant, true}, {0x10, set_rgblum, true}, - {0x80, get_config, false}, {0x81, get_uptime, false}, - {0x82, get_cputemp, false}, {0x83, get_voltage, false}, - {0x84, get_gps, false}}; +// +cmd_t table[] = { + {0x01, set_rssi, true}, + {0x02, set_countmode, true}, + {0x03, set_gps, true}, + {0x04, set_display, true}, + {0x05, set_lorasf, true}, + {0x06, set_lorapower, true}, + {0x07, set_loraadr, true}, + {0x08, set_screensaver, true}, + {0x09, set_reset, false}, + {0x0a, set_sendcycle, true}, + {0x0b, set_wifichancycle, true}, + {0x0c, set_blescantime, true}, + {0x0d, set_vendorfilter, false}, + {0x0e, set_blescan, true}, + {0x0f, set_wifiant, true}, + {0x10, set_rgblum, true}, + {0x80, get_config, false}, + {0x81, get_uptime, false}, + {0x82, get_cputemp, false}, + {0x83, get_voltage, false}, + {0x84, get_gps, false} + }; // check and execute remote command void rcommand(uint8_t cmd, uint8_t arg) { - int i = - sizeof(table) / sizeof(table[0]); // number of commands in command table - bool store_flag = false; - while (i--) { - if (cmd == table[i].nam) { // check if valid command - table[i].func(arg); // then execute assigned function - if (table[i].store) - store_flag = - true; // set save flag if function needs to store configuration - break; // exit check loop, since command was found + int i = sizeof(table) / sizeof(table[0]); // number of commands in command table + bool store_flag = false; + while(i--) { + if(cmd == table[i].nam) { // check if valid command + table[i].func(arg); // then execute assigned function + if ( table[i].store ) store_flag = true; // set save flag if function needs to store configuration + break; // exit check loop, since command was found + } } - } - if (store_flag) - saveConfig(); // if save flag is set: store new configuration in NVS to make - // it persistent + if (store_flag) saveConfig(); // if save flag is set: store new configuration in NVS to make it persistent } \ No newline at end of file diff --git a/src/rgb_led.cpp b/src/rgb_led.cpp index 772f0a0b..899ded9e 100644 --- a/src/rgb_led.cpp +++ b/src/rgb_led.cpp @@ -6,22 +6,23 @@ // 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; +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 < 1.0f / 6.0f) + return p + (q - p) * 6.0f * t; - if (t < 0.5f) - return q; + if (t < 0.5f) + return q; - if (t < 2.0f / 3.0f) - return p + ((q - p) * (2.0f / 3.0f - t) * 6.0f); + if (t < 2.0f / 3.0f) + return p + ((q - p) * (2.0f / 3.0f - t) * 6.0f); - return p; + return p; } // ------------------------------------------------------------------------ @@ -29,41 +30,45 @@ float rgb_CalcColor(float p, float q, float t) { // 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; +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); - } + 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); + 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; + return RGB_color; } void rgb_set_color(uint16_t hue) { if (hue == COLOR_NONE) { // Off - rgb_led[0] = Rgb(0, 0, 0); + 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; + 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 diff --git a/src/rgb_led.h b/src/rgb_led.h index 49aa5f76..589b3f94 100644 --- a/src/rgb_led.h +++ b/src/rgb_led.h @@ -3,26 +3,27 @@ // value for HSL color // see http://www.workwithcolor.com/blue-color-hue-range-01.htm -#define COLOR_RED 0 -#define COLOR_ORANGE 30 -#define COLOR_ORANGE_YELLOW 45 -#define COLOR_YELLOW 60 -#define COLOR_YELLOW_GREEN 90 -#define COLOR_GREEN 120 -#define COLOR_GREEN_CYAN 165 -#define COLOR_CYAN 180 -#define COLOR_CYAN_BLUE 210 -#define COLOR_BLUE 240 -#define COLOR_BLUE_MAGENTA 275 -#define COLOR_MAGENTA 300 -#define COLOR_PINK 350 -#define COLOR_WHITE 360 -#define COLOR_NONE 999 +#define COLOR_RED 0 +#define COLOR_ORANGE 30 +#define COLOR_ORANGE_YELLOW 45 +#define COLOR_YELLOW 60 +#define COLOR_YELLOW_GREEN 90 +#define COLOR_GREEN 120 +#define COLOR_GREEN_CYAN 165 +#define COLOR_CYAN 180 +#define COLOR_CYAN_BLUE 210 +#define COLOR_BLUE 240 +#define COLOR_BLUE_MAGENTA 275 +#define COLOR_MAGENTA 300 +#define COLOR_PINK 350 +#define COLOR_WHITE 360 +#define COLOR_NONE 999 -struct RGBColor { - uint8_t R; - uint8_t G; - uint8_t B; +struct RGBColor +{ + uint8_t R; + uint8_t G; + uint8_t B; }; // Exported Functions diff --git a/src/rokkithash.cpp b/src/rokkithash.cpp index 62e12656..98b6c5c3 100644 --- a/src/rokkithash.cpp +++ b/src/rokkithash.cpp @@ -36,52 +36,48 @@ #include -uint32_t rokkit(const char *data, int len) { +uint32_t rokkit(const char * data, int len) { uint32_t hash, tmp; int rem; - if (len <= 0 || data == 0) - return 0; - hash = len; - rem = len & 3; - len >>= 2; + if (len <= 0 || data == 0) return 0; + hash = len; + rem = len & 3; + len >>= 2; - /* Main loop */ - while (len > 0) { - hash += *((uint16_t *)data); - tmp = (*((uint16_t *)(data + 2)) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - data += 2 * 2; - hash += hash >> 11; - len--; - } + /* Main loop */ + while (len > 0) { + hash += *((uint16_t*)data); + tmp = (*((uint16_t*)(data+2)) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2*2; + hash += hash >> 11; + len--; + } - /* Handle end cases */ - switch (rem) { - case 3: - hash += *((uint16_t *)data); - hash ^= hash << 16; - hash ^= ((signed char)data[2]) << 18; - hash += hash >> 11; - break; - case 2: - hash += *((uint16_t *)data); - hash ^= hash << 11; + /* Handle end cases */ + switch (rem) { + case 3: hash += *((uint16_t*)data); + hash ^= hash << 16; + hash ^= ((signed char)data[2]) << 18; + hash += hash >> 11; + break; + case 2: hash += *((uint16_t*)data); + hash ^= hash << 11; + hash += hash >> 17; + break; + case 1: hash += (signed char)*data; + hash ^= hash << 10; + hash += hash >> 1; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; hash += hash >> 17; - break; - case 1: - hash += (signed char)*data; - hash ^= hash << 10; - hash += hash >> 1; - } + hash ^= hash << 25; + hash += hash >> 6; - /* Force "avalanching" of final 127 bits */ - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 4; - hash += hash >> 17; - hash ^= hash << 25; - hash += hash >> 6; - - return hash; + return hash; } diff --git a/src/vendor_array.h b/src/vendor_array.h index fd555495..9b610782 100644 --- a/src/vendor_array.h +++ b/src/vendor_array.h @@ -1,206 +1,1435 @@ std::array vendors = { - 0x38f23e, 0x807abf, 0x90e7c4, 0x7c6193, 0x485073, 0x74e28c, 0x8463d6, - 0xd48f33, 0x2c8a72, 0x980d2e, 0xa826d9, 0xd4206d, 0x00155d, 0x806c1b, - 0xa470d6, 0x985fd3, 0x1c69a5, 0x382de8, 0xd087e2, 0x205531, 0x5440ad, - 0x842e27, 0x50f0d3, 0x84119e, 0x08eca9, 0x10d38a, 0x382dd1, 0xe0cbee, - 0x64b853, 0xf4428f, 0x188331, 0x8455a5, 0xa87c01, 0xc01173, 0xbce63f, - 0xb857d8, 0x94b10a, 0xe458b8, 0x088c2c, 0xb86ce8, 0x9c65b0, 0xc8a823, - 0xc44202, 0xd059e4, 0x64b310, 0x9476b7, 0x8c1abf, 0xb47443, 0x30cbf8, - 0x182195, 0xa88195, 0x88add2, 0xd0fccc, 0x14c913, 0x4c6641, 0x3cbdd8, - 0x38256b, 0x849866, 0xe89309, 0x0016db, 0x5c3c27, 0x10d542, 0xa0821f, - 0xc45006, 0x88329b, 0xbc8ccd, 0x400e85, 0xec9bf3, 0xf8042e, 0x843838, - 0x54880e, 0xbc79ad, 0x30d6c9, 0xb0df3a, 0x805719, 0x78a873, 0x041bba, - 0x08fd0e, 0x08d42b, 0x00e3b2, 0xc81479, 0xf0728c, 0x94350a, 0x001fcd, - 0xd0dfc7, 0x1c62b8, 0x18e2c2, 0x001a8a, 0x002567, 0xa8f274, 0x001599, - 0x0012fb, 0x7cf854, 0x8cc8cd, 0xe81132, 0xa02195, 0x8c71f8, 0x04180f, - 0x9463d1, 0x0cdfa4, 0xcc051b, 0x68ebae, 0x60d0a9, 0x60a10a, 0xa07591, - 0x001fcc, 0xec107b, 0xa01081, 0xf4f524, 0x9c99a0, 0x185936, 0x98fae3, - 0x640980, 0x8cbebe, 0xf8a45f, 0xbc8385, 0x900628, 0xd4ae05, 0x3c0518, - 0xc40bcb, 0xe8bba8, 0xbc3aea, 0x8c0ee3, 0x6c5c14, 0x78abbb, 0x1816c9, - 0xfc8f90, 0x244b03, 0x988389, 0x14bb6e, 0x1c3ade, 0xf83f51, 0xd8e0e1, - 0xecf342, 0x5092b9, 0xb4bff6, 0xc8d7b0, 0x982d68, 0xecd09f, 0xe446da, - 0xf4f5db, 0xd80831, 0xdc5583, 0x2c54cf, 0x001fe3, 0x0026e2, 0x001e75, - 0x6cd68a, 0x2021a5, 0x0c4885, 0xdc0b34, 0xac0d1b, 0x60e3ac, 0xf895c7, - 0xc4438f, 0xa816b2, 0xe892a4, 0x700514, 0x88c9d0, 0x2c598a, 0x18f0e4, - 0xec8350, 0x4cdd31, 0x703eac, 0x6c94f8, 0x84788b, 0x2cf0ee, 0x68d93c, - 0x24e314, 0x28f076, 0x285aeb, 0x087402, 0xccc760, 0x705aac, 0xfc643a, - 0xd4e6b7, 0x2802d8, 0x9c2ea1, 0x68967b, 0xbc6778, 0xa82066, 0xb065bd, - 0xf0dce2, 0x7cd1c3, 0x705681, 0x2cbe08, 0x783a84, 0x84b153, 0x6476ba, - 0x54ae27, 0xf437b7, 0xf0d1a9, 0x34c059, 0x04f7e4, 0x10ddb1, 0xb4f0ab, - 0x848506, 0x7831c1, 0x8c7c92, 0xd0e140, 0xacfdec, 0xf82793, 0x40a6d9, - 0x109add, 0xf0b479, 0x58b035, 0x34159e, 0x286aba, 0xec852f, 0x44d884, - 0x003ee1, 0x7c11be, 0x04e536, 0x881fa1, 0x04db56, 0x9cfc01, 0xc81ee7, - 0x34363b, 0xc01ada, 0xacbc32, 0x70700d, 0x7c5049, 0x503237, 0xd4619d, - 0xb0481a, 0x989e63, 0xdca904, 0x48a195, 0x6cab31, 0x6c96cf, 0x3035ad, - 0xa8be27, 0xb8634d, 0x9ce33f, 0xf0989d, 0xace4b5, 0xe42b34, 0x1c36bb, - 0x3c2eff, 0xf0766f, 0x40cbc0, 0x4098ad, 0x6c4d73, 0xc48466, 0xd02b20, - 0x3010e4, 0x380f4a, 0x685b35, 0xc86f1d, 0x701124, 0x38484c, 0x041552, - 0x786c1c, 0xbc3baf, 0x00a040, 0x60fec5, 0xcc4463, 0x6c72e7, 0x18af61, - 0x00cdfe, 0xac61ea, 0x38b54d, 0x60c547, 0x28e02c, 0x50ead6, 0x4860bc, - 0x403004, 0x0c74c2, 0xa4b197, 0x7cf05f, 0xa4f1e8, 0x70a2b3, 0x4c57ca, - 0x68fb7e, 0x90c1c6, 0x9cf48e, 0xfcd848, 0x64b9e8, 0x001cb3, 0x000d93, - 0x30d9d9, 0x6030d4, 0x94bf2d, 0xc49880, 0xe0338e, 0x68fef7, 0xbce143, - 0x645aed, 0xc0b658, 0x881908, 0xfc2a9c, 0x48605f, 0x188796, 0x002376, - 0x84100d, 0x04c23e, 0x5c5188, 0xe89120, 0x9c6c15, 0x4886e8, 0x2c2997, - 0x102f6b, 0x00eebd, 0x281878, 0x6045bd, 0x7ced8d, 0xe85b5b, 0x000d3a, - 0xe09861, 0xf4f1e1, 0x60beb5, 0xb4e1c4, 0x70aab2, 0x0026ff, 0x406f2a, - 0x002557, 0xf05a09, 0x503275, 0x28cc01, 0xb46293, 0x04fe31, 0x845181, - 0xd831cf, 0xf8d0bd, 0xfcc734, 0xe4b021, 0xb0ec71, 0x3cbbfd, 0x2cae2b, - 0xc488e5, 0x7c9122, 0xe8b4c8, 0x18895b, 0xe0db10, 0xe09971, 0x6077e2, - 0x680571, 0x6c2f2c, 0x300d43, 0x6c2779, 0x607edd, 0x9c2a83, 0xe45d75, - 0xe4faed, 0xc83f26, 0x54f201, 0xa06090, 0xac3743, 0x141f78, 0x006f64, - 0xdc6672, 0x001e7d, 0x3c6200, 0x0024e9, 0x002399, 0xe4e0c5, 0xe8039a, - 0xc4731e, 0x8c7712, 0x2013e0, 0x0007ab, 0x0021d2, 0xbc4760, 0xd0176a, - 0x2cbaba, 0x24920e, 0x40d3ae, 0xf01dbc, 0x24dbed, 0xac3613, 0x1449e0, - 0xc0bdd1, 0xe8508b, 0xf025b7, 0xc8ba94, 0xec1f72, 0x9852b1, 0x1489fd, - 0xccfe3c, 0x789ed0, 0xe440e2, 0x1caf05, 0xe492fb, 0x0073e0, 0xbc4486, - 0x380b40, 0x002490, 0x0023d7, 0xfca13e, 0xa00798, 0x945103, 0xc819f7, - 0x2c4401, 0x28e31f, 0x0c1daf, 0x14f65a, 0x742344, 0xf0b429, 0xec51bc, - 0xf079e8, 0x887598, 0xd0b128, 0xd00401, 0xf06d78, 0x10683f, 0x74a722, - 0x58a2b5, 0x64899a, 0x88074b, 0x64bc0c, 0xa039f7, 0x041b6d, 0x001f6b, - 0x30b4b8, 0x503cea, 0x0c9838, 0x54fcf0, 0x08aed6, 0xa816d0, 0x88bd45, - 0x544e90, 0xd03311, 0x70e72c, 0xc0cecd, 0x98e0d9, 0xe0accb, 0x78d75f, - 0x2078f0, 0x985aeb, 0xa45e60, 0x006d52, 0x5cadcf, 0xb8e856, 0x90b21f, - 0xa8bbcf, 0xc8b5b7, 0x18af8f, 0xf4f951, 0xf0c1f1, 0xec3586, 0x88cb87, - 0xac3c0b, 0xcc785f, 0xe88d28, 0x3ce072, 0xf41ba1, 0xa85b78, 0x9cf387, - 0x34a395, 0x48437c, 0xac87a3, 0x00f76f, 0xc0f2fb, 0x1caba7, 0x60facd, - 0x680927, 0x78a3e4, 0x68a86d, 0xb817c2, 0xb88d12, 0x5c8d4e, 0xe06678, - 0x1c1ac0, 0xc8f650, 0x60d9c7, 0x44fb42, 0x64a3cb, 0xd8d1cb, 0x542696, - 0x14109f, 0xbc52b7, 0xe0c97a, 0x5c95ae, 0x8cfaba, 0x0cbc9f, 0xbc4cc4, - 0x0c1539, 0x908d6c, 0x80006e, 0xb418d1, 0x1499e2, 0xe0c767, 0xa860b6, - 0x24f094, 0x90b0ed, 0xc4b301, 0xe05f45, 0x483b38, 0x88e87f, 0xb853ac, - 0x2c3361, 0x784f43, 0x404d7f, 0xbc926b, 0x0452f3, 0x241eeb, 0xf431c3, - 0x64a5c3, 0x606944, 0xe498d6, 0x0cd746, 0x440010, 0x1c9e46, 0x7c04d0, - 0xbc9fef, 0x8866a5, 0x70f087, 0x886b6e, 0x4c74bf, 0x844167, 0xb4f61c, - 0xe49adc, 0xb8c111, 0x3408bc, 0xd0817a, 0xc4618b, 0x68ab1e, 0x2c61f6, - 0x0026bb, 0x00254b, 0x002436, 0x002332, 0x002312, 0x0019e3, 0x001451, - 0x000a27, 0x003065, 0x0050e4, 0xd023db, 0xe0b9ba, 0x3451c9, 0x8c5877, - 0x9803d8, 0xc82a14, 0x88c663, 0x8c7b9d, 0x5855ca, 0xcc08e0, 0xe80688, - 0x641cb0, 0x3cdcbc, 0xf47190, 0x587a6a, 0xe4c483, 0x8cf5a3, 0x14568e, - 0x8058f8, 0xf0d7aa, 0xc49ded, 0xb0aa36, 0x2c5bb8, 0x1c48ce, 0x24f5aa, - 0xf877b8, 0x682737, 0x5056bf, 0x9097f3, 0x58c5cb, 0xacafb9, 0x30074d, - 0x5c5181, 0x389af6, 0xe0aa96, 0x507705, 0x2c4053, 0x084acf, 0x1cddea, - 0x08152f, 0xd461da, 0xc8d083, 0x88e9fe, 0x88ae07, 0x5c0947, 0x38892c, - 0x40831d, 0x50bc96, 0x9ce65e, 0x90dd5d, 0x08f69c, 0x00092d, 0xf8db7f, - 0xe899c4, 0x24da9b, 0x1c56fe, 0xe4907e, 0x80c5e6, 0x800184, 0xf8cfc5, - 0xc808e9, 0x206274, 0x30d587, 0xc0eefb, 0x502e5c, 0x847a88, 0x0025ae, - 0x002538, 0x0022a1, 0x00125a, 0x9cd917, 0x9068c3, 0x408805, 0xf8f1b6, - 0x001ccc, 0x94ebcd, 0xa4e4b8, 0x389496, 0x0cb319, 0x08ee8b, 0xa89fba, - 0xfc1910, 0x083d88, 0x5c2e59, 0x646cb2, 0xf884f2, 0x14b484, 0x608f5c, - 0x4cbca5, 0x78595e, 0xb0d09c, 0x4ca56d, 0xa48431, 0xe4f8ef, 0x1432d1, - 0xe458e7, 0x8cbfa6, 0x7840e4, 0x9000db, 0x183a2d, 0x08373d, 0x50f520, - 0xa4ebd3, 0x28987b, 0xf40e22, 0x9c3aaf, 0x0821ef, 0xa0cbfd, 0x34145f, - 0x6c8fb5, 0xac5f3e, 0x509ea7, 0xdccf96, 0x6c2483, 0xc09727, 0xd85b2a, - 0xacc33a, 0x88797e, 0x00e091, 0x6cd032, 0xc041f6, 0x0017d5, 0x001247, - 0xe4121d, 0x684898, 0xf409d8, 0xb479a7, 0x002339, 0xd487d8, 0x184617, - 0x5001bb, 0x380a94, 0xd857ef, 0x1c66aa, 0x58c38b, 0x001ee2, 0x001c43, - 0x001d25, 0x3c5a37, 0x549b12, 0x3c8bfe, 0x00265d, 0xd4e8b2, 0x0808c2, - 0xb0c4e7, 0xd890e8, 0x34aa8b, 0x24c696, 0x181eb0, 0x20d390, 0x343111, - 0x34be00, 0x78521a, 0x7825ad, 0xf4d9fb, 0x0017c9, 0x00166b, 0x00166c, - 0xe47cf9, 0x002454, 0x20d5bf, 0x30cda7, 0xc87e75, 0x00233a, 0x60a4d0, - 0x2c0e3d, 0xd4970b, 0x64cc2e, 0xb0e235, 0x38a4ed, 0xf48b32, 0x7c787e, - 0xc0d3c0, 0x440444, 0xc09f05, 0xcc2d83, 0x38295a, 0x4c1a3d, 0xa81b5a, - 0xdc6dcd, 0x54fa3e, 0x0c8910, 0xfcf136, 0x981dfa, 0x84a466, 0x1867b0, - 0xccb11a, 0xb8bbaf, 0x60c5ad, 0x28395e, 0xc4ae12, 0xdc74a8, 0xc087eb, - 0x74f61c, 0x986f60, 0x4c189a, 0x3cf591, 0x602101, 0xa89675, 0x608e08, - 0x7c2edd, 0x3cf7a4, 0x342d0d, 0x94d029, 0x308454, 0x4c49e3, 0x087808, - 0xd03169, 0xbc5451, 0x00bf61, 0xf80cf3, 0x30766f, 0x8c3ae3, 0x78f882, - 0xb4f1da, 0x0021fb, 0xd013fd, 0xa8b86e, 0x04b167, 0xd86375, 0xdcbfe9, - 0x306a85, 0x2047da, 0x8035c1, 0xd02598, 0xa8667f, 0x7014a6, 0x10417f, - 0xac293a, 0x94e96a, 0x0c4de9, 0x907240, 0xa88808, 0xc8e0eb, 0x54e43a, - 0x28e14c, 0x848e0c, 0xb03495, 0xf0f61c, 0x0c3021, 0xd89695, 0x649abe, - 0x5cf5da, 0x20a2e4, 0xf02475, 0x24a074, 0x8863df, 0x609217, 0x34e2fd, - 0x0c3e9f, 0x6c709f, 0x6c4008, 0x5c97f3, 0x90fd61, 0x006171, 0x80e650, - 0xdc2b2a, 0xb844d9, 0xe0f5c6, 0x949426, 0xcc29f5, 0x58404e, 0xdc0c5c, - 0x2c200b, 0xdca4ca, 0x8c8fe9, 0x9810e8, 0xb49cdf, 0xa4e975, 0xc0a53e, - 0x9800c6, 0x787b8a, 0x3866f0, 0x20ee28, 0x08f4ab, 0x8c8590, 0xb48b19, - 0xe49a79, 0x28a02b, 0xb44bd2, 0x2cf0a2, 0xecadb8, 0x9801a7, 0x609ac1, - 0xf07960, 0x9c8ba0, 0x4c3275, 0xe4e4ab, 0xc8334b, 0x00f4b9, 0x0c771a, - 0x74e1b6, 0x64200c, 0xc0847a, 0x183451, 0xfc253f, 0x1040f3, 0x6cc26b, - 0x182032, 0x70dee2, 0x00c610, 0x101c0c, 0x7cfadf, 0x5cf938, 0x3871de, - 0xbc5436, 0x9c4fda, 0x1c5cf2, 0x60fb42, 0x002500, 0x00236c, 0x0021e9, - 0x001ff3, 0x001f5b, 0x001e52, 0x001d4f, 0x001124, 0xa8fad8, 0x5c969d, - 0xe48b7f, 0x84fcfe, 0x444c0c, 0x8c2daa, 0x6c3e6d, 0x189efc, 0xc09f42, - 0xb8f6b1, 0x406c8f, 0xa4d1d2, 0x040cce, 0xd89e3f, 0x28e7cf, 0xc8bcc8, - 0xd8a25e, 0x90840d, 0xf81edf, 0xb0ca68, 0x98ca33, 0x68ef43, 0xcc2db7, - 0xd4a33d, 0xe4e0a6, 0x70ef00, 0x80ad16, 0x641cae, 0x14205e, 0x5c1dd9, - 0x18f1d8, 0xf86fc1, 0xf099b6, 0xdcd3a2, 0x38e7d8, 0xd8b377, 0xb4cef6, - 0xd40b1a, 0x5882a8, 0xb4ae2b, 0x0c413e, 0xd0929e, 0x4480eb, 0xb84fd5, - 0xec59e7, 0x3059b7, 0x501ac5, 0x1cb094, 0xa0f450, 0x002248, 0xec8892, - 0xb07994, 0x141aa3, 0xccc3ea, 0x34bb26, 0x40786a, 0xf40b93, 0x68ed43, - 0x34bb1f, 0x489d24, 0x000f86, 0xacee9e, 0xc08997, 0x2827bf, 0xf05b7b, - 0x7cf90e, 0xac5a14, 0xb0c559, 0xbcd11f, 0xa0b4a5, 0x80656d, 0x48137e, - 0xe83a12, 0x9c0298, 0x6c8336, 0xb8c68e, 0x74458a, 0xa49a58, 0xb4ef39, - 0x14a364, 0x3ca10d, 0x206e9c, 0x183f47, 0x0c715d, 0x0c1420, 0xa80600, - 0x6cf373, 0x78c3e9, 0xc83870, 0x288335, 0x44783e, 0x202d07, 0x98398e, - 0x348a7b, 0xbc765e, 0x78009e, 0x68c44d, 0xf8e61a, 0x888322, 0x84b541, - 0x0015b9, 0x001df6, 0xece09b, 0x606bbd, 0x0000f0, 0x4844f7, 0x1c5a3e, - 0xf47b5e, 0x008701, 0xfc4203, 0x1c232c, 0xcc61e5, 0x404e36, 0x009ec8, - 0xacf7f3, 0x102ab3, 0x584498, 0xa086c6, 0x7c1dd9, 0x9893cc, 0x3ccd93, - 0xf06bca, 0x3423ba, 0xd022be, 0xd02544, 0xbc20a4, 0x14f42a, 0xbc851f, - 0xb85e7b, 0xc462ea, 0x0023d6, 0x002491, 0x001b98, 0x44f459, 0x34c3ac, - 0x94d771, 0x4c3c16, 0x9401c2, 0xb43a28, 0xd0c1b1, 0xf008f1, 0x78471d, - 0x3816d1, 0xd48890, 0x002566, 0x00265f, 0xacc1ee, 0x5cba37, 0x7802f8, - 0x3096fb, 0xf0ee10, 0xa43d78, 0xec01ee, 0xb83765, 0xc4576e, 0x90f1aa, - 0x78bdbc, 0xd47ae2, 0x84c0ef, 0x7c1c68, 0xd463c6, 0x508f4c, 0x7c6456, - 0x448f17, 0x04d6aa, 0x9ce063, 0xf06e0b, 0x5c865c, 0xf0b0e7, 0x209bcd, - 0xcc20e8, 0x04d13a, 0x0cf346, 0x003de8, 0x485929, 0x34fcef, 0x002483, - 0x001c62, 0x583f54, 0x40b0fa, 0xa8922c, 0x98d6f7, 0x505527, 0x0034da, - 0xa09169, 0x88365f, 0x9c8c6e, 0xbcffeb, 0x685acf, 0x48746e, 0x54724f, - 0x04f13e, 0x600308, 0x80ea96, 0x24a2e1, 0x90b931, 0x280b5c, 0xa8968a, - 0x9c04eb, 0x885395, 0x80929f, 0x98b8e3, 0xd8004d, 0x98fe94, 0x68644b, - 0xf099bf, 0xfce998, 0x48e9f1, 0x4c7c5f, 0x60f81d, 0x689c70, 0x2cb43a, - 0x042665, 0xf4f15a, 0x207d74, 0x4c8d79, 0xfcfc48, 0x38c986, 0x70ece4, - 0xd81d72, 0x94f6a3, 0x78fd94, 0x48d705, 0x7c6df8, 0x3cab8e, 0x787e61, - 0xd4f46f, 0xc88550, 0xac7f3e, 0xa4c361, 0x087045, 0x40331a, 0xdc3714, - 0x789f70, 0x64b0a6, 0x84fcac, 0x6c19c0, 0x20ab37, 0xc0d012, 0xd4dccd, - 0x484baa, 0xf80377, 0x14bd61, 0x78886d, 0xa85c2c, 0x00db70, 0xbcec5d, - 0xdc415f, 0x30636b, 0x0c5101, 0x086d41, 0x04d3cf, 0x203cae, 0x748d08, - 0xa03be3, 0x186590, 0x0010fa, 0x000502, 0xb8782e, 0xa4d18c, 0xcc25ef, - 0x68dbca, 0x044bed, 0x6c8dc1, 0x38cada, 0xf45c89, 0x581faa, 0x24ab81, - 0x70cd60, 0x7cc537, 0xc42c03, 0xd83062, 0x40d32d, 0x7c6d62, 0x286ab8, - 0x403cfc, 0xb8c75d, 0xe8040b, 0xe4ce8f, 0x3c0754, 0xa46706, 0x80b03d, - 0xc83c85, 0xa04ea7, 0x409c28, 0x08e689, 0x4cb199, 0x98d6bb, 0x3cd0f8, - 0x7cc3a1, 0x002608, 0x001ec2, 0x001b63, 0x0017f2, 0x0016cb, 0x000393, - 0x804971, 0x64e682, 0xb4f7a1, 0x785dc8, 0x48c796, 0x804e70, 0x3880df, - 0x1094bb, 0xf01898, 0x48a91c, 0xa056f3, 0x549963, 0x28ff3c, 0x902155, - 0x64a769, 0xbccfcc, 0xa4516f, 0x3c8375, 0x149a10, 0x0ce725, 0xc0335e, - 0x20a99b, 0x4c0bbe, 0x7c1e52, 0xdcb4c4, 0x001dd8, 0x0017fa, 0x0003ff, - 0xf8e079, 0x1430c6, 0xe0757d, 0x9cd35b, 0x60af6d, 0xb85a73, 0x103047, - 0x109266, 0xb047bf, 0x7c0bc6, 0x804e81, 0x244b81, 0x50a4c8, 0x8425db, - 0xd8c4e9, 0x50c8e5, 0x446d6c, 0x38d40b, 0x647791, 0x781fdb, 0x08fc88, - 0x30c7ae, 0x18227e, 0x00f46f, 0x9ce6e7, 0xe498d1, 0x5cca1a, 0x70288b, - 0x4849c7, 0x205ef7, 0x182666, 0xc06599, 0xcc07ab, 0xe84e84, 0x50fc9f, - 0xe432cb, 0x889b39, 0xbcb1f3, 0x38ece4, 0xccf9e8, 0xf0e77e, 0x5ce8eb, - 0xb8d9ce, 0x70f927, 0x301966, 0x28bab5, 0x103b59, 0x6cb7f4, 0x001ee1, - 0x0018af, 0xbc72b1, 0x78f7be, 0xf49f54, 0x00214c, 0x001632, 0xd0667b, - 0x001377, 0x50b7c3, 0x8018a7, 0x444e1a, 0xe8e5d6, 0x5492be, 0x101dc0, - 0x0021d1, 0x68dfdd, 0xc46ab7, 0xfc64ba, 0x2082c0, 0x3480b3, 0x7451ba, - 0x64b473, 0xcc2d8c, 0x949aa9, 0x20dbab, 0x5c9960, 0x948bc1, 0x4827ea, - 0x388c50, 0xa09347, 0xc8f230, 0x1c77f6, 0xe44790, 0xd4503f, 0x40163b, - 0x5c497d, 0xe47dbd, 0x503da1, 0x508569, 0x1077b1, 0x5cf6dc, 0x380195, - 0xbc1485, 0x88d50c, 0x947be7, 0x00ec0a, 0x54bd79, 0xdc44b6, 0x1007b6, - 0xc0174d, 0xa407b6, 0x149f3c, 0x88b4a6, 0x2c5491, 0x5c70a3, 0x10f96f, - 0xf01c13, 0x00aa70, 0xbcf5ac, 0xccfa00, 0xf8a9d0, 0x805a04, 0x5caf06, - 0xb81daa, 0x10f1f2, 0x0025e5, 0x0022a9, 0xc49a02, 0x344df7, 0xd41a3f, - 0xcc6ea4, 0xa46cf1, 0x0ca8a7, 0x54b802, 0x0469f8, 0xbc6c21, 0xc869cd, - 0x80d605, 0x587f57, 0xa4b805, 0x70480f, 0x18f643, 0x748114, 0x18ee69, - 0xf0dbe2, 0xb8098a, 0x549f13, 0x2c1f23, 0x507a55, 0x9c35eb, 0xa43135, - 0xd0034b, 0xa01828, 0xd0a637, 0xd04f7e, 0xd8bb2c, 0x80be05, 0xe0b52d, - 0x68ae20, 0xe8802e, 0x7c0191, 0x9c293f, 0x341298, 0x903c92, 0x24240e, - 0xa0999b, 0xe0f847, 0x442a60, 0x1093e9, 0xdc2b61, 0xb8ff61, 0x18e7f4, - 0x78ca39, 0x5c5948, 0x60334b, 0x9027e4, 0xd49a20, 0xb09fba, 0x8c006d, - 0xc06394, 0x843835, 0xe4c63d, 0x54eaa8, 0xa886dd, 0xaccf5c, 0xf0dbf8, - 0x98f0ab, 0xdc9b9c, 0x8c2937, 0xdc86d8, 0xa88e24, 0xd8cf9c, 0x04489a, - 0x3c15c2, 0x20c9d0, 0x74e2f5, 0x842999, 0x9c207b, 0x283737, 0x148fc6, - 0x28cfda, 0x145a05, 0xa0edcd, 0x1ce62b, 0x3090ab, 0x7073cb, 0xf0cba1, - 0x045453, 0x40b395, 0x008865, 0x30f7c5, 0x20768f, 0xc0ccf8, 0x80ed2c, - 0xe8b2ac, 0x8489ad, 0x8c8ef2, 0xf40f24, 0x84a134, 0x1c9148, 0x5cf7e6, - 0xa0d795, 0xcc088d, 0x00b362, 0xf86214, 0xb0702d, 0xd0c5f3, 0x60f445, - 0x5082d5, 0x9c84bf, 0x48bf6b, 0x245ba7, 0xbca920, 0xb019c6, 0x58e28f, - 0xac1f74, 0x080007, 0xe425e7, 0x28cfe9, 0x9060f1, 0x741bb2, 0x28ed6a, - 0x34ab37, 0x60a37d, 0x0056cd, 0x7081eb, 0x086698, 0x24f677, 0x7867d7, - 0x5433cb, 0xd0d2b0, 0xd88f76, 0x3c2ef9, 0xdc56e7, 0x347c25, 0xd4909c, - 0x041e64, 0x0026b0, 0x00264a, 0x0025bc, 0x0023df, 0x002241, 0x000a95, - 0x38e60a, 0x24181d, 0xf4c248, 0xa8515b, 0xc048e6, 0xd07714, 0x749eaf, - 0xb841a4, 0xf895ea, 0x50a67f, 0x647033, 0x846878}; + 0x38f23e, + 0x807abf, + 0x90e7c4, + 0x7c6193, + 0x485073, + 0x74e28c, + 0x8463d6, + 0xd48f33, + 0x2c8a72, + 0x980d2e, + 0xa826d9, + 0xd4206d, + 0x00155d, + 0x806c1b, + 0xa470d6, + 0x985fd3, + 0x1c69a5, + 0x382de8, + 0xd087e2, + 0x205531, + 0x5440ad, + 0x842e27, + 0x50f0d3, + 0x84119e, + 0x08eca9, + 0x10d38a, + 0x382dd1, + 0xe0cbee, + 0x64b853, + 0xf4428f, + 0x188331, + 0x8455a5, + 0xa87c01, + 0xc01173, + 0xbce63f, + 0xb857d8, + 0x94b10a, + 0xe458b8, + 0x088c2c, + 0xb86ce8, + 0x9c65b0, + 0xc8a823, + 0xc44202, + 0xd059e4, + 0x64b310, + 0x9476b7, + 0x8c1abf, + 0xb47443, + 0x30cbf8, + 0x182195, + 0xa88195, + 0x88add2, + 0xd0fccc, + 0x14c913, + 0x4c6641, + 0x3cbdd8, + 0x38256b, + 0x849866, + 0xe89309, + 0x0016db, + 0x5c3c27, + 0x10d542, + 0xa0821f, + 0xc45006, + 0x88329b, + 0xbc8ccd, + 0x400e85, + 0xec9bf3, + 0xf8042e, + 0x843838, + 0x54880e, + 0xbc79ad, + 0x30d6c9, + 0xb0df3a, + 0x805719, + 0x78a873, + 0x041bba, + 0x08fd0e, + 0x08d42b, + 0x00e3b2, + 0xc81479, + 0xf0728c, + 0x94350a, + 0x001fcd, + 0xd0dfc7, + 0x1c62b8, + 0x18e2c2, + 0x001a8a, + 0x002567, + 0xa8f274, + 0x001599, + 0x0012fb, + 0x7cf854, + 0x8cc8cd, + 0xe81132, + 0xa02195, + 0x8c71f8, + 0x04180f, + 0x9463d1, + 0x0cdfa4, + 0xcc051b, + 0x68ebae, + 0x60d0a9, + 0x60a10a, + 0xa07591, + 0x001fcc, + 0xec107b, + 0xa01081, + 0xf4f524, + 0x9c99a0, + 0x185936, + 0x98fae3, + 0x640980, + 0x8cbebe, + 0xf8a45f, + 0xbc8385, + 0x900628, + 0xd4ae05, + 0x3c0518, + 0xc40bcb, + 0xe8bba8, + 0xbc3aea, + 0x8c0ee3, + 0x6c5c14, + 0x78abbb, + 0x1816c9, + 0xfc8f90, + 0x244b03, + 0x988389, + 0x14bb6e, + 0x1c3ade, + 0xf83f51, + 0xd8e0e1, + 0xecf342, + 0x5092b9, + 0xb4bff6, + 0xc8d7b0, + 0x982d68, + 0xecd09f, + 0xe446da, + 0xf4f5db, + 0xd80831, + 0xdc5583, + 0x2c54cf, + 0x001fe3, + 0x0026e2, + 0x001e75, + 0x6cd68a, + 0x2021a5, + 0x0c4885, + 0xdc0b34, + 0xac0d1b, + 0x60e3ac, + 0xf895c7, + 0xc4438f, + 0xa816b2, + 0xe892a4, + 0x700514, + 0x88c9d0, + 0x2c598a, + 0x18f0e4, + 0xec8350, + 0x4cdd31, + 0x703eac, + 0x6c94f8, + 0x84788b, + 0x2cf0ee, + 0x68d93c, + 0x24e314, + 0x28f076, + 0x285aeb, + 0x087402, + 0xccc760, + 0x705aac, + 0xfc643a, + 0xd4e6b7, + 0x2802d8, + 0x9c2ea1, + 0x68967b, + 0xbc6778, + 0xa82066, + 0xb065bd, + 0xf0dce2, + 0x7cd1c3, + 0x705681, + 0x2cbe08, + 0x783a84, + 0x84b153, + 0x6476ba, + 0x54ae27, + 0xf437b7, + 0xf0d1a9, + 0x34c059, + 0x04f7e4, + 0x10ddb1, + 0xb4f0ab, + 0x848506, + 0x7831c1, + 0x8c7c92, + 0xd0e140, + 0xacfdec, + 0xf82793, + 0x40a6d9, + 0x109add, + 0xf0b479, + 0x58b035, + 0x34159e, + 0x286aba, + 0xec852f, + 0x44d884, + 0x003ee1, + 0x7c11be, + 0x04e536, + 0x881fa1, + 0x04db56, + 0x9cfc01, + 0xc81ee7, + 0x34363b, + 0xc01ada, + 0xacbc32, + 0x70700d, + 0x7c5049, + 0x503237, + 0xd4619d, + 0xb0481a, + 0x989e63, + 0xdca904, + 0x48a195, + 0x6cab31, + 0x6c96cf, + 0x3035ad, + 0xa8be27, + 0xb8634d, + 0x9ce33f, + 0xf0989d, + 0xace4b5, + 0xe42b34, + 0x1c36bb, + 0x3c2eff, + 0xf0766f, + 0x40cbc0, + 0x4098ad, + 0x6c4d73, + 0xc48466, + 0xd02b20, + 0x3010e4, + 0x380f4a, + 0x685b35, + 0xc86f1d, + 0x701124, + 0x38484c, + 0x041552, + 0x786c1c, + 0xbc3baf, + 0x00a040, + 0x60fec5, + 0xcc4463, + 0x6c72e7, + 0x18af61, + 0x00cdfe, + 0xac61ea, + 0x38b54d, + 0x60c547, + 0x28e02c, + 0x50ead6, + 0x4860bc, + 0x403004, + 0x0c74c2, + 0xa4b197, + 0x7cf05f, + 0xa4f1e8, + 0x70a2b3, + 0x4c57ca, + 0x68fb7e, + 0x90c1c6, + 0x9cf48e, + 0xfcd848, + 0x64b9e8, + 0x001cb3, + 0x000d93, + 0x30d9d9, + 0x6030d4, + 0x94bf2d, + 0xc49880, + 0xe0338e, + 0x68fef7, + 0xbce143, + 0x645aed, + 0xc0b658, + 0x881908, + 0xfc2a9c, + 0x48605f, + 0x188796, + 0x002376, + 0x84100d, + 0x04c23e, + 0x5c5188, + 0xe89120, + 0x9c6c15, + 0x4886e8, + 0x2c2997, + 0x102f6b, + 0x00eebd, + 0x281878, + 0x6045bd, + 0x7ced8d, + 0xe85b5b, + 0x000d3a, + 0xe09861, + 0xf4f1e1, + 0x60beb5, + 0xb4e1c4, + 0x70aab2, + 0x0026ff, + 0x406f2a, + 0x002557, + 0xf05a09, + 0x503275, + 0x28cc01, + 0xb46293, + 0x04fe31, + 0x845181, + 0xd831cf, + 0xf8d0bd, + 0xfcc734, + 0xe4b021, + 0xb0ec71, + 0x3cbbfd, + 0x2cae2b, + 0xc488e5, + 0x7c9122, + 0xe8b4c8, + 0x18895b, + 0xe0db10, + 0xe09971, + 0x6077e2, + 0x680571, + 0x6c2f2c, + 0x300d43, + 0x6c2779, + 0x607edd, + 0x9c2a83, + 0xe45d75, + 0xe4faed, + 0xc83f26, + 0x54f201, + 0xa06090, + 0xac3743, + 0x141f78, + 0x006f64, + 0xdc6672, + 0x001e7d, + 0x3c6200, + 0x0024e9, + 0x002399, + 0xe4e0c5, + 0xe8039a, + 0xc4731e, + 0x8c7712, + 0x2013e0, + 0x0007ab, + 0x0021d2, + 0xbc4760, + 0xd0176a, + 0x2cbaba, + 0x24920e, + 0x40d3ae, + 0xf01dbc, + 0x24dbed, + 0xac3613, + 0x1449e0, + 0xc0bdd1, + 0xe8508b, + 0xf025b7, + 0xc8ba94, + 0xec1f72, + 0x9852b1, + 0x1489fd, + 0xccfe3c, + 0x789ed0, + 0xe440e2, + 0x1caf05, + 0xe492fb, + 0x0073e0, + 0xbc4486, + 0x380b40, + 0x002490, + 0x0023d7, + 0xfca13e, + 0xa00798, + 0x945103, + 0xc819f7, + 0x2c4401, + 0x28e31f, + 0x0c1daf, + 0x14f65a, + 0x742344, + 0xf0b429, + 0xec51bc, + 0xf079e8, + 0x887598, + 0xd0b128, + 0xd00401, + 0xf06d78, + 0x10683f, + 0x74a722, + 0x58a2b5, + 0x64899a, + 0x88074b, + 0x64bc0c, + 0xa039f7, + 0x041b6d, + 0x001f6b, + 0x30b4b8, + 0x503cea, + 0x0c9838, + 0x54fcf0, + 0x08aed6, + 0xa816d0, + 0x88bd45, + 0x544e90, + 0xd03311, + 0x70e72c, + 0xc0cecd, + 0x98e0d9, + 0xe0accb, + 0x78d75f, + 0x2078f0, + 0x985aeb, + 0xa45e60, + 0x006d52, + 0x5cadcf, + 0xb8e856, + 0x90b21f, + 0xa8bbcf, + 0xc8b5b7, + 0x18af8f, + 0xf4f951, + 0xf0c1f1, + 0xec3586, + 0x88cb87, + 0xac3c0b, + 0xcc785f, + 0xe88d28, + 0x3ce072, + 0xf41ba1, + 0xa85b78, + 0x9cf387, + 0x34a395, + 0x48437c, + 0xac87a3, + 0x00f76f, + 0xc0f2fb, + 0x1caba7, + 0x60facd, + 0x680927, + 0x78a3e4, + 0x68a86d, + 0xb817c2, + 0xb88d12, + 0x5c8d4e, + 0xe06678, + 0x1c1ac0, + 0xc8f650, + 0x60d9c7, + 0x44fb42, + 0x64a3cb, + 0xd8d1cb, + 0x542696, + 0x14109f, + 0xbc52b7, + 0xe0c97a, + 0x5c95ae, + 0x8cfaba, + 0x0cbc9f, + 0xbc4cc4, + 0x0c1539, + 0x908d6c, + 0x80006e, + 0xb418d1, + 0x1499e2, + 0xe0c767, + 0xa860b6, + 0x24f094, + 0x90b0ed, + 0xc4b301, + 0xe05f45, + 0x483b38, + 0x88e87f, + 0xb853ac, + 0x2c3361, + 0x784f43, + 0x404d7f, + 0xbc926b, + 0x0452f3, + 0x241eeb, + 0xf431c3, + 0x64a5c3, + 0x606944, + 0xe498d6, + 0x0cd746, + 0x440010, + 0x1c9e46, + 0x7c04d0, + 0xbc9fef, + 0x8866a5, + 0x70f087, + 0x886b6e, + 0x4c74bf, + 0x844167, + 0xb4f61c, + 0xe49adc, + 0xb8c111, + 0x3408bc, + 0xd0817a, + 0xc4618b, + 0x68ab1e, + 0x2c61f6, + 0x0026bb, + 0x00254b, + 0x002436, + 0x002332, + 0x002312, + 0x0019e3, + 0x001451, + 0x000a27, + 0x003065, + 0x0050e4, + 0xd023db, + 0xe0b9ba, + 0x3451c9, + 0x8c5877, + 0x9803d8, + 0xc82a14, + 0x88c663, + 0x8c7b9d, + 0x5855ca, + 0xcc08e0, + 0xe80688, + 0x641cb0, + 0x3cdcbc, + 0xf47190, + 0x587a6a, + 0xe4c483, + 0x8cf5a3, + 0x14568e, + 0x8058f8, + 0xf0d7aa, + 0xc49ded, + 0xb0aa36, + 0x2c5bb8, + 0x1c48ce, + 0x24f5aa, + 0xf877b8, + 0x682737, + 0x5056bf, + 0x9097f3, + 0x58c5cb, + 0xacafb9, + 0x30074d, + 0x5c5181, + 0x389af6, + 0xe0aa96, + 0x507705, + 0x2c4053, + 0x084acf, + 0x1cddea, + 0x08152f, + 0xd461da, + 0xc8d083, + 0x88e9fe, + 0x88ae07, + 0x5c0947, + 0x38892c, + 0x40831d, + 0x50bc96, + 0x9ce65e, + 0x90dd5d, + 0x08f69c, + 0x00092d, + 0xf8db7f, + 0xe899c4, + 0x24da9b, + 0x1c56fe, + 0xe4907e, + 0x80c5e6, + 0x800184, + 0xf8cfc5, + 0xc808e9, + 0x206274, + 0x30d587, + 0xc0eefb, + 0x502e5c, + 0x847a88, + 0x0025ae, + 0x002538, + 0x0022a1, + 0x00125a, + 0x9cd917, + 0x9068c3, + 0x408805, + 0xf8f1b6, + 0x001ccc, + 0x94ebcd, + 0xa4e4b8, + 0x389496, + 0x0cb319, + 0x08ee8b, + 0xa89fba, + 0xfc1910, + 0x083d88, + 0x5c2e59, + 0x646cb2, + 0xf884f2, + 0x14b484, + 0x608f5c, + 0x4cbca5, + 0x78595e, + 0xb0d09c, + 0x4ca56d, + 0xa48431, + 0xe4f8ef, + 0x1432d1, + 0xe458e7, + 0x8cbfa6, + 0x7840e4, + 0x9000db, + 0x183a2d, + 0x08373d, + 0x50f520, + 0xa4ebd3, + 0x28987b, + 0xf40e22, + 0x9c3aaf, + 0x0821ef, + 0xa0cbfd, + 0x34145f, + 0x6c8fb5, + 0xac5f3e, + 0x509ea7, + 0xdccf96, + 0x6c2483, + 0xc09727, + 0xd85b2a, + 0xacc33a, + 0x88797e, + 0x00e091, + 0x6cd032, + 0xc041f6, + 0x0017d5, + 0x001247, + 0xe4121d, + 0x684898, + 0xf409d8, + 0xb479a7, + 0x002339, + 0xd487d8, + 0x184617, + 0x5001bb, + 0x380a94, + 0xd857ef, + 0x1c66aa, + 0x58c38b, + 0x001ee2, + 0x001c43, + 0x001d25, + 0x3c5a37, + 0x549b12, + 0x3c8bfe, + 0x00265d, + 0xd4e8b2, + 0x0808c2, + 0xb0c4e7, + 0xd890e8, + 0x34aa8b, + 0x24c696, + 0x181eb0, + 0x20d390, + 0x343111, + 0x34be00, + 0x78521a, + 0x7825ad, + 0xf4d9fb, + 0x0017c9, + 0x00166b, + 0x00166c, + 0xe47cf9, + 0x002454, + 0x20d5bf, + 0x30cda7, + 0xc87e75, + 0x00233a, + 0x60a4d0, + 0x2c0e3d, + 0xd4970b, + 0x64cc2e, + 0xb0e235, + 0x38a4ed, + 0xf48b32, + 0x7c787e, + 0xc0d3c0, + 0x440444, + 0xc09f05, + 0xcc2d83, + 0x38295a, + 0x4c1a3d, + 0xa81b5a, + 0xdc6dcd, + 0x54fa3e, + 0x0c8910, + 0xfcf136, + 0x981dfa, + 0x84a466, + 0x1867b0, + 0xccb11a, + 0xb8bbaf, + 0x60c5ad, + 0x28395e, + 0xc4ae12, + 0xdc74a8, + 0xc087eb, + 0x74f61c, + 0x986f60, + 0x4c189a, + 0x3cf591, + 0x602101, + 0xa89675, + 0x608e08, + 0x7c2edd, + 0x3cf7a4, + 0x342d0d, + 0x94d029, + 0x308454, + 0x4c49e3, + 0x087808, + 0xd03169, + 0xbc5451, + 0x00bf61, + 0xf80cf3, + 0x30766f, + 0x8c3ae3, + 0x78f882, + 0xb4f1da, + 0x0021fb, + 0xd013fd, + 0xa8b86e, + 0x04b167, + 0xd86375, + 0xdcbfe9, + 0x306a85, + 0x2047da, + 0x8035c1, + 0xd02598, + 0xa8667f, + 0x7014a6, + 0x10417f, + 0xac293a, + 0x94e96a, + 0x0c4de9, + 0x907240, + 0xa88808, + 0xc8e0eb, + 0x54e43a, + 0x28e14c, + 0x848e0c, + 0xb03495, + 0xf0f61c, + 0x0c3021, + 0xd89695, + 0x649abe, + 0x5cf5da, + 0x20a2e4, + 0xf02475, + 0x24a074, + 0x8863df, + 0x609217, + 0x34e2fd, + 0x0c3e9f, + 0x6c709f, + 0x6c4008, + 0x5c97f3, + 0x90fd61, + 0x006171, + 0x80e650, + 0xdc2b2a, + 0xb844d9, + 0xe0f5c6, + 0x949426, + 0xcc29f5, + 0x58404e, + 0xdc0c5c, + 0x2c200b, + 0xdca4ca, + 0x8c8fe9, + 0x9810e8, + 0xb49cdf, + 0xa4e975, + 0xc0a53e, + 0x9800c6, + 0x787b8a, + 0x3866f0, + 0x20ee28, + 0x08f4ab, + 0x8c8590, + 0xb48b19, + 0xe49a79, + 0x28a02b, + 0xb44bd2, + 0x2cf0a2, + 0xecadb8, + 0x9801a7, + 0x609ac1, + 0xf07960, + 0x9c8ba0, + 0x4c3275, + 0xe4e4ab, + 0xc8334b, + 0x00f4b9, + 0x0c771a, + 0x74e1b6, + 0x64200c, + 0xc0847a, + 0x183451, + 0xfc253f, + 0x1040f3, + 0x6cc26b, + 0x182032, + 0x70dee2, + 0x00c610, + 0x101c0c, + 0x7cfadf, + 0x5cf938, + 0x3871de, + 0xbc5436, + 0x9c4fda, + 0x1c5cf2, + 0x60fb42, + 0x002500, + 0x00236c, + 0x0021e9, + 0x001ff3, + 0x001f5b, + 0x001e52, + 0x001d4f, + 0x001124, + 0xa8fad8, + 0x5c969d, + 0xe48b7f, + 0x84fcfe, + 0x444c0c, + 0x8c2daa, + 0x6c3e6d, + 0x189efc, + 0xc09f42, + 0xb8f6b1, + 0x406c8f, + 0xa4d1d2, + 0x040cce, + 0xd89e3f, + 0x28e7cf, + 0xc8bcc8, + 0xd8a25e, + 0x90840d, + 0xf81edf, + 0xb0ca68, + 0x98ca33, + 0x68ef43, + 0xcc2db7, + 0xd4a33d, + 0xe4e0a6, + 0x70ef00, + 0x80ad16, + 0x641cae, + 0x14205e, + 0x5c1dd9, + 0x18f1d8, + 0xf86fc1, + 0xf099b6, + 0xdcd3a2, + 0x38e7d8, + 0xd8b377, + 0xb4cef6, + 0xd40b1a, + 0x5882a8, + 0xb4ae2b, + 0x0c413e, + 0xd0929e, + 0x4480eb, + 0xb84fd5, + 0xec59e7, + 0x3059b7, + 0x501ac5, + 0x1cb094, + 0xa0f450, + 0x002248, + 0xec8892, + 0xb07994, + 0x141aa3, + 0xccc3ea, + 0x34bb26, + 0x40786a, + 0xf40b93, + 0x68ed43, + 0x34bb1f, + 0x489d24, + 0x000f86, + 0xacee9e, + 0xc08997, + 0x2827bf, + 0xf05b7b, + 0x7cf90e, + 0xac5a14, + 0xb0c559, + 0xbcd11f, + 0xa0b4a5, + 0x80656d, + 0x48137e, + 0xe83a12, + 0x9c0298, + 0x6c8336, + 0xb8c68e, + 0x74458a, + 0xa49a58, + 0xb4ef39, + 0x14a364, + 0x3ca10d, + 0x206e9c, + 0x183f47, + 0x0c715d, + 0x0c1420, + 0xa80600, + 0x6cf373, + 0x78c3e9, + 0xc83870, + 0x288335, + 0x44783e, + 0x202d07, + 0x98398e, + 0x348a7b, + 0xbc765e, + 0x78009e, + 0x68c44d, + 0xf8e61a, + 0x888322, + 0x84b541, + 0x0015b9, + 0x001df6, + 0xece09b, + 0x606bbd, + 0x0000f0, + 0x4844f7, + 0x1c5a3e, + 0xf47b5e, + 0x008701, + 0xfc4203, + 0x1c232c, + 0xcc61e5, + 0x404e36, + 0x009ec8, + 0xacf7f3, + 0x102ab3, + 0x584498, + 0xa086c6, + 0x7c1dd9, + 0x9893cc, + 0x3ccd93, + 0xf06bca, + 0x3423ba, + 0xd022be, + 0xd02544, + 0xbc20a4, + 0x14f42a, + 0xbc851f, + 0xb85e7b, + 0xc462ea, + 0x0023d6, + 0x002491, + 0x001b98, + 0x44f459, + 0x34c3ac, + 0x94d771, + 0x4c3c16, + 0x9401c2, + 0xb43a28, + 0xd0c1b1, + 0xf008f1, + 0x78471d, + 0x3816d1, + 0xd48890, + 0x002566, + 0x00265f, + 0xacc1ee, + 0x5cba37, + 0x7802f8, + 0x3096fb, + 0xf0ee10, + 0xa43d78, + 0xec01ee, + 0xb83765, + 0xc4576e, + 0x90f1aa, + 0x78bdbc, + 0xd47ae2, + 0x84c0ef, + 0x7c1c68, + 0xd463c6, + 0x508f4c, + 0x7c6456, + 0x448f17, + 0x04d6aa, + 0x9ce063, + 0xf06e0b, + 0x5c865c, + 0xf0b0e7, + 0x209bcd, + 0xcc20e8, + 0x04d13a, + 0x0cf346, + 0x003de8, + 0x485929, + 0x34fcef, + 0x002483, + 0x001c62, + 0x583f54, + 0x40b0fa, + 0xa8922c, + 0x98d6f7, + 0x505527, + 0x0034da, + 0xa09169, + 0x88365f, + 0x9c8c6e, + 0xbcffeb, + 0x685acf, + 0x48746e, + 0x54724f, + 0x04f13e, + 0x600308, + 0x80ea96, + 0x24a2e1, + 0x90b931, + 0x280b5c, + 0xa8968a, + 0x9c04eb, + 0x885395, + 0x80929f, + 0x98b8e3, + 0xd8004d, + 0x98fe94, + 0x68644b, + 0xf099bf, + 0xfce998, + 0x48e9f1, + 0x4c7c5f, + 0x60f81d, + 0x689c70, + 0x2cb43a, + 0x042665, + 0xf4f15a, + 0x207d74, + 0x4c8d79, + 0xfcfc48, + 0x38c986, + 0x70ece4, + 0xd81d72, + 0x94f6a3, + 0x78fd94, + 0x48d705, + 0x7c6df8, + 0x3cab8e, + 0x787e61, + 0xd4f46f, + 0xc88550, + 0xac7f3e, + 0xa4c361, + 0x087045, + 0x40331a, + 0xdc3714, + 0x789f70, + 0x64b0a6, + 0x84fcac, + 0x6c19c0, + 0x20ab37, + 0xc0d012, + 0xd4dccd, + 0x484baa, + 0xf80377, + 0x14bd61, + 0x78886d, + 0xa85c2c, + 0x00db70, + 0xbcec5d, + 0xdc415f, + 0x30636b, + 0x0c5101, + 0x086d41, + 0x04d3cf, + 0x203cae, + 0x748d08, + 0xa03be3, + 0x186590, + 0x0010fa, + 0x000502, + 0xb8782e, + 0xa4d18c, + 0xcc25ef, + 0x68dbca, + 0x044bed, + 0x6c8dc1, + 0x38cada, + 0xf45c89, + 0x581faa, + 0x24ab81, + 0x70cd60, + 0x7cc537, + 0xc42c03, + 0xd83062, + 0x40d32d, + 0x7c6d62, + 0x286ab8, + 0x403cfc, + 0xb8c75d, + 0xe8040b, + 0xe4ce8f, + 0x3c0754, + 0xa46706, + 0x80b03d, + 0xc83c85, + 0xa04ea7, + 0x409c28, + 0x08e689, + 0x4cb199, + 0x98d6bb, + 0x3cd0f8, + 0x7cc3a1, + 0x002608, + 0x001ec2, + 0x001b63, + 0x0017f2, + 0x0016cb, + 0x000393, + 0x804971, + 0x64e682, + 0xb4f7a1, + 0x785dc8, + 0x48c796, + 0x804e70, + 0x3880df, + 0x1094bb, + 0xf01898, + 0x48a91c, + 0xa056f3, + 0x549963, + 0x28ff3c, + 0x902155, + 0x64a769, + 0xbccfcc, + 0xa4516f, + 0x3c8375, + 0x149a10, + 0x0ce725, + 0xc0335e, + 0x20a99b, + 0x4c0bbe, + 0x7c1e52, + 0xdcb4c4, + 0x001dd8, + 0x0017fa, + 0x0003ff, + 0xf8e079, + 0x1430c6, + 0xe0757d, + 0x9cd35b, + 0x60af6d, + 0xb85a73, + 0x103047, + 0x109266, + 0xb047bf, + 0x7c0bc6, + 0x804e81, + 0x244b81, + 0x50a4c8, + 0x8425db, + 0xd8c4e9, + 0x50c8e5, + 0x446d6c, + 0x38d40b, + 0x647791, + 0x781fdb, + 0x08fc88, + 0x30c7ae, + 0x18227e, + 0x00f46f, + 0x9ce6e7, + 0xe498d1, + 0x5cca1a, + 0x70288b, + 0x4849c7, + 0x205ef7, + 0x182666, + 0xc06599, + 0xcc07ab, + 0xe84e84, + 0x50fc9f, + 0xe432cb, + 0x889b39, + 0xbcb1f3, + 0x38ece4, + 0xccf9e8, + 0xf0e77e, + 0x5ce8eb, + 0xb8d9ce, + 0x70f927, + 0x301966, + 0x28bab5, + 0x103b59, + 0x6cb7f4, + 0x001ee1, + 0x0018af, + 0xbc72b1, + 0x78f7be, + 0xf49f54, + 0x00214c, + 0x001632, + 0xd0667b, + 0x001377, + 0x50b7c3, + 0x8018a7, + 0x444e1a, + 0xe8e5d6, + 0x5492be, + 0x101dc0, + 0x0021d1, + 0x68dfdd, + 0xc46ab7, + 0xfc64ba, + 0x2082c0, + 0x3480b3, + 0x7451ba, + 0x64b473, + 0xcc2d8c, + 0x949aa9, + 0x20dbab, + 0x5c9960, + 0x948bc1, + 0x4827ea, + 0x388c50, + 0xa09347, + 0xc8f230, + 0x1c77f6, + 0xe44790, + 0xd4503f, + 0x40163b, + 0x5c497d, + 0xe47dbd, + 0x503da1, + 0x508569, + 0x1077b1, + 0x5cf6dc, + 0x380195, + 0xbc1485, + 0x88d50c, + 0x947be7, + 0x00ec0a, + 0x54bd79, + 0xdc44b6, + 0x1007b6, + 0xc0174d, + 0xa407b6, + 0x149f3c, + 0x88b4a6, + 0x2c5491, + 0x5c70a3, + 0x10f96f, + 0xf01c13, + 0x00aa70, + 0xbcf5ac, + 0xccfa00, + 0xf8a9d0, + 0x805a04, + 0x5caf06, + 0xb81daa, + 0x10f1f2, + 0x0025e5, + 0x0022a9, + 0xc49a02, + 0x344df7, + 0xd41a3f, + 0xcc6ea4, + 0xa46cf1, + 0x0ca8a7, + 0x54b802, + 0x0469f8, + 0xbc6c21, + 0xc869cd, + 0x80d605, + 0x587f57, + 0xa4b805, + 0x70480f, + 0x18f643, + 0x748114, + 0x18ee69, + 0xf0dbe2, + 0xb8098a, + 0x549f13, + 0x2c1f23, + 0x507a55, + 0x9c35eb, + 0xa43135, + 0xd0034b, + 0xa01828, + 0xd0a637, + 0xd04f7e, + 0xd8bb2c, + 0x80be05, + 0xe0b52d, + 0x68ae20, + 0xe8802e, + 0x7c0191, + 0x9c293f, + 0x341298, + 0x903c92, + 0x24240e, + 0xa0999b, + 0xe0f847, + 0x442a60, + 0x1093e9, + 0xdc2b61, + 0xb8ff61, + 0x18e7f4, + 0x78ca39, + 0x5c5948, + 0x60334b, + 0x9027e4, + 0xd49a20, + 0xb09fba, + 0x8c006d, + 0xc06394, + 0x843835, + 0xe4c63d, + 0x54eaa8, + 0xa886dd, + 0xaccf5c, + 0xf0dbf8, + 0x98f0ab, + 0xdc9b9c, + 0x8c2937, + 0xdc86d8, + 0xa88e24, + 0xd8cf9c, + 0x04489a, + 0x3c15c2, + 0x20c9d0, + 0x74e2f5, + 0x842999, + 0x9c207b, + 0x283737, + 0x148fc6, + 0x28cfda, + 0x145a05, + 0xa0edcd, + 0x1ce62b, + 0x3090ab, + 0x7073cb, + 0xf0cba1, + 0x045453, + 0x40b395, + 0x008865, + 0x30f7c5, + 0x20768f, + 0xc0ccf8, + 0x80ed2c, + 0xe8b2ac, + 0x8489ad, + 0x8c8ef2, + 0xf40f24, + 0x84a134, + 0x1c9148, + 0x5cf7e6, + 0xa0d795, + 0xcc088d, + 0x00b362, + 0xf86214, + 0xb0702d, + 0xd0c5f3, + 0x60f445, + 0x5082d5, + 0x9c84bf, + 0x48bf6b, + 0x245ba7, + 0xbca920, + 0xb019c6, + 0x58e28f, + 0xac1f74, + 0x080007, + 0xe425e7, + 0x28cfe9, + 0x9060f1, + 0x741bb2, + 0x28ed6a, + 0x34ab37, + 0x60a37d, + 0x0056cd, + 0x7081eb, + 0x086698, + 0x24f677, + 0x7867d7, + 0x5433cb, + 0xd0d2b0, + 0xd88f76, + 0x3c2ef9, + 0xdc56e7, + 0x347c25, + 0xd4909c, + 0x041e64, + 0x0026b0, + 0x00264a, + 0x0025bc, + 0x0023df, + 0x002241, + 0x000a95, + 0x38e60a, + 0x24181d, + 0xf4c248, + 0xa8515b, + 0xc048e6, + 0xd07714, + 0x749eaf, + 0xb841a4, + 0xf895ea, + 0x50a67f, + 0x647033, + 0x846878 +};