#include #include #include "Config.h" #include "LoRa.h" #include "ROM.h" #include "Framing.h" #include "MD5.h" #if HAS_DISPLAY == true #include "Display.h" #endif #if HAS_BLUETOOTH == true #include "Bluetooth.h" #endif #if HAS_PMU == true #include "Power.h" #endif #if MCU_VARIANT == MCU_ESP32 #include "Device.h" #include "soc/rtc_wdt.h" #define ISR_VECT IRAM_ATTR #else #define ISR_VECT #endif #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 #include #include #endif uint8_t boot_vector = 0x00; #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 uint8_t OPTIBOOT_MCUSR __attribute__ ((section(".noinit"))); void resetFlagsInit(void) __attribute__ ((naked)) __attribute__ ((used)) __attribute__ ((section (".init0"))); void resetFlagsInit(void) { __asm__ __volatile__ ("sts %0, r2\n" : "=m" (OPTIBOOT_MCUSR) :); } #elif MCU_VARIANT == MCU_ESP32 // TODO: Get ESP32 boot flags #endif #if BOARD_MODEL == BOARD_RNODE_NG_20 || BOARD_RNODE_NG_21 #include #define NP_PIN 4 #define NUMPIXELS 1 #define NP_M 0.15 Adafruit_NeoPixel pixels(NUMPIXELS, NP_PIN, NEO_GRB + NEO_KHZ800); uint8_t npr = 0; uint8_t npg = 0; uint8_t npb = 0; bool pixels_started = false; void npset(uint8_t r, uint8_t g, uint8_t b) { if (pixels_started != true) { pixels.begin(); pixels_started = true; } if (r != npr || g != npg || b != npb) { npr = r; npg = g; npb = b; pixels.setPixelColor(0, pixels.Color(npr*NP_M, npg*NP_M, npb*NP_M)); pixels.show(); } } #endif #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, HIGH); } void led_tx_off() { digitalWrite(pin_led_tx, LOW); } #elif MCU_VARIANT == MCU_ESP32 #if BOARD_MODEL == BOARD_TBEAM void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, LOW); } void led_tx_off() { digitalWrite(pin_led_tx, HIGH); } #elif BOARD_MODEL == BOARD_LORA32_V2_0 #if defined(EXTERNAL_LEDS) void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, HIGH); } void led_tx_off() { digitalWrite(pin_led_tx, LOW); } #else void led_rx_on() { digitalWrite(pin_led_rx, LOW); } void led_rx_off() { digitalWrite(pin_led_rx, HIGH); } void led_tx_on() { digitalWrite(pin_led_tx, LOW); } void led_tx_off() { digitalWrite(pin_led_tx, HIGH); } #endif #elif BOARD_MODEL == BOARD_HELTEC32_V2 #if defined(EXTERNAL_LEDS) void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, HIGH); } void led_tx_off() { digitalWrite(pin_led_tx, LOW); } #else void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, HIGH); } void led_tx_off() { digitalWrite(pin_led_tx, LOW); } #endif #elif BOARD_MODEL == BOARD_LORA32_V2_1 void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, HIGH); } void led_tx_off() { digitalWrite(pin_led_tx, LOW); } #elif BOARD_MODEL == BOARD_RNODE_NG_20 void led_rx_on() { npset(0, 0, 0xFF); } void led_rx_off() { npset(0, 0, 0); } void led_tx_on() { npset(0xFF, 0x50, 0x00); } void led_tx_off() { npset(0, 0, 0); } #elif BOARD_MODEL == BOARD_RNODE_NG_21 void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, HIGH); } void led_tx_off() { digitalWrite(pin_led_tx, LOW); } #elif BOARD_MODEL == BOARD_HUZZAH32 void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, HIGH); } void led_tx_off() { digitalWrite(pin_led_tx, LOW); } #elif BOARD_MODEL == BOARD_GENERIC_ESP32 void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, HIGH); } void led_tx_off() { digitalWrite(pin_led_tx, LOW); } #endif #endif void hard_reset(void) { #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 wdt_enable(WDTO_15MS); while(true) { led_tx_on(); led_rx_off(); } #elif MCU_VARIANT == MCU_ESP32 ESP.restart(); #endif } // LED Indication: Error void led_indicate_error(int cycles) { #if BOARD_MODEL == BOARD_RNODE_NG_20 bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; while(cycles > 0) { npset(0xFF, 0x00, 0x00); delay(100); npset(0xFF, 0x50, 0x00); delay(100); if (!forever) cycles--; } npset(0,0,0); #else bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; while(cycles > 0) { digitalWrite(pin_led_rx, HIGH); digitalWrite(pin_led_tx, LOW); delay(100); digitalWrite(pin_led_rx, LOW); digitalWrite(pin_led_tx, HIGH); delay(100); if (!forever) cycles--; } led_rx_off(); led_tx_off(); #endif } // LED Indication: Boot Error void led_indicate_boot_error() { #if BOARD_MODEL == BOARD_RNODE_NG_20 while(true) { npset(0xFF, 0xFF, 0xFF); } #else while (true) { led_tx_on(); led_rx_off(); delay(10); led_rx_on(); led_tx_off(); delay(5); } #endif } // LED Indication: Warning void led_indicate_warning(int cycles) { #if BOARD_MODEL == BOARD_RNODE_NG_20 bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; while(cycles > 0) { npset(0xFF, 0x50, 0x00); delay(100); npset(0x00, 0x00, 0x00); delay(100); if (!forever) cycles--; } npset(0,0,0); #else bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; digitalWrite(pin_led_tx, HIGH); while(cycles > 0) { led_tx_off(); delay(100); led_tx_on(); delay(100); if (!forever) cycles--; } led_tx_off(); #endif } // LED Indication: Info #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 void led_indicate_info(int cycles) { bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; while(cycles > 0) { led_rx_off(); delay(100); led_rx_on(); delay(100); if (!forever) cycles--; } led_rx_off(); } #elif MCU_VARIANT == MCU_ESP32 #if BOARD_MODEL == BOARD_RNODE_NG_20 void led_indicate_info(int cycles) { bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; while(cycles > 0) { npset(0x00, 0x00, 0xFF); delay(100); npset(0x00, 0x00, 0x00); delay(100); if (!forever) cycles--; } npset(0,0,0); } #elif BOARD_MODEL == BOARD_LORA32_V2_1 void led_indicate_info(int cycles) { bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; while(cycles > 0) { led_rx_off(); delay(100); led_rx_on(); delay(100); if (!forever) cycles--; } led_rx_off(); } #elif BOARD_MODEL == BOARD_LORA32_V2_0 void led_indicate_info(int cycles) { bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; while(cycles > 0) { led_rx_off(); delay(100); led_rx_on(); delay(100); if (!forever) cycles--; } led_rx_off(); } #else void led_indicate_info(int cycles) { bool forever = (cycles == 0) ? true : false; cycles = forever ? 1 : cycles; while(cycles > 0) { led_tx_off(); delay(100); led_tx_on(); delay(100); if (!forever) cycles--; } led_tx_off(); } #endif #endif unsigned long led_standby_ticks = 0; #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 uint8_t led_standby_min = 1; uint8_t led_standby_max = 40; unsigned long led_standby_wait = 11000; #elif MCU_VARIANT == MCU_ESP32 #if BOARD_MODEL == BOARD_RNODE_NG_20 || BOARD_MODEL == BOARD_RNODE_NG_21 uint8_t led_standby_lng = 32; uint8_t led_standby_cut = 16; uint8_t led_standby_min = 0; uint8_t led_standby_max = 200+led_standby_lng; uint8_t led_notready_min = 0; uint8_t led_notready_max = led_standby_max; uint8_t led_notready_value = led_notready_min; int8_t led_notready_direction = 0; unsigned long led_notready_ticks = 0; unsigned long led_standby_wait = 1000; unsigned long led_notready_wait = 200; #else uint8_t led_standby_min = 200; uint8_t led_standby_max = 255; uint8_t led_notready_min = 0; uint8_t led_notready_max = 255; uint8_t led_notready_value = led_notready_min; int8_t led_notready_direction = 0; unsigned long led_notready_ticks = 0; unsigned long led_standby_wait = 1768; unsigned long led_notready_wait = 150; #endif #endif uint8_t led_standby_value = led_standby_min; int8_t led_standby_direction = 0; #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 void led_indicate_standby() { led_standby_ticks++; if (led_standby_ticks > led_standby_wait) { led_standby_ticks = 0; if (led_standby_value <= led_standby_min) { led_standby_direction = 1; } else if (led_standby_value >= led_standby_max) { led_standby_direction = -1; } led_standby_value += led_standby_direction; analogWrite(pin_led_rx, led_standby_value); led_tx_off(); } } #elif MCU_VARIANT == MCU_ESP32 #if BOARD_MODEL == BOARD_RNODE_NG_20 void led_indicate_standby() { led_standby_ticks++; if (led_standby_ticks > led_standby_wait) { led_standby_ticks = 0; if (led_standby_value <= led_standby_min) { led_standby_direction = 1; } else if (led_standby_value >= led_standby_max) { led_standby_direction = -1; } led_standby_value += led_standby_direction; int offset = led_standby_value - led_standby_lng; uint8_t led_standby_intensity; if (offset < 0) { led_standby_intensity = 0; } else { led_standby_intensity = offset; } if (offset > led_standby_cut) offset = led_standby_cut; npset(0x00, 0x00, led_standby_intensity); } } #else void led_indicate_standby() { led_standby_ticks++; if (led_standby_ticks > led_standby_wait) { led_standby_ticks = 0; if (led_standby_value <= led_standby_min) { led_standby_direction = 1; } else if (led_standby_value >= led_standby_max) { led_standby_direction = -1; } led_standby_value += led_standby_direction; if (led_standby_value > 253) { led_tx_on(); } else { led_tx_off(); } #if BOARD_MODEL == BOARD_LORA32_V2_1 #if defined(EXTERNAL_LEDS) led_rx_off(); #endif #elif BOARD_MODEL == BOARD_LORA32_V2_0 #if defined(EXTERNAL_LEDS) led_rx_off(); #endif #else led_rx_off(); #endif } } #endif #endif #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 void led_indicate_not_ready() { led_standby_ticks++; if (led_standby_ticks > led_standby_wait) { led_standby_ticks = 0; if (led_standby_value <= led_standby_min) { led_standby_direction = 1; } else if (led_standby_value >= led_standby_max) { led_standby_direction = -1; } led_standby_value += led_standby_direction; analogWrite(pin_led_tx, led_standby_value); led_rx_off(); } } #elif MCU_VARIANT == MCU_ESP32 #if BOARD_MODEL == BOARD_RNODE_NG_20 || BOARD_MODEL == BOARD_RNODE_NG_21 void led_indicate_not_ready() { led_standby_ticks++; if (led_standby_ticks > led_notready_wait) { led_standby_ticks = 0; if (led_standby_value <= led_standby_min) { led_standby_direction = 1; } else if (led_standby_value >= led_standby_max) { led_standby_direction = -1; } led_standby_value += led_standby_direction; int offset = led_standby_value - led_standby_lng; uint8_t led_standby_intensity; if (offset < 0) { led_standby_intensity = 0; } else { led_standby_intensity = offset; } if (offset > led_standby_cut) offset = led_standby_cut; npset(led_standby_intensity, 0x00, 0x00); } } #else void led_indicate_not_ready() { led_notready_ticks++; if (led_notready_ticks > led_notready_wait) { led_notready_ticks = 0; if (led_notready_value <= led_notready_min) { led_notready_direction = 1; } else if (led_notready_value >= led_notready_max) { led_notready_direction = -1; } led_notready_value += led_notready_direction; if (led_notready_value > 128) { led_tx_on(); } else { led_tx_off(); } #if BOARD_MODEL == BOARD_LORA32_V2_1 #if defined(EXTERNAL_LEDS) led_rx_off(); #endif #elif BOARD_MODEL == BOARD_LORA32_V2_0 #if defined(EXTERNAL_LEDS) led_rx_off(); #endif #else led_rx_off(); #endif } } #endif #endif void serial_write(uint8_t byte) { #if HAS_BLUETOOTH if (bt_state != BT_STATE_CONNECTED) { Serial.write(byte); } else { SerialBT.write(byte); } #else Serial.write(byte); #endif } void escaped_serial_write(uint8_t byte) { if (byte == FEND) { serial_write(FESC); byte = TFEND; } if (byte == FESC) { serial_write(FESC); byte = TFESC; } serial_write(byte); } void kiss_indicate_reset() { serial_write(FEND); serial_write(CMD_RESET); serial_write(CMD_RESET_BYTE); serial_write(FEND); } void kiss_indicate_error(uint8_t error_code) { serial_write(FEND); serial_write(CMD_ERROR); serial_write(error_code); serial_write(FEND); } void kiss_indicate_radiostate() { serial_write(FEND); serial_write(CMD_RADIO_STATE); serial_write(radio_online); serial_write(FEND); } void kiss_indicate_stat_rx() { serial_write(FEND); serial_write(CMD_STAT_RX); escaped_serial_write(stat_rx>>24); escaped_serial_write(stat_rx>>16); escaped_serial_write(stat_rx>>8); escaped_serial_write(stat_rx); serial_write(FEND); } void kiss_indicate_stat_tx() { serial_write(FEND); serial_write(CMD_STAT_TX); escaped_serial_write(stat_tx>>24); escaped_serial_write(stat_tx>>16); escaped_serial_write(stat_tx>>8); escaped_serial_write(stat_tx); serial_write(FEND); } void kiss_indicate_stat_rssi() { uint8_t packet_rssi_val = (uint8_t)(last_rssi+rssi_offset); serial_write(FEND); serial_write(CMD_STAT_RSSI); escaped_serial_write(packet_rssi_val); serial_write(FEND); } void kiss_indicate_stat_snr() { serial_write(FEND); serial_write(CMD_STAT_SNR); escaped_serial_write(last_snr_raw); serial_write(FEND); } void kiss_indicate_radio_lock() { serial_write(FEND); serial_write(CMD_RADIO_LOCK); serial_write(radio_locked); serial_write(FEND); } void kiss_indicate_spreadingfactor() { serial_write(FEND); serial_write(CMD_SF); serial_write((uint8_t)lora_sf); serial_write(FEND); } void kiss_indicate_codingrate() { serial_write(FEND); serial_write(CMD_CR); serial_write((uint8_t)lora_cr); serial_write(FEND); } void kiss_indicate_implicit_length() { serial_write(FEND); serial_write(CMD_IMPLICIT); serial_write(implicit_l); serial_write(FEND); } void kiss_indicate_txpower() { serial_write(FEND); serial_write(CMD_TXPOWER); serial_write((uint8_t)lora_txp); serial_write(FEND); } void kiss_indicate_bandwidth() { serial_write(FEND); serial_write(CMD_BANDWIDTH); escaped_serial_write(lora_bw>>24); escaped_serial_write(lora_bw>>16); escaped_serial_write(lora_bw>>8); escaped_serial_write(lora_bw); serial_write(FEND); } void kiss_indicate_frequency() { serial_write(FEND); serial_write(CMD_FREQUENCY); escaped_serial_write(lora_freq>>24); escaped_serial_write(lora_freq>>16); escaped_serial_write(lora_freq>>8); escaped_serial_write(lora_freq); serial_write(FEND); } void kiss_indicate_random(uint8_t byte) { serial_write(FEND); serial_write(CMD_RANDOM); serial_write(byte); serial_write(FEND); } void kiss_indicate_fbstate() { serial_write(FEND); serial_write(CMD_FB_EXT); #if HAS_DISPLAY if (disp_ext_fb) { serial_write(0x01); } else { serial_write(0x00); } #else serial_write(0xFF); #endif serial_write(FEND); } #if MCU_VARIANT == MCU_ESP32 void kiss_indicate_device_hash() { serial_write(FEND); serial_write(CMD_DEV_HASH); for (int i = 0; i < DEV_HASH_LEN; i++) { uint8_t byte = dev_hash[i]; escaped_serial_write(byte); } serial_write(FEND); } void kiss_indicate_target_fw_hash() { serial_write(FEND); serial_write(CMD_DEV_HASH); for (int i = 0; i < DEV_HASH_LEN; i++) { uint8_t byte = dev_firmware_hash_target[i]; escaped_serial_write(byte); } serial_write(FEND); } void kiss_indicate_fw_hash() { serial_write(FEND); serial_write(CMD_DEV_HASH); for (int i = 0; i < DEV_HASH_LEN; i++) { uint8_t byte = dev_firmware_hash[i]; escaped_serial_write(byte); } serial_write(FEND); } void kiss_indicate_bootloader_hash() { serial_write(FEND); serial_write(CMD_DEV_HASH); for (int i = 0; i < DEV_HASH_LEN; i++) { uint8_t byte = dev_bootloader_hash[i]; escaped_serial_write(byte); } serial_write(FEND); } void kiss_indicate_partition_table_hash() { serial_write(FEND); serial_write(CMD_DEV_HASH); for (int i = 0; i < DEV_HASH_LEN; i++) { uint8_t byte = dev_partition_table_hash[i]; escaped_serial_write(byte); } serial_write(FEND); } #endif void kiss_indicate_fb() { serial_write(FEND); serial_write(CMD_FB_READ); #if HAS_DISPLAY for (int i = 0; i < 512; i++) { uint8_t byte = fb[i]; escaped_serial_write(byte); } #else serial_write(0xFF); #endif serial_write(FEND); } void kiss_indicate_ready() { serial_write(FEND); serial_write(CMD_READY); serial_write(0x01); serial_write(FEND); } void kiss_indicate_not_ready() { serial_write(FEND); serial_write(CMD_READY); serial_write(0x00); serial_write(FEND); } void kiss_indicate_promisc() { serial_write(FEND); serial_write(CMD_PROMISC); if (promisc) { serial_write(0x01); } else { serial_write(0x00); } serial_write(FEND); } void kiss_indicate_detect() { serial_write(FEND); serial_write(CMD_DETECT); serial_write(DETECT_RESP); serial_write(FEND); } void kiss_indicate_version() { serial_write(FEND); serial_write(CMD_FW_VERSION); serial_write(MAJ_VERS); serial_write(MIN_VERS); serial_write(FEND); } void kiss_indicate_platform() { serial_write(FEND); serial_write(CMD_PLATFORM); serial_write(PLATFORM); serial_write(FEND); } void kiss_indicate_board() { serial_write(FEND); serial_write(CMD_BOARD); serial_write(BOARD_MODEL); serial_write(FEND); } void kiss_indicate_mcu() { serial_write(FEND); serial_write(CMD_MCU); serial_write(MCU_VARIANT); serial_write(FEND); } inline bool isSplitPacket(uint8_t header) { return (header & FLAG_SPLIT); } inline uint8_t packetSequence(uint8_t header) { return header >> 4; } void setSpreadingFactor() { if (radio_online) LoRa.setSpreadingFactor(lora_sf); } void setCodingRate() { if (radio_online) LoRa.setCodingRate4(lora_cr); } void set_implicit_length(uint8_t len) { implicit_l = len; if (implicit_l != 0) { implicit = true; } else { implicit = false; } } void setTXPower() { if (radio_online) { if (model == MODEL_A2) LoRa.setTxPower(lora_txp, PA_OUTPUT_RFO_PIN); if (model == MODEL_A3) LoRa.setTxPower(lora_txp, PA_OUTPUT_RFO_PIN); if (model == MODEL_A4) LoRa.setTxPower(lora_txp, PA_OUTPUT_RFO_PIN); if (model == MODEL_A7) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_A8) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_A9) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_B3) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_B4) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_B8) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_B9) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_C4) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_C9) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_E4) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_E9) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_FE) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); if (model == MODEL_FF) LoRa.setTxPower(lora_txp, PA_OUTPUT_RFO_PIN); } } void getBandwidth() { if (radio_online) { lora_bw = LoRa.getSignalBandwidth(); } } void setBandwidth() { if (radio_online) { LoRa.setSignalBandwidth(lora_bw); getBandwidth(); } } void getFrequency() { if (radio_online) { lora_freq = LoRa.getFrequency(); } } void setFrequency() { if (radio_online) { LoRa.setFrequency(lora_freq); getFrequency(); } } uint8_t getRandom() { if (radio_online) { return LoRa.random(); } else { return 0x00; } } void promisc_enable() { promisc = true; } void promisc_disable() { promisc = false; } bool eeprom_info_locked() { uint8_t lock_byte = EEPROM.read(eeprom_addr(ADDR_INFO_LOCK)); if (lock_byte == INFO_LOCK_BYTE) { return true; } else { return false; } } void eeprom_dump_info() { for (int addr = ADDR_PRODUCT; addr <= ADDR_INFO_LOCK; addr++) { uint8_t byte = EEPROM.read(eeprom_addr(addr)); escaped_serial_write(byte); } } void eeprom_dump_config() { for (int addr = ADDR_CONF_SF; addr <= ADDR_CONF_OK; addr++) { uint8_t byte = EEPROM.read(eeprom_addr(addr)); escaped_serial_write(byte); } } void eeprom_dump_all() { for (int addr = 0; addr < EEPROM_RESERVED; addr++) { uint8_t byte = EEPROM.read(eeprom_addr(addr)); escaped_serial_write(byte); } } void kiss_dump_eeprom() { serial_write(FEND); serial_write(CMD_ROM_READ); eeprom_dump_all(); serial_write(FEND); } void eeprom_update(int mapped_addr, uint8_t byte) { #if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560 EEPROM.update(mapped_addr, byte); #elif MCU_VARIANT == MCU_ESP32 if (EEPROM.read(mapped_addr) != byte) { EEPROM.write(mapped_addr, byte); EEPROM.commit(); } #endif } void eeprom_write(uint8_t addr, uint8_t byte) { if (!eeprom_info_locked() && addr >= 0 && addr < EEPROM_RESERVED) { eeprom_update(eeprom_addr(addr), byte); } else { kiss_indicate_error(ERROR_EEPROM_LOCKED); } } void eeprom_erase() { for (int addr = 0; addr < EEPROM_RESERVED; addr++) { eeprom_update(eeprom_addr(addr), 0xFF); } hard_reset(); } bool eeprom_lock_set() { if (EEPROM.read(eeprom_addr(ADDR_INFO_LOCK)) == INFO_LOCK_BYTE) { return true; } else { return false; } } bool eeprom_product_valid() { uint8_t rval = EEPROM.read(eeprom_addr(ADDR_PRODUCT)); #if PLATFORM == PLATFORM_AVR if (rval == PRODUCT_RNODE || rval == PRODUCT_HMBRW) { #elif PLATFORM == PLATFORM_ESP32 if (rval == PRODUCT_RNODE || rval == BOARD_RNODE_NG_20 || rval == BOARD_RNODE_NG_21 || rval == PRODUCT_HMBRW || rval == PRODUCT_TBEAM || rval == PRODUCT_T32_20 || rval == PRODUCT_T32_21 || rval == PRODUCT_H32_V2) { #else if (false) { #endif return true; } else { return false; } } bool eeprom_model_valid() { model = EEPROM.read(eeprom_addr(ADDR_MODEL)); #if BOARD_MODEL == BOARD_RNODE if (model == MODEL_A4 || model == MODEL_A9 || model == MODEL_FF || model == MODEL_FE) { #elif BOARD_MODEL == BOARD_RNODE_NG_20 if (model == MODEL_A3 || model == MODEL_A8) { #elif BOARD_MODEL == BOARD_RNODE_NG_21 if (model == MODEL_A2 || model == MODEL_A7) { #elif BOARD_MODEL == BOARD_HMBRW if (model == MODEL_FF || model == MODEL_FE) { #elif BOARD_MODEL == BOARD_TBEAM if (model == MODEL_E4 || model == MODEL_E9) { #elif BOARD_MODEL == BOARD_LORA32_V2_0 if (model == MODEL_B3 || model == MODEL_B8) { #elif BOARD_MODEL == BOARD_LORA32_V2_1 if (model == MODEL_B4 || model == MODEL_B9) { #elif BOARD_MODEL == BOARD_HELTEC32_V2 if (model == MODEL_C4 || model == MODEL_C9) { #elif BOARD_MODEL == BOARD_HUZZAH32 if (model == MODEL_FF) { #elif BOARD_MODEL == BOARD_GENERIC_ESP32 if (model == MODEL_FF || model == MODEL_FE) { #else if (false) { #endif return true; } else { return false; } } bool eeprom_hwrev_valid() { hwrev = EEPROM.read(eeprom_addr(ADDR_HW_REV)); if (hwrev != 0x00 && hwrev != 0xFF) { return true; } else { return false; } } bool eeprom_checksum_valid() { char *data = (char*)malloc(CHECKSUMMED_SIZE); for (uint8_t i = 0; i < CHECKSUMMED_SIZE; i++) { char byte = EEPROM.read(eeprom_addr(i)); data[i] = byte; } unsigned char *hash = MD5::make_hash(data, CHECKSUMMED_SIZE); bool checksum_valid = true; for (uint8_t i = 0; i < 16; i++) { uint8_t stored_chk_byte = EEPROM.read(eeprom_addr(ADDR_CHKSUM+i)); uint8_t calced_chk_byte = (uint8_t)hash[i]; if (stored_chk_byte != calced_chk_byte) { checksum_valid = false; } } free(hash); free(data); return checksum_valid; } void bt_conf_save(bool is_enabled) { if (is_enabled) { eeprom_update(eeprom_addr(ADDR_CONF_BT), BT_ENABLE_BYTE); } else { eeprom_update(eeprom_addr(ADDR_CONF_BT), 0x00); } } bool eeprom_have_conf() { if (EEPROM.read(eeprom_addr(ADDR_CONF_OK)) == CONF_OK_BYTE) { return true; } else { return false; } } void eeprom_conf_load() { if (eeprom_have_conf()) { lora_sf = EEPROM.read(eeprom_addr(ADDR_CONF_SF)); lora_cr = EEPROM.read(eeprom_addr(ADDR_CONF_CR)); lora_txp = EEPROM.read(eeprom_addr(ADDR_CONF_TXP)); lora_freq = (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x00) << 24 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x01) << 16 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x02) << 8 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_FREQ)+0x03); lora_bw = (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x00) << 24 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x01) << 16 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x02) << 8 | (uint32_t)EEPROM.read(eeprom_addr(ADDR_CONF_BW)+0x03); } } void eeprom_conf_save() { if (hw_ready && radio_online) { eeprom_update(eeprom_addr(ADDR_CONF_SF), lora_sf); eeprom_update(eeprom_addr(ADDR_CONF_CR), lora_cr); eeprom_update(eeprom_addr(ADDR_CONF_TXP), lora_txp); eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x00, lora_bw>>24); eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x01, lora_bw>>16); eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x02, lora_bw>>8); eeprom_update(eeprom_addr(ADDR_CONF_BW)+0x03, lora_bw); eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x00, lora_freq>>24); eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x01, lora_freq>>16); eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x02, lora_freq>>8); eeprom_update(eeprom_addr(ADDR_CONF_FREQ)+0x03, lora_freq); eeprom_update(eeprom_addr(ADDR_CONF_OK), CONF_OK_BYTE); led_indicate_info(10); } else { led_indicate_warning(10); } } void eeprom_conf_delete() { eeprom_update(eeprom_addr(ADDR_CONF_OK), 0x00); } void unlock_rom() { led_indicate_error(50); eeprom_erase(); } typedef struct FIFOBuffer { unsigned char *begin; unsigned char *end; unsigned char * volatile head; unsigned char * volatile tail; } FIFOBuffer; inline bool fifo_isempty(const FIFOBuffer *f) { return f->head == f->tail; } inline bool fifo_isfull(const FIFOBuffer *f) { return ((f->head == f->begin) && (f->tail == f->end)) || (f->tail == f->head - 1); } inline void fifo_push(FIFOBuffer *f, unsigned char c) { *(f->tail) = c; if (f->tail == f->end) { f->tail = f->begin; } else { f->tail++; } } inline unsigned char fifo_pop(FIFOBuffer *f) { if(f->head == f->end) { f->head = f->begin; return *(f->end); } else { return *(f->head++); } } inline void fifo_flush(FIFOBuffer *f) { f->head = f->tail; } #if MCU_VARIANT != MCU_ESP32 static inline bool fifo_isempty_locked(const FIFOBuffer *f) { bool result; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { result = fifo_isempty(f); } return result; } static inline bool fifo_isfull_locked(const FIFOBuffer *f) { bool result; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { result = fifo_isfull(f); } return result; } static inline void fifo_push_locked(FIFOBuffer *f, unsigned char c) { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { fifo_push(f, c); } } #endif /* static inline unsigned char fifo_pop_locked(FIFOBuffer *f) { unsigned char c; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { c = fifo_pop(f); } return c; } */ inline void fifo_init(FIFOBuffer *f, unsigned char *buffer, size_t size) { f->head = f->tail = f->begin = buffer; f->end = buffer + size; } inline size_t fifo_len(FIFOBuffer *f) { return f->end - f->begin; } typedef struct FIFOBuffer16 { uint16_t *begin; uint16_t *end; uint16_t * volatile head; uint16_t * volatile tail; } FIFOBuffer16; inline bool fifo16_isempty(const FIFOBuffer16 *f) { return f->head == f->tail; } inline bool fifo16_isfull(const FIFOBuffer16 *f) { return ((f->head == f->begin) && (f->tail == f->end)) || (f->tail == f->head - 1); } inline void fifo16_push(FIFOBuffer16 *f, uint16_t c) { *(f->tail) = c; if (f->tail == f->end) { f->tail = f->begin; } else { f->tail++; } } inline uint16_t fifo16_pop(FIFOBuffer16 *f) { if(f->head == f->end) { f->head = f->begin; return *(f->end); } else { return *(f->head++); } } inline void fifo16_flush(FIFOBuffer16 *f) { f->head = f->tail; } #if MCU_VARIANT != MCU_ESP32 static inline bool fifo16_isempty_locked(const FIFOBuffer16 *f) { bool result; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { result = fifo16_isempty(f); } return result; } #endif /* static inline bool fifo16_isfull_locked(const FIFOBuffer16 *f) { bool result; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { result = fifo16_isfull(f); } return result; } static inline void fifo16_push_locked(FIFOBuffer16 *f, uint16_t c) { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { fifo16_push(f, c); } } static inline size_t fifo16_pop_locked(FIFOBuffer16 *f) { size_t c; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { c = fifo16_pop(f); } return c; } */ inline void fifo16_init(FIFOBuffer16 *f, uint16_t *buffer, uint16_t size) { f->head = f->tail = f->begin = buffer; f->end = buffer + size; } inline uint16_t fifo16_len(FIFOBuffer16 *f) { return (f->end - f->begin); }