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:
gremond
Date:
2015-11-25
Revision:
17:660ab11cd0ad
Parent:
16:590e0f613893

File content as of revision 17:660ab11cd0ad:

/*
 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
    (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
Actility maintainer: Geoffroy de Guillebon and Guillaume Rémond
*/
#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                     0

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

/*!
 * Device address
 */
static uint32_t DevAddr = 0x00000000;                               /// <<< Change here

/*!
 * AES encryption/decryption cipher network session key
 */
static uint8_t NwkSKey[] = 
{ 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                 /// <<< Change here
    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,                 /// <<< Change here
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};




/*!
 * 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                              50000000  // 50 [s] value in us (minimum 10s)
#define APP_TX_DUTYCYCLE_RND                          10000000  // 10 [s] value in us (minimum 3s)

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

/*!
 * 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;

static float LightValue = 0.0; 
static uint8_t LightMode = 0;  // 0:automatic, 1:manual

Ticker Led1Timer;
Ticker Led2Timer;
Ticker BuzTimer;


InterruptIn userButton(USER_BUTTON);      // User button on NUCLEO board
//DigitalOut TxLed(LED1);               // not used, do not use LED1 with the Semtech SX1276MB1xAS board
//DigitalOut RxLed(A2);                 // not used

AnalogIn LightSens( A1 ); 
#define NUM_LED 3
ChainableLED color_led(D6, D7, NUM_LED);
DigitDisplay display(D8, D9);
DigitalOut buzzer(A2);


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

/*!
 *
 */
static void PrepareTxFrame( uint8_t port )
{
    uint32_t tempValue = (uint32_t)(LightValue*1000000.0);
    
    debug( "[Tx] LightValue=%d 0x%x\n\r" , tempValue, tempValue);
    
    AppData[0] = LightMode;
    AppData[1] = ((tempValue&0xFF000000)>>24)&0xFF;
    AppData[2] = ((tempValue&0x00FF0000)>>16)&0xFF;
    AppData[3] = ((tempValue&0x0000FF00)>>8)&0xFF;
    AppData[4] = (tempValue&0x000000FF);
}

static void ProcessRxFrame( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info )
{
    debug( "[Rx] Port=%d\n\r" , info->RxPort);
    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:
            LightMode = info->RxBuffer[0];
            debug( "[Rx] LightMode=%x - R G B= 0x%x 0x%x 0x%x\n\r" , LightMode, info->RxBuffer[1], info->RxBuffer[2], info->RxBuffer[3]);
            if( LightMode )
            {
                color_led.setColorRGB(0, info->RxBuffer[1], info->RxBuffer[2], info->RxBuffer[3] );
            }
            break;
            
        case 30:
            BuzTimer.attach_us( &OnBuzTimerEvent, 500000 );
            buzzer = 1;
            break;
            
        default:
            break;
    }
}

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

//    TxLed = 1;
    
    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 )
{
//    TxLed = 0;  
//  RxLed = 1;
    
    debug( "[OnMacEvent]\n\r");
    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
//  RxLed = 0;
    TxDone = true;
}

/**
 * Main application entry point.
 */
int main( void )
{
#if( OVER_THE_AIR_ACTIVATION != 0 )
    uint8_t sendFrameStatus = 0;
#endif
    bool trySendingFrameAgain = false;
    float tempLightValue = 0;   
    
//    TxLed = 0;
//    RxLed = 0;
    
    LightMode = 0;      // 0: manual,   1: automatic
    buzzer = 0;         // 0: OFF,      1: ON

    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]
    if( ( DevAddr == 0 ) || ( DevAddr == 0xFFFFFFFF ) )
    {
        // Generate random DevAddr if it does not exist
        debug("Generate random DevAddr\n\r");
        DevAddr = randr( 0, 0x01FFFFFF );
    }
    debug( "- DevAddr = 0x%x\n\r" , DevAddr);    
    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("[OTAA] JoinReq 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( "[Tx] done\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( );
        }

        // Read light sensor
        tempLightValue = LightSens.read( ) * 1.65;
        
        LightValue = ( 1 - tempLightValue );
        
        // Set automatic RGB from light sensor
        if( LightMode == 0 )
        {
            color_led.setColorRGB( 0, ( uint8_t )( 255 * LightValue ), ( uint8_t )( 255 * LightValue ), ( uint8_t )( 255 * LightValue ) );
        }
//        TimerLowPowerHandler( );
    }
}