testing lora and ble on nrf51

Dependencies:   BLE_API LoRaWAN-lib SX1276Lib mbed nRF51822

Revision:
0:4c1fcbfcc7bf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon May 09 08:06:21 2016 +0000
@@ -0,0 +1,555 @@
+#include "mbed.h"
+#include "board.h"
+#include "radio.h"
+
+#include "LoRaMac.h"
+#include "Comissioning.h"
+
+/*!
+ * Join requests trials duty cycle.
+ */
+#define OVER_THE_AIR_ACTIVATION_DUTYCYCLE           10000000  // 10 [s] value in us
+
+/*!
+ * Defines the application data transmission duty cycle. 5s, value in [us].
+ */
+#define APP_TX_DUTYCYCLE                            5000000
+
+/*!
+ * Defines a random delay for application data transmission duty cycle. 1s,
+ * value in [us].
+ */
+#define APP_TX_DUTYCYCLE_RND                        1000000
+
+/*!
+ * Default mote datarate
+ */
+#define LORAWAN_DEFAULT_DATARATE                    DR_0
+
+/*!
+ * LoRaWAN confirmed messages
+ */
+#define LORAWAN_CONFIRMED_MSG_ON                    false
+
+#define LORAWAN_ADR_ON                              1
+
+#define LORAWAN_DUTYCYCLE_ON                        false
+
+#define LORAWAN_APP_PORT                            15
+
+/*!
+ * User application data buffer size
+ */
+#if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
+#define LORAWAN_APP_DATA_SIZE                       6
+
+#else
+#define LORAWAN_APP_DATA_SIZE                       1
+
+#endif
+
+#if( OVER_THE_AIR_ACTIVATION != 0 )
+
+static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
+static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
+static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
+
+#else
+
+static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
+static uint8_t AppSKey[] = LORAWAN_APPSKEY;
+
+/*!
+ * Device address
+ */
+static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
+
+#endif
+
+/*!
+ * Application port
+ */
+static uint8_t AppPort = LORAWAN_APP_PORT;
+
+/*!
+ * User application data size
+ */
+static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE;
+
+/*!
+ * User application data buffer size
+ */
+#define LORAWAN_APP_DATA_MAX_SIZE                           64
+
+/*!
+ * User application data
+ */
+static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
+
+/*!
+ * Indicates if the node is sending confirmed or unconfirmed messages
+ */
+static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
+
+/*!
+ * Defines the application data transmission duty cycle
+ */
+static uint32_t TxDutyCycleTime;
+
+/*!
+ * Timer to handle the application data transmission duty cycle
+ */
+static TimerEvent_t TxNextPacketTimer;
+
+/*!
+ * Indicates if a new packet can be sent
+ */
+static bool NextTx = true;
+
+/*!
+ * Device states
+ */
+static enum eDevicState
+{
+    DEVICE_STATE_INIT,
+    DEVICE_STATE_JOIN,
+    DEVICE_STATE_SEND,
+    DEVICE_STATE_CYCLE,
+    DEVICE_STATE_SLEEP
+}DeviceState;
+
+/*!
+ * Strucure containing the Downlink status
+ */
+struct sLoRaMacDownlinkStatus
+{
+    int16_t Rssi;
+    int8_t Snr;
+    uint16_t DownlinkCounter;
+    bool RxData;
+    uint8_t Port;
+    uint8_t *Buffer;
+    uint8_t BufferSize;
+}LoRaMacDownlinkStatus;
+
+/*!
+ * Strucure containing the Uplink status
+ */
+struct sLoRaMacUplinkStatus
+{
+    uint8_t Acked;
+    int8_t Datarate;
+    uint16_t UplinkCounter;
+    uint8_t Port;
+    uint8_t *Buffer;
+    uint8_t BufferSize;
+}LoRaMacUplinkStatus;
+
+MibRequestConfirm_t mibReq;
+
+InterruptIn button(BUTTON3);
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+
+/*!
+ * Indicates if the MAC layer network join status has changed.
+ */
+static bool IsNetworkJoinedStatusUpdate = false;
+
+static void PrepareTxFrame( uint8_t port )
+{
+    switch( port )
+    {
+    case 15:
+    {}
+    default:
+        {
+            AppData[0] = 1;
+            if( IsTxConfirmed == true )
+            {
+                AppData[1] = LoRaMacDownlinkStatus.DownlinkCounter >> 8;
+                AppData[2] = LoRaMacDownlinkStatus.DownlinkCounter;
+                AppData[3] = LoRaMacDownlinkStatus.Rssi >> 8;
+                AppData[4] = LoRaMacDownlinkStatus.Rssi;
+                AppData[5] = LoRaMacDownlinkStatus.Snr;
+                
+                AppData[6] = 1;
+            }
+            else
+            {
+                AppData[1] = 1;
+            }
+        }
+        break;
+    }
+}
+
+/*!
+ * \brief   MCPS-Confirm event function
+ *
+ * \param   [IN] McpsConfirm - Pointer to the confirm structure,
+ *               containing confirm attributes.
+ */
+static void McpsConfirm( McpsConfirm_t *McpsConfirm )
+{
+    if( McpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
+    {
+        switch( McpsConfirm->McpsRequest )
+        {
+            case MCPS_UNCONFIRMED:
+            {
+                // Check Datarate
+                // Check TxPower
+                break;
+            }
+            case MCPS_CONFIRMED:
+            {
+                // Check Datarate
+                // Check TxPower
+                // Check AckReceived
+                // Check NbRetries
+                break;
+            }
+            case MCPS_PROPRIETARY:
+            {
+                break;
+            }
+            default:
+                break;
+        }
+    }
+    NextTx = true;
+}
+
+/*!
+ * \brief   MCPS-Indication event function
+ *
+ * \param   [IN] McpsIndication - Pointer to the indication structure,
+ *               containing indication attributes.
+ */
+static void McpsIndication( McpsIndication_t *McpsIndication )
+{
+    printf("Downstream message! \r\n");
+    if( McpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
+    {
+        printf("Something fishy %d  \r\n", McpsIndication->Status);
+        return;
+    }
+
+    switch( McpsIndication->McpsIndication )
+    {
+        case MCPS_UNCONFIRMED:
+        {
+            break;
+        }
+        case MCPS_CONFIRMED:
+        {
+            break;
+        }
+        case MCPS_PROPRIETARY:
+        {
+            break;
+        }
+        case MCPS_MULTICAST:
+        {
+            break;
+        }
+        default:
+            break;
+    }
+
+    // Check Multicast
+    // Check Port
+    // Check Datarate
+    // Check FramePending
+    // Check Buffer
+    // Check BufferSize
+    // Check Rssi
+    // Check Snr
+    // Check RxSlot
+
+    LoRaMacDownlinkStatus.Rssi = McpsIndication->Rssi;
+    if( McpsIndication->Snr & 0x80 ) // The SNR sign bit is 1
+    {
+        // Invert and divide by 4
+        LoRaMacDownlinkStatus.Snr = ( ( ~McpsIndication->Snr + 1 ) & 0xFF ) >> 2;
+        LoRaMacDownlinkStatus.Snr = -LoRaMacDownlinkStatus.Snr;
+    }
+    else
+    {
+        // Divide by 4
+        LoRaMacDownlinkStatus.Snr = ( McpsIndication->Snr & 0xFF ) >> 2;
+    }
+    LoRaMacDownlinkStatus.DownlinkCounter++;
+    LoRaMacDownlinkStatus.RxData = McpsIndication->RxData;
+    LoRaMacDownlinkStatus.Port = McpsIndication->Port;
+    LoRaMacDownlinkStatus.Buffer = McpsIndication->Buffer;
+    LoRaMacDownlinkStatus.BufferSize = McpsIndication->BufferSize;
+    
+    if( McpsIndication->RxData == true )
+    {
+        printf("Got a nice thingie! \r\n");
+        switch( McpsIndication->Port )
+        {
+        case 1:
+            printf("Logic for port1 %u\r\n", McpsIndication->Buffer[0]);
+            if( McpsIndication->BufferSize == 1 )
+            {
+                led1 = !McpsIndication->Buffer[0];
+            }
+            break;
+        case 2:
+            printf("Logic for port2 %u\r\n", McpsIndication->Buffer[0]);
+            if( McpsIndication->BufferSize == 1 )
+            {
+                led2 = !McpsIndication->Buffer[0];
+            }
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+/*!
+ * \brief   MLME-Confirm event function
+ *
+ * \param   [IN] MlmeConfirm - Pointer to the confirm structure,
+ *               containing confirm attributes.
+ */
+static void MlmeConfirm( MlmeConfirm_t *MlmeConfirm )
+{
+    if( MlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
+    {
+        switch( MlmeConfirm->MlmeRequest )
+        {
+            case MLME_JOIN:
+            {
+                printf("We joined! \r\n");
+                // Status is OK, node has joined the network
+                IsNetworkJoinedStatusUpdate = true;
+                break;
+            }
+            default:
+                break;
+        }
+    }
+    NextTx = true;
+}
+
+/*!
+ * \brief   Prepares the payload of the frame
+ *
+ * \retval  [0: frame could be send, 1: error]
+ */
+static bool SendFrame( void )
+{
+    printf("Sending!\r\n");
+    McpsReq_t mcpsReq;
+    LoRaMacTxInfo_t txInfo;
+    
+    if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
+    {
+        printf("Flush mac\r\n");
+        // Send empty frame in order to flush MAC commands
+        mcpsReq.Type = MCPS_UNCONFIRMED;
+        mcpsReq.Req.Unconfirmed.fBuffer = NULL;
+        mcpsReq.Req.Unconfirmed.fBufferSize = 0;
+        mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
+    }
+    else
+    {
+        if( IsTxConfirmed == false )
+        {
+            mcpsReq.Type = MCPS_UNCONFIRMED;
+            mcpsReq.Req.Unconfirmed.fPort = AppPort;
+            mcpsReq.Req.Unconfirmed.fBuffer = AppData;
+            mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize;
+            mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
+        }
+        else
+        {
+            mcpsReq.Type = MCPS_CONFIRMED;
+            mcpsReq.Req.Confirmed.fPort = AppPort;
+            mcpsReq.Req.Confirmed.fBuffer = AppData;
+            mcpsReq.Req.Confirmed.fBufferSize = AppDataSize;
+            mcpsReq.Req.Confirmed.NbTrials = 8;
+            mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
+        }
+    }
+    if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
+    {
+        return false;
+    }
+    
+    return true;
+}
+
+/*!
+ * \brief Function executed on TxNextPacket Timeout event
+ */
+static void OnTxNextPacketTimerEvent( void )
+{
+    LoRaMacStatus_t status;
+    status = LoRaMacMibGetRequestConfirm( &mibReq );
+
+    TimerStop( &TxNextPacketTimer );
+
+    if( status == LORAMAC_STATUS_OK )
+    {
+        if( mibReq.Param.IsNetworkJoined == true )
+        {
+            //DeviceState = DEVICE_STATE_SEND;
+            DeviceState = DEVICE_STATE_SLEEP;
+            NextTx = true;
+        }
+        else
+        {
+            DeviceState = DEVICE_STATE_JOIN;
+        }
+    }
+}
+
+void buttonPressedCallback(void)
+{
+    printf("Button pressed \r\n");
+    PrepareTxFrame( AppPort );
+    NextTx = SendFrame( );
+    printf("res: %d \r\n",NextTx);
+}
+
+int main( void )
+{
+    
+    button.fall(buttonPressedCallback);
+    
+    printf("Hello world! \r\n");
+    LoRaMacPrimitives_t LoRaMacPrimitives;
+    LoRaMacCallback_t LoRaMacCallbacks;
+    
+    BoardInit( );
+    
+    DeviceState = DEVICE_STATE_INIT;
+    
+    while( 1 )
+    {
+        if (DeviceState != DEVICE_STATE_SLEEP)
+            printf("State: %d \r\n", DeviceState);
+
+        if( IsNetworkJoinedStatusUpdate == true )
+        {
+            printf("Joined okay \r\n");
+            IsNetworkJoinedStatusUpdate = false;
+            mibReq.Type = MIB_NETWORK_JOINED;
+            LoRaMacMibGetRequestConfirm( &mibReq );
+        }
+        switch( DeviceState )
+        {
+            case DEVICE_STATE_INIT:
+            {
+                LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
+                LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
+                LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
+                LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
+                LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks );
+
+                TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
+                mibReq.Type = MIB_ADR;
+                mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                mibReq.Type = MIB_PUBLIC_NETWORK;
+                mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                LoRaMacTestSetDutyCycleOn( false );
+
+                DeviceState = DEVICE_STATE_JOIN;
+                break;
+            }
+            case DEVICE_STATE_JOIN:
+            {
+#if( OVER_THE_AIR_ACTIVATION != 0 )
+                MlmeReq_t mlmeReq;
+
+                mlmeReq.Type = MLME_JOIN;
+
+                mlmeReq.Req.Join.DevEui = DevEui;
+                mlmeReq.Req.Join.AppEui = AppEui;
+                mlmeReq.Req.Join.AppKey = AppKey;
+
+                if( NextTx == true )
+                {
+                    LoRaMacMlmeRequest( &mlmeReq );
+                }
+
+                // Schedule next packet transmission
+                TxDutyCycleTime = OVER_THE_AIR_ACTIVATION_DUTYCYCLE;
+                DeviceState = DEVICE_STATE_CYCLE;
+
+#else
+                mibReq.Type = MIB_NET_ID;
+                mibReq.Param.NetID = LORAWAN_NETWORK_ID;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                mibReq.Type = MIB_DEV_ADDR;
+                mibReq.Param.DevAddr = DevAddr;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                mibReq.Type = MIB_NWK_SKEY;
+                mibReq.Param.NwkSKey = NwkSKey;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                mibReq.Type = MIB_APP_SKEY;
+                mibReq.Param.AppSKey = AppSKey;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                mibReq.Type = MIB_NETWORK_JOINED;
+                mibReq.Param.IsNetworkJoined = true;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                DeviceState = DEVICE_STATE_SEND;
+#endif
+                IsNetworkJoinedStatusUpdate = true;
+                break;
+            }
+            case DEVICE_STATE_SEND:
+            {
+                if( NextTx == true )
+                {
+                    printf("Send a frame! \r\n");
+                    PrepareTxFrame( AppPort );
+
+                    NextTx = SendFrame( );
+
+                }
+
+                // Schedule next packet transmission
+                TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
+
+                DeviceState = DEVICE_STATE_CYCLE;
+                break;
+            }
+            case DEVICE_STATE_CYCLE:
+            {
+                // Schedule next packet transmission
+                printf("Do some cycling .. \r\n");
+                TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
+                TimerStart( &TxNextPacketTimer );
+
+                DeviceState = DEVICE_STATE_SLEEP;
+                break;
+            }
+            case DEVICE_STATE_SLEEP:
+            {
+                // Wake up through events
+                break;
+            }
+            default:
+            {
+                DeviceState = DEVICE_STATE_INIT;
+                break;
+            }
+        }
+    }
+}
\ No newline at end of file