Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed Private_lora_SX1276
main.cpp
- Committer:
- hakusan270
- Date:
- 2020-12-18
- Revision:
- 3:87140a4e4903
- Parent:
- 2:0da0a3008102
File content as of revision 3:87140a4e4903:
#include "mbed.h"
#include "main.h"
#include "sx1276-hal.h"
#include "debug.h"
/***********************************************
Semtech SX1276 Loraの実験
Priva Lora
SX1278 NUCLEO 接続
3.3V AVDD
GND GND
SPI SCK D13
SPI MISO D12
SPI MOSI D11
SPI CS D10
RESET D9
DIO0 D8
通常は送信
ボタン押し リセットで受信モード
***********************************************/
/* Set this flag to '1' to display debug messages on the console */
#define DEBUG_MESSAGE 1
/* 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 RF868 1 //920Mhz 429MHzはコメントにする
#ifdef RF868
#define RF_FREQUENCY 921000000 // Hz
#define TX_OUTPUT_POWER 13 // 13 dBm 20mW 20dB 100mWまで可能
#else
#define RF_FREQUENCY 426375000 // Hz
#define TX_OUTPUT_POWER 13 // 20 dBm 20mW 20dB 100mWまで可能
#endif
#if USE_MODEM_LORA == 1
#define LORA_BANDWIDTH 0
#define LORA_SPREADING_FACTOR 12 /*6-12 12が一番遅いが感度*/
#define LORA_CODINGRATE 2
//#define LORA_BANDWIDTH 2 // [0: 125 kHz,
// 1: 250 kHz,
// 2: 500 kHz,
// 3: Reserved]
//#define LORA_SPREADING_FACTOR 7 // [SF7..SF12]
//#define LORA_CODINGRATE 1 // [1: 4/5,
// 2: 4/6,
// 3: 4/7,
// 4: 4/8]
#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 5 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_FHSS_ENABLED false
#define LORA_NB_SYMB_HOP 4
#define LORA_IQ_INVERSION_ON false
#define LORA_CRC_ENABLED true
#elif USE_MODEM_FSK == 1
#define FSK_FDEV 25000 // Hz
#define FSK_DATARATE 19200 // bps
#define FSK_BANDWIDTH 50000 // Hz
#define FSK_AFC_BANDWIDTH 83333 // Hz
#define FSK_PREAMBLE_LENGTH 5 // Same for Tx and Rx
#define FSK_FIX_LENGTH_PAYLOAD_ON false
#define FSK_CRC_ENABLED true
#else
#error "Please define a modem in the compiler options."
#endif
#define RX_TIMEOUT_VALUE 3500000 // in us
#define BUFFER_SIZE 64 // Define the payload size here
#if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) )
DigitalOut led(LED2);
#else
//DigitalOut led(LED1);
//DigitalOut led2(LED2);
//DigitalOut led3(LED3);
//DigitalOut led4(LED4);
DigitalOut debugled(D6);
DigitalOut debugled2(D7);
#endif
DigitalIn role(USER_BUTTON); // PC_13 in Mini 103RC mini board
Timer tx_tmr;
#define UART_ENABLE
#ifdef UART_ENABLE
//Serial pc(USBTX, USBRX);
Serial pc(SERIAL_TX, SERIAL_RX,115200);
#endif
Ticker nwk_ticker;
bool channelOccupied = false;
#define NWK_SLEEP 0
#define NWK_TX 1
#define NWK_TX_NOK 2
#define NWK_RX_OK 3
#define NWK_RX_NOK 4
//#define PINGPONG
void nwk_toggle()
{
debugled = !debugled;
debugled2 = !debugled2;
}
void nwk_setmode(uint8_t mode)
{
switch(mode){
case NWK_TX:
case NWK_RX_OK:
nwk_ticker.attach(&nwk_toggle, 1);
break;
case NWK_TX_NOK:
case NWK_RX_NOK:
nwk_ticker.attach(&nwk_toggle, 0.1);
break;
case NWK_SLEEP:
default:
debugled = 0;
debugled2 = 0;
nwk_ticker.detach();
break;
}
}
/*
* Global variables declarations
*/
typedef enum
{
ST_LOWPOWER = 0,
ST_IDLE,
ST_RX,
ST_RX_TIMEOUT,
ST_RX_ERROR,
ST_TX,
ST_TX_TIMEOUT,
ST_CAD,
ST_CAD_DONE
}AppStates_t;
volatile AppStates_t State = ST_LOWPOWER;
/*!
* Radio events function pointer
*/
static RadioEvents_t RadioEvents;
/*
* Global variables declarations
*/
SX1276MB1xAS Radio( NULL );
const uint8_t PingMsg[] = "PING";
const uint8_t PongMsg[] = "PONG";
const uint8_t TestMsg[] = "LoRa Test";
uint16_t BufferSize = 56;//up to 56 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;
#define REG_SIZE 0x70 // see below
#define REG_IDX_SIZE 39
static int my_strncmp(const char *, const char *, int);
static void my_strcpy(char * , const char *);
int my_strncmp(const char * s1, const char * s2, int size)
{
int n = size;
for ( ; n > 0; s1++, s2++, --n)
if (*s1 != *s2)
return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1);
else if (*s1 == '\0')
return 0;
return 0;
}
void my_strcpy(char * s1, const char * s2)
{
char *s = s1;
while ((*s++ = *s2++) != 0)
;
}
void Sender ( void )
{
int i;
my_strcpy( ( char* )Buffer, ( char* )PingMsg );
for( i = 4; i < BufferSize; i++ ){
Buffer[i] = (i % 10) + '0' ;
}
Radio.Send( Buffer, BufferSize );
}
int main()
{
uint8_t i;
uint8_t regval;
bool isMaster = true;
int begin, end;
uint32_t rand;
debugled = 1;
debugled2 = 1;
isMaster = role.read();
//debug( "\n\n\r SX1276 Ping Pong Demo Application \n\n\r" );
// Initialize Radio driver
RadioEvents.TxDone = OnTxDone;
RadioEvents.RxDone = OnRxDone;
RadioEvents.RxError = OnRxError;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxTimeout = OnRxTimeout;
Radio.Init( &RadioEvents );
#ifdef UART_ENABLE
regval = Radio.Read(REG_VERSION);
pc.printf("%s freq=%d", TestMsg, RF_FREQUENCY );
pc.printf("IC Version: %02X\r\n", regval);
regval = Radio.Read(REG_OPMODE);
pc.printf("OPMODE: %02X\r\n", regval);
#endif
debugled = 0;
debugled2 = 0;
// verify the connection with the board
while( Radio.Read( REG_VERSION ) == 0x00 )
{
//debug( "Radio could not be detected!\n\r", 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" );
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");
Radio.SetTxConfig( MODEM_LORA, 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,
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 );
#elif USE_MODEM_FSK == 1
//debug("\n\n\r > FSK Mode < \n\n\r");
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 );
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 );
#else
#error "Please define a modem in the compiler options."
#endif
//debug_if( DEBUG_MESSAGE, "Starting Ping-Pong loop\r\n" );
rand = Radio.Random();
rand = rand%1000;
wait_ms((uint16_t)rand);
#ifdef PINGPONG
Radio.Rx( RX_TIMEOUT_VALUE );
int j=0;
while( 1 )
{
switch( State )
{
case ST_RX:
if( isMaster == true )
{
if( BufferSize > 0 )
{
#ifdef UART_ENABLE
pc.printf("Received message:\r\n");
pc.printf("%s",Buffer);
#endif
//if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
if( my_strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
{
nwk_setmode(NWK_NORMAL);
//debug( "...Pong\r\n" );
// Send the next PING frame
my_strcpy( ( char* )Buffer, ( char* )PingMsg );
//_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( my_strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
{ // A master already exists then become a slave
debug( "...Ping\r\n" );
//nwk_setmode(NWK_NORMAL);
//led = !led;
isMaster = false;
// Send the next PONG frame
my_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 );
}
}
}
else
{
if( BufferSize > 0 )
{
#ifdef UART_ENABLE
pc.printf("Received message:\r\n");
pc.printf("%s",Buffer);
#endif
if( my_strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
{
nwk_setmode(NWK_NORMAL);
//led = !led;
//debug( "...Ping\r\n" );
// Send the reply to the PING string
my_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 = ST_LOWPOWER;
break;
case ST_TX:
//nwk_setmode(NWK_NORMAL);
//led = !led;
if( isMaster == true )
{
//debug( "Ping...\r\n" );
}
else
{
//debug( "Pong...\r\n" );
}
Radio.Rx( RX_TIMEOUT_VALUE );
State = ST_LOWPOWER;
break;
case ST_RX_TIMEOUT:
//debugled = !debugled;
//debugled2 = !debugled2;
nwk_setmode(NWK_ERR);
if( isMaster == true )
{
// Send the next PING frame
my_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 );
}
State = ST_LOWPOWER;
break;
case ST_RX_ERROR:
// We have received a Packet with a CRC error, send reply as if packet was correct
nwk_setmode(NWK_ERR);
if( isMaster == true )
{
// Send the next PING frame
my_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
my_strcpy( ( char* )Buffer, ( char* )PongMsg );
for( i = 4; i < BufferSize; i++ )
{
Buffer[i] = i - 4;
}
wait_ms( 10 );
Radio.Send( Buffer, BufferSize );
}
State = ST_LOWPOWER;
break;
case ST_TX_TIMEOUT:
nwk_setmode(NWK_ERR);
Radio.Rx( RX_TIMEOUT_VALUE );
State = ST_LOWPOWER;
break;
case ST_CAD:
break;
case ST_CAD_DONE:
if(channelOccupied){
State = ST_LOWPOWER;
}else{
// start to transmit here.
}
break;
case ST_LOWPOWER:
break;
default:
nwk_setmode(0xFF);
State = ST_LOWPOWER;
break;
}
}
#else
int j=0;
if(isMaster == true){
tx_tmr.start();
begin = tx_tmr.read_ms();
}else{
Radio.Rx( RX_TIMEOUT_VALUE );
}
while(1){
switch(State){
case ST_RX:
//nwk_setmode(NWK_RX_OK);
Radio.Rx( RX_TIMEOUT_VALUE );
State = ST_LOWPOWER;
#ifdef UART_ENABLE
//pc.printf("\r\nRX OK\tRSSI:%f SNR:%f \r\n",float(RssiValue),float(SnrValue));
if (RssiValue>=64) RssiValue -= 256;
pc.printf("RX OK\tRSSI:%d SNR:%d ",RssiValue,SnrValue);
for(i=0;i<BufferSize;i++) if (Buffer[i] & 0x80) Buffer[i]=0;
pc.printf("\tSZ=%d %s\r\n", BufferSize,Buffer);
Buffer[0]=0;
#endif
break;
case ST_TX:
nwk_setmode(NWK_TX);
State = ST_LOWPOWER;
#ifdef UART_ENABLE
pc.printf("\r\nTX Done.\r\n");
#endif
break;
case ST_RX_TIMEOUT:
case ST_RX_ERROR:
//nwk_setmode(NWK_RX_NOK);
Radio.Rx( RX_TIMEOUT_VALUE );
State = ST_LOWPOWER;
#ifdef UART_ENABLE
pc.printf("\r\nRX TIMEOUT or ERROR.\r\n");
#endif
break;
case ST_TX_TIMEOUT:
State = ST_LOWPOWER;
break;
case ST_LOWPOWER:
if (isMaster){
end = tx_tmr.read_ms();
if ((end-begin) >= 2000){
Sender();
tx_tmr.stop();
tx_tmr.start();
begin = tx_tmr.read_ms();
if (j++ > 500) NVIC_SystemReset();
}
}
break;
default:
State = ST_LOWPOWER;
break;
}
}
#endif
}
void OnTxDone( void )
{
Radio.Sleep( );
State = ST_TX;
//debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" );
}
void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
Radio.Sleep( );
BufferSize = size;
memcpy( Buffer, payload, BufferSize );
RssiValue = rssi;
SnrValue = snr;
State = ST_RX;
nwk_setmode(NWK_RX_OK);
//debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" );
}
void OnTxTimeout( void )
{
Radio.Sleep( );
State = ST_TX_TIMEOUT;
//debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" );
}
void OnRxTimeout( void )
{
Radio.Sleep( );
Buffer[ BufferSize ] = 0;
State = ST_RX_TIMEOUT;
nwk_setmode(NWK_RX_NOK);
//debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" );
}
void OnRxError( void )
{
Radio.Sleep( );
State = ST_RX_ERROR;
//debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" );
}
// Added by allankliu
void OnCadDone( bool channelActivityDetected )
{
Radio.Sleep();
channelOccupied = channelActivityDetected;
State = ST_CAD_DONE;
}