MAX20361 System Demo with Low Power 2 mode

Dependencies:   SX1276GenericLib USBDevice

Fork of NonPingPong_PICO_LoRa by Walter Luu

SX1276GenericPingPong/GenericPingPong2.cpp

Committer:
walterluu
Date:
2020-10-20
Revision:
7:62c868478eef
Parent:
6:51f492ca61a2

File content as of revision 7:62c868478eef:

/*
 * This file contains a copy of the master content sx1276PingPong
 * with adaption for the SX1276Generic environment
 * (c) 2017 Helmut Tschemernjak
 * 30826 Garbsen (Hannover) Germany
 */
 
#include "mbed.h"
#include "PinMap.h"
#include "GenericPingPong2.h"
#include "sx1276-mbed-hal.h"
#include "main.h"
#include "global_buffers.h" //adding this for development		

#include "sx1276.h"

#include "USBSerial.h"

#ifdef FEATURE_LORA				// in main.cpp

/* 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 RF_FREQUENCY            RF_FREQUENCY_915_0  // Hz
#define TX_OUTPUT_POWER         1                  // 14 dBm

#if USE_MODEM_LORA == 1

#define LORA_BANDWIDTH          125000  // LoRa default, details in SX1276::BandwidthMap
#define LORA_SPREADING_FACTOR   LORA_SF7
#define LORA_CODINGRATE         LORA_ERROR_CODING_RATE_4_5

#define LORA_PREAMBLE_LENGTH    8       // Same for Tx and Rx, default
//#define LORA_PREAMBLE_LENGTH    5
#define LORA_SYMBOL_TIMEOUT     5       // Symbols
//#define LORA_SYMBOL_TIMEOUT     4       // 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    3500	// in ms, default
#define RX_TIMEOUT_VALUE    333	// in ms


//#define BUFFER_SIZE       32        // Define the payload size here
//#define BUFFER_SIZE         64        // Define the payload size here


/*
 *  Global variables declarations
 */
typedef enum
{
    LOWPOWER = 0,
    IDLE,
    
    RX,
    RX_TIMEOUT,
    RX_ERROR,
    
    TX,
    TX_TIMEOUT,
    
    CAD,
    CAD_DONE
} AppStates_t;

volatile AppStates_t State = LOWPOWER;

/*!
 * Radio events function pointer
 */
static RadioEvents_t RadioEvents;

/*
 *  Global variables declarations
 */
SX1276Generic *Radio;


//const uint8_t PingMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'I', 'N', 'G'};// "PING";
//const uint8_t PongMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'O', 'N', 'G'};// "PONG";

//uint16_t BufferSize = BUFFER_SIZE;
//uint8_t *Buffer;

// Aliases for the buffers that are made in the main()
uint8_t *BufferTx;
uint8_t *BufferRx;
USBSerial *ad;

DigitalOut *led3;


/*
This function is in Devin's main function

*/
int SX1276PingPongSetup(uint8_t *BufferTxFromMain, uint8_t *BufferRxFromMain, USBSerial *_ad) 
{
	ad = _ad;
	
	ad->printf("TEST\r\n" );
	
#if( defined ( TARGET_KL25Z ) || defined ( TARGET_Lad11U6X ) )
    DigitalOut *led = new DigitalOut(LED2);
#elif defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_DISCO_L072CZ_LRWAN1)
    DigitalOut *led = new DigitalOut(LED4);   // RX red
    led3 = new DigitalOut(LED3);  // TX blue
#else
    DigitalOut *led = new DigitalOut(LED1);
//    led = 0;
    led3 = led;
#endif
    
    BufferTx = BufferTxFromMain;
    BufferRx = BufferRxFromMain;
    *led3 = 0;						// change to 0

#ifdef B_L072Z_LRWAN1_LORA
    Radio = new SX1276Generic(NULL, MURATA_SX1276,
    		LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
        	LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5,
        	LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO);
#else // RFM95
    Radio = new SX1276Generic(NULL, RFM95_SX1276,
			LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
            LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5);

#endif
    
//    dprintf("SX1276 Ping Pong Demo Application" );
    ad->printf("SX1276 Ping Pong Demo Application\r\n");
//    dprintf("Freqency: %.1f", (double)RF_FREQUENCY/1000000.0);
     ad->printf("Freqency: %.1f\r\n", (double)RF_FREQUENCY/1000000.0);
//    dprintf("TXPower: %d dBm",  TX_OUTPUT_POWER);
    ad->printf("TXPower: %d dBm\r\n",  TX_OUTPUT_POWER);
#if USE_MODEM_LORA == 1
//    dprintf("Bandwidth: %d Hz", LORA_BANDWIDTH);
    ad->printf("Bandwidth: %d Hz\r\n", LORA_BANDWIDTH);
//    dprintf("Spreading factor: SF%d", LORA_SPREADING_FACTOR);
    ad->printf("Spreading factor: SF%d\r\n", LORA_SPREADING_FACTOR);
#elif USE_MODEM_FSK == 1
//    dprintf("Bandwidth: %d kHz",  FSK_BANDWIDTH);
    ad->printf("Bandwidth: %d kHz\r\n",  FSK_BANDWIDTH);
//    dprintf("Baudrate: %d", FSK_DATARATE);
    ad->printf("Baudrate: %d\r\n", FSK_DATARATE);
#endif
    // Initialize Radio driver
    RadioEvents.TxDone = OnTxDone;
    RadioEvents.RxDone = OnRxDone;
    RadioEvents.RxError = OnRxError;
    RadioEvents.TxTimeout = OnTxTimeout;
    RadioEvents.RxTimeout = OnRxTimeout;    
    if (Radio->Init( &RadioEvents ) == false) {
        while(1) {
//        	dprintf("Radio could not be detected!");
        	ad->printf("Radio could not be detected!\r\n");
        	wait( 1 );
        }
    }

    
    switch(Radio->DetectBoardType()) {
        case SX1276MB1LAS:
            if (DEBUG_MESSAGE)
                ad->printf(" > Board Type: SX1276MB1LAS <\r\n");
            break;
        case SX1276MB1MAS:
            if (DEBUG_MESSAGE)
                ad->printf(" > Board Type: SX1276MB1LAS <\r\n");
        case MURATA_SX1276:
            if (DEBUG_MESSAGE)
            	ad->printf(" > Board Type: MURATA_SX1276_STM32L0 <\r\n");
            break;
        case RFM95_SX1276:
            if (DEBUG_MESSAGE)
                ad->printf(" > HopeRF RFM95xx <\r\n");
            break;
        default:
            ad->printf(" > Board Type: unknown <\r\n");
    }

    Radio->SetChannel(RF_FREQUENCY ); 

#if USE_MODEM_LORA == 1
    
    if (LORA_FHSS_ENABLED)
        ad->printf("             > LORA FHSS Mode <\r\n");
    if (!LORA_FHSS_ENABLED)
        ad->printf("             > LORA Mode <\r\n");
	
	
	// Without this line, the default max payload length is only 64 bytes
	Radio->SetMaxPayloadLength(MODEM_LORA, 255);

    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, 2000 );
    
    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

    ad->printf("              > FSK Mode <\n");
    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, 2000 );
    
    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
     
    if (DEBUG_MESSAGE)
        ad->printf("Starting Ping-Pong loop\r\n"); 

#if MASTER == 1        
    Radio->Rx( RX_TIMEOUT_VALUE );	// initate Rx State for Master
#endif
    
return 0; //added by Walter due to "Control reaches end of non-void function"
}


bool SX1276MasterCheckForNewData(void)
{
    bool new_data_available = false;
    switch( State )
    {
    case RX:
        if( BufferSizeRx > 0 )
        {
            new_data_available = true;
            wait_ms( 10 ); //do we need this?
            if (DEBUG_MESSAGE)
                ad->printf( "State=RX\r\n" );
        }
        Radio->Rx( RX_TIMEOUT_VALUE );  
        State = LOWPOWER;
        break;
    case RX_TIMEOUT:
        wait_ms( 10 ); 
        if (DEBUG_MESSAGE)
                ad->printf( "State=RX_TIMEOUT\r\n" );     
        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
        wait_ms( 10 );  
        if (DEBUG_MESSAGE)
                ad->printf( "State=RX_ERROR\r\n" );
        Radio->Rx( RX_TIMEOUT_VALUE );
        State = LOWPOWER;
        break;
    case TX_TIMEOUT:
        if (DEBUG_MESSAGE)
                ad->printf( "State=TX_TIMEOUT\r\n" );
        State = LOWPOWER;
        break;
    case LOWPOWER:
        sleep();
        break;
    default:
        sleep(); // TODO, should this be removed?
        break;
    }   
    return new_data_available; 
}

void SX1276SlaveSendData(void)
{
    //wait_ms( 10 );  
    Radio->Send( BufferTx, BufferSizeTx );
    sleep();
}

/****************************************************************************************************************************************
 * 
 ****************************************************************************************************************************************/
//int SX1276PingPong(void)
//{
//#if   MASTER == 1 // Master Device: Bluetooth Gateway
//    bool isMaster = true;
//#elif SLAVE == 1 // Slave Device: Robot
//	bool isMaster = false;
//#endif
//	
//    switch( State )
//    {
//    case RX:
////        	*led3 = 0;				// uncommented
//        if( isMaster == true )		// Master Device received payload from Slave
//        {
//            if( BufferSizeRx > 0 )
//            {
//                /* This checks if the ID of the received transaction is matching that of
//                 * the slave device's ID. This is defined in the GenericPingPong.h
//                 */
//                if( memcmp(&BufferRx[rx_idx_signature], PongMsg, sizeof(PongMsg)) == 0 )
//                {
////                        *led = !*led;    
////						*led = 0;          // changed to 0
//					if (DEBUG_MESSAGE)
//	                    ad->printf( "...Pong\r\n" );
//                    wait_ms( 10 ); 
//                    Radio->Send( BufferTx, BufferSizeTx );
//                }	// memcmp != 0
//                else // valid reception but not a PONG message
//                {    // Set device as master and start again
//                    isMaster = true;					// new update
//                    Radio->Rx( RX_TIMEOUT_VALUE );
//                }	// end of if memcmp
//            }	// end of if BufferSizeRx > 0
//        }	// end of isMaster == true
//        else		// Slave Device received payload from Master
//        {
//            if( BufferSizeRx > 0 )
//            {
//                if( memcmp(BufferRx, PingMsg, sizeof(PingMsg)) == 0 )
//                {
////                        *led = !*led;
////							*led = 0			//changed to 0
//					if (DEBUG_MESSAGE)
//	                    ad->printf( "...Ping\r\n" );
//                    wait_ms( 10 );  
//                    Radio->Send( BufferTx, BufferSizeTx );
//                }
//                else // valid reception but not a PING as expected
//                {    // Set device as slave and start again
//                    isMaster = false;					// new update
//                    Radio->Rx( RX_TIMEOUT_VALUE );
//                }    
//            } // end of if BufferSizeRx > 0
//        } // end of if (isMaster == True), end of checking devices
//        
//        State = LOWPOWER;		// back to LOWPOWER State
//        
//        break;
//    case TX:    
////            *led3 = 0;		// change to 0
//        if( isMaster == true )  // Master Device
//        {
//            if (DEBUG_MESSAGE)
//	            ad->printf("Ping...\r\n" );
//        }
//        else		// Slave Device
//        {
//            if (DEBUG_MESSAGE)
//	            ad->printf("Pong...\r\n" );
//        }
//        Radio->Rx( RX_TIMEOUT_VALUE );
//        State = LOWPOWER;				// back to LOWPOWER State
//        break;
//    case RX_TIMEOUT:
//        if( isMaster == true )		// Master Device
//        {
//            wait_ms( 10 ); 
//            Radio->Send( BufferTx, BufferSizeTx );
//        }
//        else	// Slave Device
//        {
//            Radio->Rx( RX_TIMEOUT_VALUE );  
//        }             
//        State = LOWPOWER;			// back to LOWPOWER State
//        break;
//    case RX_ERROR:
//        // We have received a Packet with a CRC error, send reply as if packet was correct
//        if( isMaster == true )		// Master Device
//        {
//            // Send the next PING frame
////            memcpy(BufferTx, PingMsg, sizeof(PingMsg));
///*            
//            for( i = 4; i < BufferSizeTx; i++ )
//            {
//                BufferTx[i] = i - 4;
//            }
//*/
////			fillPayloadWithGlobalBufs(BufferTx);
//            wait_ms( 10 );  
//            Radio->Send( BufferTx, BufferSizeTx );
//        }
//        else			// Slave Device
//        {
//            // Send the next PONG frame
////            memcpy(BufferTx, PongMsg, sizeof(PongMsg));
///*
//            for( i = sizeof(PongMsg); i < BufferSizeTx; i++ )
//            {
//                BufferTx[i] = i - sizeof(PongMsg);
//            }
//*/
//            wait_ms( 10 );  
//            Radio->Send( BufferTx, BufferSizeTx );
//        }
//        State = LOWPOWER;		// Back to Low Power State
//        break;
//    case TX_TIMEOUT:
//        Radio->Rx( RX_TIMEOUT_VALUE );
//        State = LOWPOWER;
//        break;
//    case LOWPOWER:
//    	sleep();
//        break;
//    default:
//        State = LOWPOWER;
//        break;
//    }    
//}


int TimeOnAirSend(void) {

	return  Radio->TimeOnAir( MODEM_LORA, sizeof(BufferSizeTx));

}	


int SX1276SensorSend(void) {
	
	switch( State )
	{
	    case RX:
           // if( BufferSizeRx > 0 )
//            {
//                Radio->Send( BufferTx, BufferSizeTx );
//                Radio->Rx( RX_TIMEOUT_VALUE );
//	        } // end of if BufferSizeRx > 0
	        
	        Radio->Send( BufferTx, BufferSizeTx );
            Radio->Rx( RX_TIMEOUT_VALUE );
	        
	        State = LOWPOWER;		// back to LOWPOWER State
	        
	    break;
	}	// end of switch statement
}



int SX1276GateWayReceive(int TimeOut) {
	
	switch( State )
	{
	    case RX:
           // if( BufferSizeRx > 0 )
//            {
////                Radio->Send( BufferTx, BufferSizeTx );
//                Radio->Rx( RX_TIMEOUT_VALUE );
//	        } // end of if BufferSizeRx > 0
	        
	        
//	        Radio->Rx( RX_TIMEOUT_VALUE );
	        
	        Radio->Rx( TimeOut );
	        
	        State = LOWPOWER;		// back to LOWPOWER State
	        
	    break;
	}	// end of switch statement
}




//void OnTxDone(void *radio, void *userThisPtr, void *userData)
//{
//    Radio->Sleep( );
//    State = TX;
//    if (DEBUG_MESSAGE)
//        dprintf("> OnTxDone");
//}

// moved to main
void OnTxDone(void *radio, void *userThisPtr, void *userData)
{
    Radio->Sleep( );
    State = TX;
    if (DEBUG_MESSAGE)
        //dprintf("> OnTxDone");
        ad->printf("> OnTxDone");
}


//void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
//{
//    Radio->Sleep( );
//    BufferSize = size;
//    memcpy( Buffer, payload, BufferSize );
//    State = RX;
//    if (DEBUG_MESSAGE)
//        dprintf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d", rssi, snr);
//    dump("Data:", payload, size);
//}

// moved to main
void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
    Radio->Sleep( );
    
    if(BufferSizeRx != size)
    	memcpy( BufferRx, payload, size );
    else
    	memcpy( BufferRx, payload, BufferSizeRx );
    State = RX;
    
    // Reset the RxTimeoutCount 
    RxTimeoutCount = 0;

    if (DEBUG_MESSAGE) {
        ad->printf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d\n", rssi, snr);
    	dump("Data:", payload, size);
	}
}

//void OnTxTimeout(void *radio, void *userThisPtr, void *userData)
//{
//    *led3 = 0;
//    Radio->Sleep( );
//    State = TX_TIMEOUT;
//    if(DEBUG_MESSAGE)
//        dprintf("> OnTxTimeout");
//}

// moved to main
void OnTxTimeout(void *radio, void *userThisPtr, void *userData)
{
//    *led3 = 0;
    Radio->Sleep( );
    State = TX_TIMEOUT;
    if(DEBUG_MESSAGE)
        ad->printf("> OnTxTimeout");
}

//void OnRxTimeout(void *radio, void *userThisPtr, void *userData)
//{
//    *led3 = 0;
//    Radio->Sleep( );
//    Buffer[BufferSize-1] = 0;
//    State = RX_TIMEOUT;
//    if (DEBUG_MESSAGE)
//        dprintf("> OnRxTimeout");
//}

// moved to main
void OnRxTimeout(void *radio, void *userThisPtr, void *userData)
{
    Radio->Sleep( );
    BufferRx[BufferSizeRx-1] = 0;
    State = RX_TIMEOUT;
    if (DEBUG_MESSAGE)
        ad->printf("> OnRxTimeout\n");
        
	// Increment how many times a transmission times out\
	RxTimeoutCount = RxTimeoutCount + 1;
}

//void OnRxError(void *radio, void *userThisPtr, void *userData)
//{
//    Radio->Sleep( );
//    State = RX_ERROR;
//    if (DEBUG_MESSAGE)
//        dprintf("> OnRxError");
//}

// moved to main
void OnRxError(void *radio, void *userThisPtr, void *userData)
{
    Radio->Sleep( );
    State = RX_ERROR;
    if (DEBUG_MESSAGE)
        ad->printf("> OnRxError\n");
        
    // Increment how many times a transmission times out\
	RxTimeoutCount = RxTimeoutCount + 1;
}


int numOfRxTimeouts()
{
	return RxTimeoutCount;
}




#endif