# include <EEPROM.h>
# include <stddef.h>
# 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 <avr/wdt.h>
# include <util/atomic.h>
# 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 <Adafruit_NeoPixel.h>
# 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 ( ) ;
}
}
void boot_seq ( ) {
uint8_t rs [ ] = { 0x00 , 0x00 , 0x00 } ;
uint8_t gs [ ] = { 0x10 , 0x08 , 0x00 } ;
uint8_t bs [ ] = { 0x00 , 0x08 , 0x10 } ;
for ( int i = 0 ; i < 1 * sizeof ( rs ) ; i + + ) {
npset ( rs [ i % sizeof ( rs ) ] , gs [ i % sizeof ( gs ) ] , bs [ i % sizeof ( bs ) ] ) ;
delay ( 33 ) ;
npset ( 0x00 , 0x00 , 0x00 ) ;
delay ( 66 ) ;
}
}
# else
void boot_seq ( ) { }
# 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 = 55 ;
uint8_t led_standby_cut = 100 ;
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 = 350 ;
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_HASHES ) ;
serial_write ( 0x01 ) ;
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_HASHES ) ;
serial_write ( 0x02 ) ;
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_HASHES ) ;
serial_write ( 0x03 ) ;
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_HASHES ) ;
serial_write ( 0x04 ) ;
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 ) ;
}