Fork from LoRa Alliance program. available here: https://developer.mbed.org/users/Alliance/code/LoRaWAN/

Dependencies:   LoRaMacLib SX1276Lib mbed Chainable_RGB_LED DigitDisplay

Fork of LoRaWAN by LoRa All

main.cpp

Committer:
Alliance
Date:
2015-10-20
Revision:
5:2499c195ccfe
Parent:
4:0c164d628006
Child:
6:ea71f564e0ce

File content as of revision 5:2499c195ccfe:

/*
 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
    (C)2015 Semtech

Description: LoRaMac classA device implementation

License: Revised BSD License, see LICENSE.TXT file include in the project

Maintainer: Miguel Luis and Gregory Cristian
*/
#include "mbed.h"
#include "board.h"
#include "LoRaMac.h"
#include "utilities.h"
#include "DigitDisplay.h"
#include "ChainableLED.h"

/*!
 * When set to 1 the application uses the Over-the-Air activation procedure
 * When set to 0 the application uses the Personalization activation procedure
 */
#define OVER_THE_AIR_ACTIVATION                     1

/*!
 * Mote device IEEE EUI
 */
static uint8_t DevEui[] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

#if( OVER_THE_AIR_ACTIVATION != 0 )

#define OVER_THE_AIR_ACTIVATION_DUTYCYCLE          10000000  // 10 [s] value in us

/*!
 * Application IEEE EUI
 */
static uint8_t AppEui[] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/*!
 * AES encryption/decryption cipher application key
 */
static uint8_t AppKey[] = 
{ 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

#else

/*!
 * AES encryption/decryption cipher network session key
 */
static uint8_t NwkSKey[] = 
{ 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/*!
 * AES encryption/decryption cipher application session key
 */
static uint8_t AppSKey[] = 
{ 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/*!
 * Device address
 */
static uint32_t DevAddr;

#endif

/*!
 * Indicates if the MAC layer has already joined a network.
 */
static bool IsNetworkJoined = false;

/*!
 * Defines the application data transmission duty cycle
 */
#define APP_TX_DUTYCYCLE                            10000000  // 10 [s] value in us
#define APP_TX_DUTYCYCLE_RND                         2000000  // 2 [s] value in us

/*!
 * User application data buffer size
 */
#define APP_DATA_SIZE                               8

/*!
 * User application data
 */
static uint8_t AppData[APP_DATA_SIZE];

/*!
 * Defines the application data transmission duty cycle
 */
static uint32_t TxDutyCycleTime;

Ticker TxNextPacketTimer;

#if( OVER_THE_AIR_ACTIVATION != 0 )

/*!
 * Defines the join request timer
 */
Ticker JoinReqTimer;

#endif

/*!
 * Indicates if a new packet can be sent
 */
static bool TxNextPacket = true;
static bool TxDone = false;

static uint8_t AppPort = 3;
static uint8_t AppDataSize = APP_DATA_SIZE;

static LoRaMacEvent_t LoRaMacEvents;

Ticker Led1Timer;
Ticker Led2Timer;
Ticker BuzTimer;

#define NUM_LED 3


// ChainableLED(clk, data, number_of_leds)
ChainableLED color_led(D8, D9, NUM_LED);

DigitDisplay display(D6, D7);

DigitalOut buzzer(A2);


static void OnBuzTimerEvent( void )
{
    buzzer = 0;
    BuzTimer.detach( );
}

/*!
 *
 */
static void PrepareTxFrame( uint8_t port )
{
    AppData[0] = 0x99;
    AppData[1] = 0x99;
    AppData[2] = 0x99;
    AppData[3] = 0x99;
    AppData[4] = 0x99;
    AppData[5] = 0x99;
    AppData[6] = 0x99;
    AppData[7] = 0x99;
}

static void ProcessRxFrame( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info )
{
    switch( info->RxPort ) // Check Rx port number
    {
        case 10: 
            display.write( 0, info->RxBuffer[0] );
            display.write( 1, info->RxBuffer[1] );
            display.write( 2, info->RxBuffer[2] );
            display.write( 3, info->RxBuffer[3] ); 
            break;
            
        case 20:
            color_led.setColorRGB(0, info->RxBuffer[0], info->RxBuffer[1], info->RxBuffer[2] );
            break;
            
        case 30:
            BuzTimer.attach_us( &OnBuzTimerEvent, 500000 );
            buzzer = 1;
            break;
            
        default:
            break;
    }
}

static bool SendFrame( void )
{
    uint8_t sendFrameStatus = 0;

    sendFrameStatus = LoRaMacSendFrame( AppPort, AppData, AppDataSize );
 //   sendFrameStatus = LoRaMacSendConfirmedFrame( AppPort, AppData, AppDataSize, 8 );
    switch( sendFrameStatus )
    {
    case 5: // NO_FREE_CHANNEL
        // Try again later
        return true;
    default:
        return false;
    }
}


#if( OVER_THE_AIR_ACTIVATION != 0 )
/*!
 * \brief Function executed on JoinReq Timeout event
 */
static void OnJoinReqTimerEvent( void )
{
    TxNextPacket = true;
    JoinReqTimer.detach( );
}
#endif


/*!
 * \brief Function executed on TxNextPacket Timeout event
 */
static void OnTxNextPacketTimerEvent( void )
{    
    TxNextPacket = true;
    TxNextPacketTimer.detach( );
}


/*!
 * \brief Function to be executed on MAC layer event
 */
static void OnMacEvent( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info )
{
    if( flags->Bits.JoinAccept == 1 )
    {
#if( OVER_THE_AIR_ACTIVATION != 0 )
        JoinReqTimer.detach( );
#endif
        IsNetworkJoined = true;
    }
    
    if( flags->Bits.Tx == 1 )
    {
    }

    if( flags->Bits.Rx == 1 )
    {
        if( flags->Bits.RxData == true )
        {
            ProcessRxFrame( flags, info );
        }
    }

    // Schedule a new transmission
    TxDone = true;
}

/**
 * Main application entry point.
 */
int main( void )
{
#if( OVER_THE_AIR_ACTIVATION != 0 )
    uint8_t sendFrameStatus = 0;
#endif
    bool trySendingFrameAgain = false;

    buzzer = 0;

    debug( "\n\n\r    LoRaWAN Class A Demo code  \n\n\r" );
    
    BoardInitMcu( );
    BoardInitPeriph( );

    // Initialize LoRaMac device unique ID
    // BoardGetUniqueId( DevEui );
    
    LoRaMacEvents.MacEvent = OnMacEvent;
    LoRaMacInit( &LoRaMacEvents );

    IsNetworkJoined = false;

#if( OVER_THE_AIR_ACTIVATION == 0 )
    // Random seed initialization
    srand( RAND_SEED );
    // Choose a random device address
    // NwkID = 0
    // NwkAddr rand [0, 33554431]
    DevAddr = randr( 0, 0x01FFFFFF );
        
    LoRaMacInitNwkIds( 0x000000, DevAddr, NwkSKey, AppSKey );
    IsNetworkJoined = true;
#endif

    TxNextPacket = true;

    LoRaMacSetAdrOn( false );
    
    LoRaMacSetDutyCycleOn( false );    
        
    while( 1 )
    {
        while( IsNetworkJoined == false )
        {
#if( OVER_THE_AIR_ACTIVATION != 0 )
            if( TxNextPacket == true )
            {
                TxNextPacket = false;
                
                sendFrameStatus = LoRaMacJoinReq( DevEui, AppEui, AppKey );
                debug("Req Sent\n\r");
                switch( sendFrameStatus )
                {
                case 1: // BUSY
                    break;
                case 0: // OK
                case 2: // NO_NETWORK_JOINED
                case 3: // LENGTH_PORT_ERROR
                case 4: // MAC_CMD_ERROR
                case 6: // DEVICE_OFF
                default:
                    // Relaunch timer for next trial
                    JoinReqTimer.attach_us( &OnJoinReqTimerEvent, OVER_THE_AIR_ACTIVATION_DUTYCYCLE );
                    break;
                }
            }
//            TimerLowPowerHandler( );
#endif
        }

        if( TxDone == true )
        {
            
            TxDone = false;
            
            debug( "TxDone \n\n\r" );
            // Schedule next packet transmission
            TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
            TxNextPacketTimer.attach_us( &OnTxNextPacketTimerEvent, TxDutyCycleTime );
        }

        if( trySendingFrameAgain == true )
        {
            trySendingFrameAgain = SendFrame( );
        }
        
        if( TxNextPacket == true )
        {       
            TxNextPacketTimer.detach( );
            
            TxNextPacket = false;
        
            PrepareTxFrame( AppPort );
            
            trySendingFrameAgain = SendFrame( );
        }

//        TimerLowPowerHandler( );
    }
}