lora experiments
Dependencies: BLE_API LoRaWAN-lib SX1276Lib mbed nRF51822 HCSR04Lib
Fork of LoRa by
Diff: main.cpp
- Revision:
- 0:4c1fcbfcc7bf
- Child:
- 2:ce7cea075e95
--- /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