diff --git a/lora/lora.c b/lora/lora.c index 82573b2..307a3b6 100644 --- a/lora/lora.c +++ b/lora/lora.c @@ -13,6 +13,9 @@ Standard Includes ------------------------------------------------------------------------------*/ +#include +#include + /*------------------------------------------------------------------------------ MCU Pins ------------------------------------------------------------------------------*/ @@ -28,20 +31,34 @@ #include "lora.h" #include "main.h" -// Debugging purposes -// #include "led.h" +#if defined( TESTRECEIVER ) +#include "usb_device.h" +#include "usbd_cdc_if.h" + +void serial_printlnx(unsigned char* mesg, size_t mesg_len){ + while(CDC_Transmit_FS(mesg, mesg_len)==USBD_BUSY); +} +#endif + +#if defined( STM32F103xB ) // For the LoRa testbeds +extern SPI_HandleTypeDef hspi1; +#define LORA_SPI hspi1 +#endif + + +#ifndef STM32F103xB // The LoRa testbeds don't support our LED library + #include "led.h" +#endif /*------------------------------------------------------------------------------ - Frequency calculation helper function + Global Variables ------------------------------------------------------------------------------*/ -uint32_t lora_helper_mhz_to_reg_val( uint32_t mhz_freq ) { - return ( (2^19) * mhz_freq * 10^6 )/( 32 * 10^6 ); -} +static LORA_STATUS lora_rx_done = LORA_WAITING; /*------------------------------------------------------------------------------ Helper functions for various pin functions on the LoRa modem. ------------------------------------------------------------------------------*/ -LORA_STATUS LORA_SPI_Receive( uint8_t* read_buffer_ptr ) { +static LORA_STATUS LORA_SPI_Receive( uint8_t* read_buffer_ptr ) { HAL_StatusTypeDef status; /* Takes pointer to the read buffer. and puts output there */ @@ -53,7 +70,7 @@ LORA_STATUS LORA_SPI_Receive( uint8_t* read_buffer_ptr ) { return LORA_FAIL; } -LORA_STATUS LORA_SPI_Transmit_Byte( LORA_REGISTER_ADDR reg ) { +static LORA_STATUS LORA_SPI_Transmit_Byte( LORA_REGISTER_ADDR reg ) { HAL_StatusTypeDef status; /* Takes register and data to write (1 byte) and writes that register. */ @@ -65,7 +82,7 @@ LORA_STATUS LORA_SPI_Transmit_Byte( LORA_REGISTER_ADDR reg ) { } else return LORA_FAIL; } -LORA_STATUS LORA_SPI_Transmit_Data( LORA_REGISTER_ADDR reg, uint8_t data ) { +static LORA_STATUS LORA_SPI_Transmit_Data( LORA_REGISTER_ADDR reg, uint8_t data ) { HAL_StatusTypeDef status; /* Takes register and data to write and writes that register. */ @@ -151,8 +168,58 @@ LORA_STATUS lora_set_chip_mode( LORA_CHIPMODE chip_mode ) { return LORA_FAIL; } } - +/*------------------------------------------------------------------------------ + Chip initialization function +------------------------------------------------------------------------------*/ LORA_STATUS lora_init( LORA_CONFIG *lora_config_ptr ) { + // Check legality of frequency settings + // We do this first so that nothing gets set if we're on an illegal frequency. + + // Get a version of our bandwidth for legality calculations + uint32_t bandwidth; // Calculations down in hz due to decimal bandwidths + switch( lora_config_ptr->lora_bandwidth ) { + case LORA_BANDWIDTH_7_8_KHZ: + bandwidth = 7800; + break; + case LORA_BANDWIDTH_10_4_KHZ: + bandwidth = 10400; + break; + case LORA_BANDWIDTH_15_6_KHZ: + bandwidth = 15600; + break; + case LORA_BANDWIDTH_20_8_KHZ: + bandwidth = 20800; + break; + case LORA_BANDWIDTH_31_25_KHZ: + bandwidth = 31250; + break; + case LORA_BANDWIDTH_41_7_KHZ: + bandwidth = 41700; + break; + case LORA_BANDWIDTH_62_5_KHZ: + bandwidth = 62500; + break; + case LORA_BANDWIDTH_125_KHZ: + bandwidth = 125000; + break; + case LORA_BANDWIDTH_250_KHZ: + bandwidth = 250000; + break; + case LORA_BANDWIDTH_500_KHZ: + bandwidth = 500000; + break; + default: + // Just in case, even though this is reading an enum + return LORA_FAIL; + } + + // Check legal compliance of frequency: + if( !( lora_config_ptr->lora_frequency * 1000 + ( bandwidth / 2 ) <= ISM_MAX_FREQ * 1000 && + lora_config_ptr->lora_frequency * 1000 - ( bandwidth / 2 ) >= ISM_MIN_FREQ * 1000 ) + ) { + return LORA_FAIL; + } + LORA_STATUS set_sleep_status = lora_set_chip_mode( LORA_SLEEP_MODE ); // Switch to sleep mode to enable LoRa bit (datasheeet page 102) // Get initial value of the operation mode register uint8_t operation_mode_register; @@ -181,20 +248,32 @@ LORA_STATUS lora_init( LORA_CONFIG *lora_config_ptr ) { LORA_STATUS write_status3 = lora_write_register( LORA_REG_NUM_RX_BYTES, new_config1_register ); // Determine register values for the frequency registers - uint32_t frf_reg = lora_config_ptr->lora_frequency * 524288 / 32; + uint32_t freq_mhz = lora_config_ptr->lora_frequency / 1000; // The megahertz component of our frequency. + uint32_t freq_khz = lora_config_ptr->lora_frequency - freq_mhz * 1000; // The kilohertz component of our frequency. + // The formula for converting khz to chip unit is fruqency * 524288 / ( 32 * 1000 ) + // Straight up doing that causes an integer overflow, though, so I have to do it this way. + uint32_t frf_reg = ( freq_mhz * 524288 / 32 ) + ( freq_khz * 524288 / ( 32 * 1000 ) ); uint8_t lora_freq_reg1 = ( frf_reg << 8 ) >> 24; uint8_t lora_freq_reg2 = ( frf_reg << 16 ) >> 24; uint8_t lora_freq_reg3 = ( frf_reg << 24 ) >> 24; - // Write the frequncy registers + // Write the frequency registers LORA_STATUS write_status4 = lora_write_register( LORA_REG_FREQ_MSB, lora_freq_reg1 ); LORA_STATUS write_status5 = lora_write_register( LORA_REG_FREQ_MSD, lora_freq_reg2 ); LORA_STATUS write_status6 = lora_write_register( LORA_REG_FREQ_LSB, lora_freq_reg3 ); - LORA_STATUS standby_status = lora_set_chip_mode( LORA_STANDBY_MODE ); // Switch it into standby mode, which is what's convenient. + // Determine register values for the PA Config Register + uint8_t pa_select_reg; + LORA_STATUS read_status4 = lora_read_register( LORA_REG_PA_CONFIG, &pa_select_reg ); + uint8_t new_pa_select_reg = pa_select_reg | lora_config_ptr->lora_pa_select; - if( set_sleep_status + read_status1 + read_status2 + read_status3 + write_status1 + write_status2 + write_status3 + write_status4 + write_status5 + write_status6 + standby_status == 0 ) { + // Write the PA Config Register + LORA_STATUS write_status7 = lora_write_register( LORA_REG_PA_CONFIG, new_pa_select_reg ); + + LORA_STATUS standby_status = lora_set_chip_mode( lora_config_ptr->lora_mode ); // Switch it into standby mode, which is what's convenient. + + if( set_sleep_status + read_status1 + read_status2 + read_status3 + read_status4 + write_status1 + write_status2 + write_status3 + write_status4 + write_status5 + write_status6 + write_status7 + standby_status == 0 ) { return LORA_OK; } else { return LORA_FAIL; @@ -219,14 +298,14 @@ LORA_STATUS lora_transmit(uint8_t* buffer_ptr, uint8_t buffer_len){ // Write data to LoRA FIFO uint8_t fifo_ptr_addr; - LORA_STATUS ptr_status = lora_read_register(LORA_REG_FIFO_SPI_POINTER, &fifo_ptr_addr); // Access LoRA FIFO data buffer pointer - if (ptr_status + standby_status != LORA_OK){ + LORA_STATUS tx_base_status = lora_read_register(LORA_REG_FIFO_TX_BASE_ADDR, &fifo_ptr_addr); // Access LoRA FIFO data buffer pointer + if (tx_base_status + standby_status != LORA_OK){ // Error handler // led_set_color(// led_RED); return LORA_FAIL; } - LORA_STATUS tx_base_status = lora_write_register(LORA_REG_FIFO_TX_BASE_ADDR, fifo_ptr_addr); // Set fifo data pointer to TX base address - if (tx_base_status != LORA_OK){ + LORA_STATUS ptr_status = lora_write_register(LORA_REG_FIFO_SPI_POINTER, fifo_ptr_addr); // Set fifo data pointer to TX base address + if (ptr_status != LORA_OK){ // Error handler // led_set_color(// led_RED); return LORA_FAIL; @@ -236,7 +315,7 @@ LORA_STATUS lora_transmit(uint8_t* buffer_ptr, uint8_t buffer_len){ LORA_STATUS fifo_status = lora_write_register(LORA_REG_SIGNAL_TO_NOISE, buffer_len); // Send byte to byte to the fifo buffer - LORA_STATUS sendbyte_status; + LORA_STATUS sendbyte_status = LORA_OK; for (int i = 0; i> 7; - rx_done = (irq_flag & (1<<6)) >> 6; - - if (timeout_flag){ - return LORA_TIMEOUT_FAIL; - } else if (rx_done) { - break; - } - timeout++; - } + if ( lora_rx_done == LORA_READY ){ + // Reset IRQ register. TODO: Not sure if I actually need to this; will investigate. + uint8_t reset_irq = 0; + // lora_write_register( LORA_REG_IRQ_FLAGS, reset_irq ); + + uint8_t irq_flag; - if (rx_done){ LORA_STATUS irq_status2 = lora_read_register(LORA_REG_IRQ_FLAGS, &irq_flag); - uint8_t crc_err = (irq_flag & (1<<5)) >> 5; + lora_write_register( LORA_REG_IRQ_FLAGS, irq_flag ); + uint8_t crc_err = irq_flag & 0x20 == 0x00; + // uint8_t crc_err = irq_flag & 0x20 == 0x00; if (!crc_err){ // Read received number of bytes uint8_t num_bytes; LORA_STATUS fifo2_status = lora_read_register(LORA_REG_FIFO_RX_NUM_BYTES, &num_bytes); + #if defined( TESTRECEIVER ) + char buf[255]; + int len = sprintf( buf, "Numbytes: %d\r\n", num_bytes ); + serial_printlnx( buf, len ); + #endif + // Set lora fifo pointer to the RX base current address uint8_t fifo_ptr_addr; - LORA_STATUS ptr2_status = lora_read_register(LORA_REG_FIFO_SPI_POINTER, &fifo_ptr_addr); // Access LoRA FIFO data buffer pointer - if (ptr2_status != LORA_OK){ + LORA_STATUS base_adr_status = lora_read_register(LORA_REG_FIFO_RX_BASE_CUR_ADDR, &fifo_ptr_addr); // Access LoRA FIFO data buffer pointer + if (base_adr_status != LORA_OK){ // Error handler // led_set_color(// led_RED); return LORA_FAIL; } - LORA_STATUS base_adr_status = lora_write_register(LORA_REG_FIFO_RX_BASE_CUR_ADDR, fifo_ptr_addr); // Set fifo data pointer to TX base address - if (base_adr_status != LORA_OK){ + LORA_STATUS ptr2_status = lora_write_register(LORA_REG_FIFO_SPI_POINTER, fifo_ptr_addr); // Set fifo data pointer to TX base address + if (ptr2_status != LORA_OK){ // Error handler // led_set_color(// led_RED); return LORA_FAIL; } // Begin extracting payload - LORA_STATUS pld_xtr_status; + LORA_STATUS pld_xtr_status = LORA_OK; for (int i = 0; i < num_bytes; i++){ uint8_t packet; pld_xtr_status = lora_read_register(LORA_REG_FIFO_RW, &packet); // Access LoRA FIFO data buffer pointer buffer_ptr[i] = packet; } *buffer_len_ptr = num_bytes; - if( pld_xtr_status == LORA_OK ) { + if (pld_xtr_status == LORA_OK ) { return LORA_OK; } else { return LORA_FAIL; } } return LORA_OK; + } else if( lora_rx_done == LORA_WAITING ) { + return LORA_WAITING; } return LORA_FAIL; } \ No newline at end of file diff --git a/lora/lora.h b/lora/lora.h index 4b60258..cdabf3e 100644 --- a/lora/lora.h +++ b/lora/lora.h @@ -12,23 +12,15 @@ #ifndef LORA_H #define LORA_H -/* Project includes */ - -/* Operation Mode Register Values */ -/* These are just random parts of the operation register that may or not get used -To avoid any chance they're in the final binary without being used, -they are commented out for now and will be uncommented as they're needed. - -#define LORA_LORA_MODE 0b1 -#define LORA_LORA_REGISTER_PAGE 0b0 -#define LORA_FSK_REGISTER_PAGE 0b1 -#define LORA_HIGH_FREQ_MODE 0b1 -#define LORA_LOW_FREQ_MODE 0b0 -#define LORA_OPERATION_RESERVED 0b00 -*/ +/* Standard includes */ +#include #define LORA_TIMEOUT 2000 +/* US ISM band frequencies, used in the code to prevent violating US law */ +#define ISM_MAX_FREQ 928000 +#define ISM_MIN_FREQ 902000 + typedef enum LORA_CHIPMODE { LORA_SLEEP_MODE = 0x00, LORA_STANDBY_MODE = 0x01, @@ -47,6 +39,8 @@ typedef enum LORA_STATUS { LORA_TRANSMIT_FAIL, LORA_RECEIVE_FAIL, LORA_TIMEOUT_FAIL, + LORA_READY, + LORA_WAITING } LORA_STATUS; /* Radio register addresses from datasheet (https://www.mouser.com/datasheet/2/975/1463993415RFM95_96_97_98W-1858106.pdf) @@ -136,6 +130,13 @@ typedef enum LORA_HEADER_MODE {// You can see this on 106 - what this actually m LORA_EXPLICIT_HEADER = 0b0 } LORA_HEADER_MODE; + +// PaConfig options - See datasheet pages 79 and 103 +typedef enum LORA_PA_SELECT { + LORA_RFO = 0x00, + LORA_PA_BOOST = 0x01 +} LORA_PA_SELECT; + /* LORA CONFIG SETTINGS */ typedef struct _LORA_CONFIG { LORA_CHIPMODE lora_mode; // Current LORA Chipmode @@ -143,17 +144,11 @@ typedef struct _LORA_CONFIG { LORA_BANDWIDTH lora_bandwidth; // Signal bandwith LORA_ERROR_CODING lora_ecr; // Data Error coding LORA_HEADER_MODE lora_header_mode; // LORA Header mode - uint32_t lora_frequency; // The LORA carrier frequency. This is NOT directly in megahertz. (See datasheet page 103) - // To convert, use the formula (2^19 * x)/(32 * 10^6) - // This library provides a helper function + LORA_PA_SELECT lora_pa_select; // Amplifier Selection + uint32_t lora_frequency; // The LORA carrier frequency, in kilohertz. + // To convert to internal chip unit, use the formula (2^19 * x)/(32 * 10^3) } LORA_CONFIG; -LORA_STATUS LORA_SPI_Receive( uint8_t* read_buffer_ptr ); - -LORA_STATUS LORA_SPI_Transmit_Buffer( LORA_REGISTER_ADDR reg, uint8_t data ); - -LORA_STATUS LORA_SPI_Transmit_Byte( LORA_REGISTER_ADDR reg ); - LORA_STATUS lora_read_register( LORA_REGISTER_ADDR lora_register, uint8_t* regData); LORA_STATUS lora_write_register( LORA_REGISTER_ADDR lora_register, uint8_t data ); @@ -167,11 +162,9 @@ LORA_STATUS lora_init(); void lora_reset(); LORA_STATUS lora_transmit(uint8_t* buffer_ptr, uint8_t buffer_len); -LORA_STATUS lora_receive(uint8_t* buffer_ptr, uint8_t* buffer_len_ptr); -// Convert a human-readable frequency to the unit used internally by the modem -uint32_t lora_helper_mhz_to_reg_val( uint32_t mhz_freq ); +LORA_STATUS lora_receive_ready(); -// LORA_STATUS lora_transmit( uint8_t data ); +LORA_STATUS lora_receive(uint8_t* buffer_ptr, uint8_t* buffer_len_ptr); #endif \ No newline at end of file