I-O DATA DEV2 / Mbed 2 deprecated Nucleo_Private_LoRa

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;
}