create a LoRa Modem from the PingPong example
Fork of SX1276PingPong by
Diff: main.cpp
- Revision:
- 10:9184674b5cfd
- Parent:
- 9:e764990e45df
- Child:
- 16:352011886276
--- a/main.cpp Tue Dec 16 12:52:01 2014 +0000 +++ b/main.cpp Sun Mar 06 11:10:13 2016 +0000 @@ -1,25 +1,45 @@ #include "mbed.h" #include "main.h" #include "sx1276-hal.h" + #include "debug.h" +/* CONFIGURATION */ + +#define NODE_ADDR 0x411A + /* Set this flag to '1' to display debug messages on the console */ -#define DEBUG_MESSAGE 0 +#define DEBUG_MESSAGE 1 + +#define RX_MODE 1 + +#define TX_MODE !RX_MODE + +/* Set the mode RX_MODE or TX_MODE */ +#define MODE RX_MODE + +/* Set the delay (according the duty cycle for the ISM band of the frequency RF_FREQUENCY */ + +#define DUTY_CYCLE 0.01 +//#define DELAY_NEXT_TX_IN_MILLISEC ((int)((timeOnAirInMilli / DUTY_CYCLE)-timeOnAirInMilli)) + +#define DELAY_NEXT_TX_IN_MILLISEC 5000 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */ #define USE_MODEM_LORA 1 #define USE_MODEM_FSK !USE_MODEM_LORA -#define RF_FREQUENCY 868000000 // Hz +#define RF_FREQUENCY 868100000 // Hz #define TX_OUTPUT_POWER 14 // 14 dBm + #if USE_MODEM_LORA == 1 - #define LORA_BANDWIDTH 2 // [0: 125 kHz, + #define LORA_BANDWIDTH 0 // [0: 125 kHz, // 1: 250 kHz, // 2: 500 kHz, // 3: Reserved] - #define LORA_SPREADING_FACTOR 7 // [SF7..SF12] + #define LORA_SPREADING_FACTOR 12 // [SF7..SF12] #define LORA_CODINGRATE 1 // [1: 4/5, // 2: 4/6, // 3: 4/7, @@ -46,8 +66,11 @@ #error "Please define a modem in the compiler options." #endif -#define RX_TIMEOUT_VALUE 3500000 // in us -#define BUFFER_SIZE 32 // Define the payload size here +#define RX_TIMEOUT_VALUE 1000000000 // in us +#define BUFFER_SIZE 17 // Define the payload size here + + +Serial pc(USBTX,USBRX); #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) ) DigitalOut led(LED2); @@ -61,211 +84,193 @@ typedef RadioState States_t; volatile States_t State = LOWPOWER; -SX1276MB1xAS Radio( OnTxDone, OnTxTimeout, OnRxDone, OnRxTimeout, OnRxError, NULL, NULL ); - -const uint8_t PingMsg[] = "PING"; -const uint8_t PongMsg[] = "PONG"; +SX1276MB1xAS Radio( OnTxDone, OnTxTimeout, OnRxDone, OnRxTimeout, OnRxError, NULL /*OnFhssChangeChannel*/, NULL /*OnCadDone*/ ); uint16_t BufferSize = BUFFER_SIZE; uint8_t Buffer[BUFFER_SIZE]; -int16_t RssiValue = 0.0; -int8_t SnrValue = 0.0; +int16_t RssiValue = 0; +int8_t SnrValue = 0; + +ModemType Modem; + +uint16_t SeqNum = 0; + +// Address of the Source Node +uint16_t NodeSrcAddr = NODE_ADDR; + +void hexprintf(Serial* pc, const uint8_t* buffer, uint16_t size) +{ + for(uint16_t count = 0; count < size; count++) + { + pc->printf("%02x", buffer[count]); + } +} +const uint8_t Msg[] = "TEST**##abcdefghijklmnopqrstuvwxyz#0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZ#0123456789#abcdefghijklmnopqrstuvwxyz#0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZ#0123456789#abcdefghijklmnopqrstuvwxyz#0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZ#0123456789#abcdefghijklmnopqrs#"; /* abc.. is for padding */ + int main() -{ - uint8_t i; - bool isMaster = true; +{ + + pc.format(8, Serial::None, 1); + pc.baud(115200); - debug( "\n\n\r SX1276 Ping Pong Demo Application \n\n\r" ); + sx_debug( ">INFO RX/TX Modem \r\n\n" ); // verify the connection with the board while( Radio.Read( REG_VERSION ) == 0x00 ) { - debug( "Radio could not be detected!\n\r", NULL ); + sx_debug( ">ERROR : Radio could not be detected!\r\n", NULL ); wait( 1 ); } - debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1LAS ) ) , "\n\r > Board Type: SX1276MB1LAS < \n\r" ); - debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1MAS ) ) , "\n\r > Board Type: SX1276MB1MAS < \n\r" ); + sx_debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1LAS ) ) , ">INFO Board Type: SX1276MB1LAS\r\n" ); + sx_debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1MAS ) ) , ">INFO Board Type: SX1276MB1MAS\r\n" ); Radio.SetChannel( RF_FREQUENCY ); + #if USE_MODEM_LORA == 1 - debug_if( LORA_FHSS_ENABLED, "\n\n\r > LORA FHSS Mode < \n\n\r"); - debug_if( !LORA_FHSS_ENABLED, "\n\n\r > LORA Mode < \n\n\r"); + sx_debug_if( LORA_FHSS_ENABLED, ">INFO LORA FHSS Mode\r\n"); + sx_debug_if( !LORA_FHSS_ENABLED, ">INFO LORA Mode\r\n"); - Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, + Modem = MODEM_LORA; + + Radio.SetTxConfig( Modem, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, LORA_IQ_INVERSION_ON, 2000000 ); - Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, + pc.printf(">INFO TX Parameters freq=%d bw=%d sf=%d cr=%d preamble=%d crc=%d fhss=%d hop=%d iq=%d\r\n", + RF_FREQUENCY, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, + LORA_PREAMBLE_LENGTH, LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, + LORA_IQ_INVERSION_ON + ); + + Radio.SetRxConfig( Modem, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0, LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, LORA_IQ_INVERSION_ON, true ); + + pc.printf(">INFO RX Parameters freq=%d bw=%d sf=%d cr=%d preamble=%d crc=%d fhss=%d hop=%d iq=%d\r\n", + RF_FREQUENCY, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, + LORA_PREAMBLE_LENGTH, LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, + LORA_IQ_INVERSION_ON + ); + #elif USE_MODEM_FSK == 1 - debug("\n\n\r > FSK Mode < \n\n\r"); + sx_debug(">INFO FSK Mode\r\n"); + + Modem = MODEM_FSK; + Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, FSK_DATARATE, 0, FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, FSK_CRC_ENABLED, 0, 0, 0, 2000000 ); + + pc.printf(">INFO TX Parameters freq=%d bw=%d sf=%d dr=%d\r\n", + RF_FREQUENCY, FSK_BANDWIDTH, FSK_DATARATE ); Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED, 0, 0, false, true ); + pc.printf(">INFO RX Parameters freq=%d bw=%d dr=%d afc_bw=%d preamble=%d crc=%d\r\n", + RF_FREQUENCY, FSK_BANDWIDTH, FSK_DATARATE, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, FSK_CRC_ENABLED ); + + #else #error "Please define a modem in the compiler options." #endif - - debug_if( DEBUG_MESSAGE, "Starting Ping-Pong loop\r\n" ); + led = 0; - +#if MODE == RX_MODE + sx_debug_if( DEBUG_MESSAGE, ">INFO Starting RX loop\r\n" ); + + // start RX Radio.Rx( RX_TIMEOUT_VALUE ); + State = LOWPOWER; +#elif MODE == TX_MODE + sx_debug_if( DEBUG_MESSAGE, ">INFO Starting TX loop\r\n" ); + State = TX; + +#else +#error "Please define a valid mode (RX_MODE, TX_MODE)." +#endif + +// TODO ECHO_MODE : RX_MODE then TX_MODE + while( 1 ) { switch( State ) { case RX: - if( isMaster == true ) - { if( BufferSize > 0 ) { - if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 ) - { - led = !led; - debug( "...Pong\r\n" ); - // Send the next PING frame - strcpy( ( char* )Buffer, ( char* )PingMsg ); - // We fill the buffer with numbers for the payload - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - else if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 ) - { // A master already exists then become a slave - debug( "...Ping\r\n" ); - led = !led; - isMaster = false; - // Send the next PONG frame - strcpy( ( char* )Buffer, ( char* )PongMsg ); - // We fill the buffer with numbers for the payload - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - else // valid reception but neither a PING or a PONG message - { // Set device as master ans start again - isMaster = true; - Radio.Rx( RX_TIMEOUT_VALUE ); - } + led = !led; // Invert LED + + + // TODO ADD tmst | number | Internal timestamp of "RX finished" event (32b unsigned) + + pc.printf(">INFO RX modem=%d size=%d rssi=%d snr=%d freq=%d bw=%d sf=%d cr=%d buffer=", + Modem, BufferSize, RssiValue, SnrValue, RF_FREQUENCY, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE ); + hexprintf(&pc, Buffer, BufferSize); + pc.printf("\r\n"); + + pc.printf("RX;%d;%d;%d;%d;%d;%d;%d;%d;", + Modem, BufferSize, RssiValue, SnrValue, RF_FREQUENCY, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE ); + hexprintf(&pc, Buffer, BufferSize); + pc.printf("\r\n"); +// wait_ms( 10 ); + Radio.Rx( RX_TIMEOUT_VALUE ); } - } - else - { - if( BufferSize > 0 ) - { - if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 ) - { - led = !led; - debug( "...Ping\r\n" ); - // Send the reply to the PING string - strcpy( ( char* )Buffer, ( char* )PongMsg ); - // We fill the buffer with numbers for the payload - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - else // valid reception but not a PING as expected - { // Set device as master and start again - isMaster = true; - Radio.Rx( RX_TIMEOUT_VALUE ); - } - } - } - State = LOWPOWER; - break; - case TX: - led = !led; - if( isMaster == true ) - { - debug( "Ping...\r\n" ); - } - else - { - debug( "Pong...\r\n" ); - } - Radio.Rx( RX_TIMEOUT_VALUE ); + State = LOWPOWER; break; case RX_TIMEOUT: - if( isMaster == true ) - { - // Send the next PING frame - strcpy( ( char* )Buffer, ( char* )PingMsg ); - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - else - { - Radio.Rx( RX_TIMEOUT_VALUE ); - } + Radio.Rx( RX_TIMEOUT_VALUE ); State = LOWPOWER; break; case RX_ERROR: - // We have received a Packet with a CRC error, send reply as if packet was correct - if( isMaster == true ) - { - // Send the next PING frame - strcpy( ( char* )Buffer, ( char* )PingMsg ); - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - else - { - // Send the next PONG frame - strcpy( ( char* )Buffer, ( char* )PongMsg ); - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } + // We have received a Packet with a CRC error + pc.printf(">INFO RX_ERROR size=%d\r\n", BufferSize); + pc.printf("RX_ERROR;%d\r\n", BufferSize); + Radio.Rx( RX_TIMEOUT_VALUE ); State = LOWPOWER; break; case TX_TIMEOUT: - Radio.Rx( RX_TIMEOUT_VALUE ); + pc.printf(">TX: TIMEOUT\r\n"); + case TX: + int timeOnAirInMilli = Radio.TimeOnAir(Modem,BufferSize)/1000; + if(DELAY_NEXT_TX_IN_MILLISEC!=0) { + pc.printf(">INFO: wait %.4f sec before TX\r\n", DELAY_NEXT_TX_IN_MILLISEC/1000.0); + wait_ms( DELAY_NEXT_TX_IN_MILLISEC ); + } + led = !led; // Invert LED + memcpy(( char* )Buffer, ( char* ) Msg, BufferSize); + ++SeqNum; + /* refresh counters in payload (big endian, for readability) */ + Buffer[4] = (uint8_t)(SeqNum >> 8); /* MSB */ + Buffer[5] = (uint8_t)(SeqNum & 0x00FF); /* LSB */ + Buffer[6] = (uint8_t)(NodeSrcAddr >> 8); /* MSB */ + Buffer[7] = (uint8_t)(NodeSrcAddr & 0x00FF); /* LSB */ + + /* send packet */ + pc.printf(">TX: src=%4x seqnum=%u size=%d timeOnAir=%.4f\r\n", NodeSrcAddr, SeqNum, BufferSize, timeOnAirInMilli/1000.0); + wait_ms( 10 ); + Radio.Send( Buffer, BufferSize ); State = LOWPOWER; - break; + break; case LOWPOWER: break; default: @@ -279,7 +284,7 @@ { Radio.Sleep( ); State = TX; - debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" ); + sx_debug_if( DEBUG_MESSAGE, ">INFO OnTxDone\r\n" ); } void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) @@ -290,14 +295,14 @@ RssiValue = rssi; SnrValue = snr; State = RX; - debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" ); + sx_debug_if( DEBUG_MESSAGE, ">INFO OnRxDone\r\n" ); } void OnTxTimeout( void ) { Radio.Sleep( ); State = TX_TIMEOUT; - debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" ); + sx_debug_if( DEBUG_MESSAGE, ">INFO OnTxTimeout\r\n" ); } void OnRxTimeout( void ) @@ -305,13 +310,29 @@ Radio.Sleep( ); Buffer[ BufferSize ] = 0; State = RX_TIMEOUT; - debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" ); + sx_debug_if( DEBUG_MESSAGE, ">INFO OnRxTimeout\r\n" ); } void OnRxError( void ) { Radio.Sleep( ); State = RX_ERROR; - debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" ); + sx_debug_if( DEBUG_MESSAGE, ">INFO OnRxError\r\n" ); } +/*! + * @brief Function executed on Radio Fhss Change Channel event + */ +void OnFhssChangeChannel( uint8_t channelIndex ) +{ + sx_debug_if( DEBUG_MESSAGE, ">INFO OnFhssChangeChannel\r\n" ); +} + +/*! + * @brief Function executed on CAD Done event + */ +void OnCadDone( void ) +{ + State = TX; + sx_debug_if( DEBUG_MESSAGE, ">INFO OnCadDone\r\n" ); +} \ No newline at end of file