/*!
* \file main.c
*
* \brief LoRaMac classA device implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*/
/*! \file classA/ASR6505/main.c */
#include <stdio.h>
#include <string.h>
#include "utilities.h"
#include "board.h"
#include "gpio.h"
#include "LoRaMac.h"
#include "LoRaMacClassD.h"
#include "LoRaMacCrypto.h"
#include "Commissioning.h"
#ifndef ACTIVE_REGION
#warning "No active region defined, LORAMAC_REGION_CN470 will be used as default."
#define ACTIVE_REGION LORAMAC_REGION_IN865
#endif
#ifdef CONFIG_D2D
#define D2D_PREAMBLE_TIME D2D_PREAMBLE_TIME_DEFAULT
#define D2D_FREQUENCY 503000000
#define D2D_DATARATE 5
#endif
#define LORAWAN_UNCONFIRMED_D2D_MSG 2
#define LORAWAN_CONFIRMED_MSG 1
#define LORAWAN_UNCONFIRMED_MSG 0
/*!
* Defines the application data transmission duty cycle. 5s, value in [ms].
*/
//#define APP_TX_DUTYCYCLE 5000
/*!
* Defines a random delay for application data transmission duty cycle. 1s,
* value in [ms].
*/
//#define APP_TX_DUTYCYCLE_RND 1000
/*!
* Default datarate
*/
#define LORAWAN_DEFAULT_DATARATE DR_0
/*!
* LoRaWAN confirmed messages
*/
#define LORAWAN_MSG_TYPE LORAWAN_CONFIRMED_MSG
/*!
* LoRaWAN Adaptive Data Rate
*
* \remark Please note that when ADR is enabled the end-device should be static
*/
#define LORAWAN_ADR_ON 1
#ifdef CONFIG_D2D
typedef enum LmhpRemoteMcastSetupMoteCmd_e
{
REMOTE_MCAST_SETUP_PKG_VERSION_ANS = 0x00,
REMOTE_MCAST_SETUP_MC_GROUP_STATUS_ANS = 0x01,
REMOTE_MCAST_SETUP_MC_GROUP_SETUP_ANS = 0x02,
REMOTE_MCAST_SETUP_MC_GROUP_DELETE_ANS = 0x03,
REMOTE_MCAST_SETUP_MC_GROUP_CLASS_C_SESSION_ANS = 0x04,
REMOTE_MCAST_SETUP_MC_GROUP_CLASS_B_SESSION_ANS = 0x05
}LmhpRemoteMcastSetupMoteCmd_t;
typedef enum LmhpRemoteMcastSetupSrvCmd_e
{
REMOTE_MCAST_SETUP_PKG_VERSION_REQ = 0x00,
REMOTE_MCAST_SETUP_MC_GROUP_STATUS_REQ = 0x01,
REMOTE_MCAST_SETUP_MC_GROUP_SETUP_REQ = 0x02,
REMOTE_MCAST_SETUP_MC_GROUP_DELETE_REQ = 0x03,
REMOTE_MCAST_SETUP_MC_GROUP_CLASS_C_SESSION_REQ = 0x04,
REMOTE_MCAST_SETUP_MC_GROUP_CLASS_B_SESSION_REQ = 0x05
}LmhpRemoteMcastSetupSrvCmd_t;
#endif
static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
#if( OVER_THE_AIR_ACTIVATION == 0 )
static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
static uint8_t AppSKey[] = LORAWAN_APPSKEY;
static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
#endif
extern RxConfigParams_t RxWindow1Config;
extern McpsIndication_t McpsIndication;
#ifdef CONFIG_D2D
static uint16_t preambletimtemp = 0;
static ClassDKey_t ClassDMCKeys[] = {
{LORAWAN_MC_KEY_0},
{LORAWAN_MC_KEY_1},
{LORAWAN_MC_KEY_2},
{LORAWAN_MC_KEY_3}
};
static MulticastParams_t ClassDMCChannels[] = {
{ LORAWAN_MC_ADDR_0, {0},{0},0, NULL },
{ LORAWAN_MC_ADDR_1, {0},{0},0, NULL },
{ LORAWAN_MC_ADDR_2, {0},{0},0, NULL },
{ LORAWAN_MC_ADDR_3, {0},{0},0, NULL },
};
#endif
uint32_t APP_TX_DUTYCYCLE = 30000; //28800000 ; // 8 hours
uint32_t Server_TDC = 0;
uint32_t APP_TX_DUTYCYCLE_RND = 1000;
uint32_t TxDutyCycleTime = 30000;
/*!
* Application port
*/
static uint8_t AppPort = LORAWAN_APP_PORT;
/*!
* User application data size
*/
static uint8_t AppDataSize = 4;
/*!
* User application data buffer size
*/
#define LORAWAN_APP_DATA_MAX_SIZE 16
/*!
* 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 TxMsgType = LORAWAN_MSG_TYPE;
/*!
* Defines the application data transmission duty cycle
*/
//static uint32_t TxDutyCycleTime = APP_TX_DUTYCYCLE;
/*!
* 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 eDeviceState
{
DEVICE_STATE_INIT,
DEVICE_STATE_JOIN,
DEVICE_STATE_SEND,
DEVICE_STATE_SEND_MAC,
DEVICE_STATE_CYCLE,
DEVICE_STATE_SLEEP
}DeviceState;
/*!
* \brief Prepares the payload of the frame
*/
static void PrepareTxFrame( uint8_t port )
{
AppDataSize = 4;
AppData[0] = 0x00;
AppData[1] = 0x01;
AppData[2] = 0x02;
AppData[3] = 0x03;
}
/*!
* \brief Prepares the payload of the frame
*
* \retval [0: frame could be send, 1: error]
*/
static bool SendFrame( void )
{
McpsReq_t mcpsReq;
LoRaMacTxInfo_t txInfo;
if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
{
// 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( TxMsgType == LORAWAN_UNCONFIRMED_MSG
#ifdef CONFIG_D2D
|| TxMsgType == LORAWAN_UNCONFIRMED_D2D_MSG
#endif
)
{
#ifdef CONFIG_D2D
if(TxMsgType == LORAWAN_UNCONFIRMED_D2D_MSG)
{
mcpsReq.Type = MCPS_UNCONFIRMED_D2D;
}
else
#endif
{
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;
}
#ifdef CONFIG_D2D
bool lwan_multicast_add(void * multicastInfo )
{
uint8_t i;
MibRequestConfirm_t mibset;
uint32_t address = ((MulticastParams_t *)multicastInfo)->Address;
for(i = 0; i < CLASSD_GROUP_ID_NUM; i++){
if( address == ClassDMCChannels[i].Address){
return false;
}
}
for(i = 0; i < CLASSD_GROUP_ID_NUM; i++){
if(ClassDMCChannels[i].Address == 0){
memcpy(&ClassDMCChannels[i], multicastInfo, sizeof(MulticastParams_t));
mibset.Type = MIB_MULTICAST_CHANNEL;
mibset.Param.MulticastList = &ClassDMCChannels[i];
if (LoRaMacMibSetRequestConfirm(&mibset) != LORAMAC_STATUS_OK) {
return false;
}
return true;
}
}
return false;
}
bool lwan_multicast_del(uint32_t address)
{
uint8_t i;
MibRequestConfirm_t mibset;
for(i = 0; i < CLASSD_GROUP_ID_NUM; i++){
if( address == ClassDMCChannels[i].Address){
ClassDMCChannels[i].Address = 0;
mibset.Type = MIB_MULTICAST_CHANNEL_DEL;
mibset.Param.MulticastList = &ClassDMCChannels[i];
if (LoRaMacMibSetRequestConfirm(&mibset) != LORAMAC_STATUS_OK) {
return false;
} else {
return true;
}
}
}
return false;
}
void on_remote_mcastgroup_setup(uint8_t * buffer, uint16_t size)
{
uint8_t cmdIndex = 0;
uint8_t dataBufferIndex = 0;
while( cmdIndex < size)
{
switch( buffer[cmdIndex++] )
{
case REMOTE_MCAST_SETUP_PKG_VERSION_REQ:
{
AppData[dataBufferIndex++] = REMOTE_MCAST_SETUP_PKG_VERSION_ANS;
AppData[dataBufferIndex++] = REMOTE_MCAST_SETUP_ID;
AppData[dataBufferIndex++] = REMOTE_MCAST_SETUP_VERSION;
printf("\r\n====REMOTE_MCAST_SETUP_PKG_VERSION_REQ.====\r\n");
break;
}
case REMOTE_MCAST_SETUP_MC_GROUP_STATUS_REQ:
{
uint8_t i;
uint32_t addr;
uint8_t reqGroupMask;
uint8_t nbGroup = 0;
uint8_t ansGroupMask = 0;
uint8_t statusIndex = 0;
uint8_t status = 0;
AppData[dataBufferIndex++] = REMOTE_MCAST_SETUP_MC_GROUP_STATUS_ANS;
statusIndex = dataBufferIndex;
AppData[dataBufferIndex++] = status;//init
reqGroupMask = buffer[cmdIndex++] & 0x0F;
for (i = 0; i < CLASSD_GROUP_ID_NUM; i++) {
if (ClassDMCChannels[i].Address) {
nbGroup++;
if (reqGroupMask & (1 << i))
{
ansGroupMask |= (1 << i);
addr = ClassDMCChannels[i].Address;
AppData[dataBufferIndex++] = i;
AppData[dataBufferIndex++] = ((uint8_t)(addr & 0xFF));
AppData[dataBufferIndex++] = ((uint8_t)(addr >> 8 & 0xFF));
AppData[dataBufferIndex++] = ((uint8_t)(addr >> 16 & 0xFF));
AppData[dataBufferIndex++] = ((uint8_t)(addr >> 24 & 0xFF));
}
}
}
status = ansGroupMask;
status |= ((nbGroup << 4) & 0xF0);
AppData[statusIndex] = status;//update
printf("\r\n====REMOTE_MCAST_SETUP_MC_GROUP_STATUS_REQ,reqGroupMask=%d,status=%d.====\r\n",reqGroupMask,status);
break;
}
case REMOTE_MCAST_SETUP_MC_GROUP_SETUP_REQ:
{
const uint8_t genappkey[]=LORAWAN_GENAPP_KEY;
uint8_t idError = 0x01; // One bit value
uint8_t id = buffer[cmdIndex++];
uint32_t address = 0;
bool enable_mcaddr = false;
address = ClassDMCChannels[id].Address;
if(id < CLASSD_GROUP_ID_NUM)
{
ClassDMCChannels[id].Address = ( buffer[cmdIndex++] << 0 ) & 0x000000FF;
ClassDMCChannels[id].Address += ( buffer[cmdIndex++] << 8 ) & 0x0000FF00;
ClassDMCChannels[id].Address += ( ((uint32_t)buffer[cmdIndex++]) << 16 ) & 0x00FF0000;
ClassDMCChannels[id].Address += ( ((uint32_t)buffer[cmdIndex++]) << 24 ) & 0xFF000000;
LoRaMacDecryptMCastKey(genappkey,&buffer[cmdIndex],ClassDMCKeys[id].key);
cmdIndex += 16;
//discard McFCountMin
//McFCountMin = ( mcpsIndication->Buffer[cmdIndex++] << 0 ) & 0x000000FF;
//McFCountMin += ( mcpsIndication->Buffer[cmdIndex++] << 8 ) & 0x0000FF00;
//McFCountMin += ( mcpsIndication->Buffer[cmdIndex++] << 16 ) & 0x00FF0000;
//McFCountMin += ( mcpsIndication->Buffer[cmdIndex++] << 24 ) & 0xFF000000;
//discard McFCountMax
//McFCountMax = ( mcpsIndication->Buffer[cmdIndex++] << 0 ) & 0x000000FF;
//McFCountMax += ( mcpsIndication->Buffer[cmdIndex++] << 8 ) & 0x0000FF00;
//McFCountMax += ( mcpsIndication->Buffer[cmdIndex++] << 16 ) & 0x00FF0000;
//McFCountMax += ( mcpsIndication->Buffer[cmdIndex++] << 24 ) & 0xFF000000;
LoRaMacD2DMcastComputeSKeys(ClassDMCKeys[id].key,ClassDMCChannels[id].Address,ClassDMCChannels[id].AppSKey,ClassDMCChannels[id].NwkSKey);
if(address == 0){
MibRequestConfirm_t mibset;
mibset.Type = MIB_MULTICAST_CHANNEL;
mibset.Param.MulticastList = &ClassDMCChannels[id];
if (LoRaMacMibSetRequestConfirm(&mibset) == LORAMAC_STATUS_OK) {
enable_mcaddr = true;
}
}else{
printf("WARNING!!!overwrite previous mcast group:%08x\r\n",(unsigned int)address);
enable_mcaddr = true;
}
if( enable_mcaddr == true )
{
idError = 0x00;
printf("setup mcast group :%08x\r\n",(unsigned int)address);
}
}
AppData[dataBufferIndex++] = REMOTE_MCAST_SETUP_MC_GROUP_SETUP_ANS;
AppData[dataBufferIndex++] = ( idError << 2 ) | id;
printf("\r\n====REMOTE_MCAST_SETUP_MC_GROUP_SETUP_REQ====\r\n");
break;
}
case REMOTE_MCAST_SETUP_MC_GROUP_DELETE_REQ:
{
uint8_t status = 0x00;
uint8_t id = buffer[cmdIndex++] & 0x03;
uint32_t address = 0;
status = id;
address = ClassDMCChannels[id].Address;
AppData[dataBufferIndex++] = REMOTE_MCAST_SETUP_MC_GROUP_DELETE_ANS;
if(address == 0 || lwan_multicast_del( address ) != true )
{
status |= 0x04; // McGroupUndefined bit set
}
else
{
printf("delete mcast group :%08x\r\n",(unsigned int)address);
}
AppData[dataBufferIndex++] = status;
printf("\r\n====REMOTE_MCAST_SETUP_MC_GROUP_DELETE_REQ,GroupId=%d,status=%d.====\r\n",id,status);
break;
}
case REMOTE_MCAST_SETUP_MC_GROUP_CLASS_C_SESSION_REQ://not support yet
case REMOTE_MCAST_SETUP_MC_GROUP_CLASS_B_SESSION_REQ://not support yet
default:
{
printf("mcast command not support \r\n");
break;
}
}
}
if( dataBufferIndex != 0 )
{
// Answer commands
printf("\r\n====RemoteMcAns:Size=%d,0x%02X%02X====\r\n",dataBufferIndex,AppData[0],AppData[1]);
TxMsgType = LORAWAN_CONFIRMED_MSG;
AppPort = REMOTE_MCAST_SETUP_PORT;
AppDataSize = dataBufferIndex;
DeviceState = DEVICE_STATE_SEND;
}
}
void lwan_classd_mcchannel_setup(void)
{
uint32_t i ;
MibRequestConfirm_t mibset;
mibset.Type = MIB_MULTICAST_CHANNEL;
for( i = 0;i<sizeof(ClassDMCChannels)/sizeof(MulticastParams_t);i++){
if(ClassDMCChannels[i].Address){
LoRaMacD2DMcastComputeSKeys(ClassDMCKeys[i].key,ClassDMCChannels[i].Address,ClassDMCChannels[i].AppSKey,ClassDMCChannels[i].NwkSKey);
mibset.Param.MulticastList = &ClassDMCChannels[i];
if (LoRaMacMibSetRequestConfirm(&mibset) != LORAMAC_STATUS_OK) {
break;
}
}
}
}
#endif
/*!
* \brief Function executed on TxNextPacket Timeout event
*/
static void OnTxNextPacketTimerEvent( void )
{
MibRequestConfirm_t mibReq;
LoRaMacStatus_t status;
TimerStop( &TxNextPacketTimer );
mibReq.Type = MIB_NETWORK_JOINED;
status = LoRaMacMibGetRequestConfirm( &mibReq );
if( status == LORAMAC_STATUS_OK )
{
if( mibReq.Param.IsNetworkJoined == true )
{
DeviceState = DEVICE_STATE_SEND;
NextTx = true;
}
else
{
// Network not joined yet. Try to join again
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_JOIN;
mlmeReq.Req.Join.DevEui = DevEui;
mlmeReq.Req.Join.AppEui = AppEui;
mlmeReq.Req.Join.AppKey = AppKey;
mlmeReq.Req.Join.NbTrials = 48;
mlmeReq.Req.Join.Datarate = LORAWAN_DEFAULT_DATARATE;
if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK )
{
DeviceState = DEVICE_STATE_SLEEP;
}
else
{
DeviceState = DEVICE_STATE_CYCLE;
}
}
}
}
/*!
* \brief MCPS-Confirm event function
*
* \param [IN] mcpsConfirm - Pointer to the confirm structure,
* containing confirm attributes.
*/
static void mcps_confirm( 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 NbTrials
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 mcps_indication( McpsIndication_t *mcpsIndication )
{
int i=0;
if( mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
{
return;
}
printf( "receive data: rssi = %d, snr = %d, datarate = %d\r\n", mcpsIndication->Rssi, (int)mcpsIndication->Snr,
(int)mcpsIndication->RxDatarate);
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
if( mcpsIndication->FramePending == true )
{
// The server signals that it has pending data to be sent.
// We schedule an uplink as soon as possible to flush the server.
OnTxNextPacketTimerEvent( );
}
// Check Buffer
// Check BufferSize
// Check Rssi
// Check Snr
// Check RxSlot
if( mcpsIndication->RxData == true )
{
switch(mcpsIndication->Port)
{
#ifdef CONFIG_D2D
case REMOTE_MCAST_SETUP_PORT:{
on_remote_mcastgroup_setup(mcpsIndication->Buffer, mcpsIndication->BufferSize);
break;
}
#endif
default:
break;
}
}
if(mcpsIndication->BufferSize) {
printf("Received: ");
for(i=0; i<mcpsIndication->BufferSize; i++) {
printf("%x ", (void *)mcpsIndication->Buffer[i]);
//Receive_Buff_Size = (mcpsIndication->BufferSize);
//Receive_Buffer = mcpsIndication->Buffer[0];
}
printf("\r\n");
Server_TDC = mcpsIndication->Buffer[0]<<8 | mcpsIndication->Buffer[1];
if(Server_TDC != 0)
{
APP_TX_DUTYCYCLE = Server_TDC * 60000;
}
}
}
/*!
* \brief MLME-Confirm event function
*
* \param [IN] mlmeConfirm - Pointer to the confirm structure,
* containing confirm attributes.
*/
static void mlme_confirm( MlmeConfirm_t *mlmeConfirm )
{
switch( mlmeConfirm->MlmeRequest )
{
case MLME_JOIN:
{
if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
{
#ifdef CONFIG_D2D
MlmeReq_t mlmeReq;
MibRequestConfirm_t mibReq;
uint16_t preambletime = D2D_PREAMBLE_TIME;
#endif
printf("joined\r\n");
// Status is OK, node has joined the network
DeviceState = DEVICE_STATE_SEND;
#ifdef CONFIG_D2D
mibReq.Type = MIB_RXD_CHANNEL;
mibReq.Param.RxDChannel.Frequency = D2D_FREQUENCY;
mibReq.Param.RxDChannel.Datarate = D2D_DATARATE;
LoRaMacMibSetRequestConfirm(&mibReq);
if(preambletime != D2D_PREAMBLE_TIME_DEFAULT)
{
mlmeReq.Type = MLME_PREAMBLE_INFO;
mlmeReq.Req.PreambleInfo.Period.Value = D2D_PREAMBLE_TIME/100-1;
preambletimtemp = (D2D_PREAMBLE_TIME / 100 ) * 100;
}
else
{
mlmeReq.Type = MLME_DEVICE_TIME;
}
if (LoRaMacMlmeRequest(&mlmeReq) == LORAMAC_STATUS_OK)
{
DeviceState = DEVICE_STATE_SEND_MAC;
}
else
{
DeviceState = DEVICE_STATE_CYCLE;
}
#endif
}
else
{
MlmeReq_t mlmeReq;
printf("join failed\r\n");
// Join was not successful. Try to join again
mlmeReq.Type = MLME_JOIN;
mlmeReq.Req.Join.DevEui = DevEui;
mlmeReq.Req.Join.AppEui = AppEui;
mlmeReq.Req.Join.AppKey = AppKey;
mlmeReq.Req.Join.NbTrials = 48;
mlmeReq.Req.Join.Datarate = LORAWAN_DEFAULT_DATARATE;
if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK )
{
DeviceState = DEVICE_STATE_SLEEP;
}
else
{
DeviceState = DEVICE_STATE_CYCLE;
}
}
break;
}
case MLME_LINK_CHECK:
{
if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
{
// Check DemodMargin
// Check NbGateways
}
break;
}
#ifdef CONFIG_D2D
case MLME_DEVICE_TIME:
{
MibRequestConfirm_t mibReq;
if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
{
mibReq.Type = MIB_DEVICE_CLASS;
mibReq.Param.Class = CLASS_D;
LoRaMacMibSetRequestConfirm(&mibReq);
}
break;
}
case MLME_PREAMBLE_INFO: {
MibRequestConfirm_t mibReq;
if ( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) {
if(preambletimtemp){
mibReq.Type = MIB_PREAMBLE_TIME;
mibReq.Param.PreambleTime = preambletimtemp;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_DEVICE_CLASS;
mibReq.Param.Class = CLASS_D;
LoRaMacMibSetRequestConfirm(&mibReq);
}
}
else
{
mibReq.Type = MIB_DEVICE_CLASS;
mibReq.Param.Class = CLASS_A;
LoRaMacMibSetRequestConfirm(&mibReq);
}
preambletimtemp = 0;
break;
}
#endif
default:
break;
}
NextTx = true;
}
/*!
* \brief MLME-Indication event function
*
* \param [IN] mlmeIndication - Pointer to the indication structure.
*/
static void mlme_indication( MlmeIndication_t *mlmeIndication )
{
switch( mlmeIndication->MlmeIndication )
{
case MLME_SCHEDULE_UPLINK:
{// The MAC signals that we shall provide an uplink as soon as possible
OnTxNextPacketTimerEvent( );
break;
}
default:
break;
}
}
static void lwan_dev_params_update( void )
{
MibRequestConfirm_t mibReq;
uint16_t channelsMaskTemp[6];
channelsMaskTemp[0] = 0x00FF;
channelsMaskTemp[1] = 0x0000;
channelsMaskTemp[2] = 0x0000;
channelsMaskTemp[3] = 0x0000;
channelsMaskTemp[4] = 0x0000;
channelsMaskTemp[5] = 0x0000;
mibReq.Type = MIB_CHANNELS_DEFAULT_MASK;
mibReq.Param.ChannelsDefaultMask = channelsMaskTemp;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_CHANNELS_MASK;
mibReq.Param.ChannelsMask = channelsMaskTemp;
LoRaMacMibSetRequestConfirm(&mibReq);
}
/**
* Main application entry point.
*/
int main( void )
{
LoRaMacPrimitives_t LoRaMacPrimitives;
LoRaMacCallback_t LoRaMacCallbacks;
MibRequestConfirm_t mibReq;
BoardInitMcu( );
BoardInitPeriph( );
DeviceState = DEVICE_STATE_INIT;
printf("ClassA app start\r\n");
while( 1 )
{
switch( DeviceState )
{
case DEVICE_STATE_INIT:
{
LoRaMacPrimitives.MacMcpsConfirm = mcps_confirm;
LoRaMacPrimitives.MacMcpsIndication = mcps_indication;
LoRaMacPrimitives.MacMlmeConfirm = mlme_confirm;
LoRaMacPrimitives.MacMlmeIndication = mlme_indication;
LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, ACTIVE_REGION );
TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
#ifdef CONFIG_D2D
lwan_classd_mcchannel_setup();
#endif
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 );
lwan_dev_params_update();
DeviceState = DEVICE_STATE_JOIN;
break;
}
case DEVICE_STATE_JOIN:
{
#if( OVER_THE_AIR_ACTIVATION != 0 )
MlmeReq_t mlmeReq;
// Initialize LoRaMac device unique ID
//BoardGetUniqueId( DevEui );
mlmeReq.Type = MLME_JOIN;
mlmeReq.Req.Join.DevEui = DevEui;
mlmeReq.Req.Join.AppEui = AppEui;
mlmeReq.Req.Join.AppKey = AppKey;
mlmeReq.Req.Join.NbTrials = 48;
mlmeReq.Req.Join.Datarate = LORAWAN_DEFAULT_DATARATE;
if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK )
{
DeviceState = DEVICE_STATE_SLEEP;
}
else
{
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
break;
}
case DEVICE_STATE_SEND:
{
if( NextTx == true )
{
PrepareTxFrame( AppPort );
NextTx = SendFrame( );
}
// Schedule next packet transmission
TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( 0, APP_TX_DUTYCYCLE_RND );
DeviceState = DEVICE_STATE_CYCLE;
break;
}
case DEVICE_STATE_SEND_MAC: {
if (NextTx == true) {
AppDataSize = 0;
NextTx = SendFrame();
}
DeviceState = DEVICE_STATE_SLEEP;
break;
}
case DEVICE_STATE_CYCLE:
{
DeviceState = DEVICE_STATE_SLEEP;
// Schedule next packet transmission
TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
TimerStart( &TxNextPacketTimer );
break;
}
case DEVICE_STATE_SLEEP:
{
#ifdef CONFIG_D2D
if(LoRaMacClassDISCADDetecting() == false)
#endif
{
// Wake up through events
TimerLowPowerHandler( );
}
// Process Radio IRQ
Radio.IrqProcess( );
break;
}
default:
{
DeviceState = DEVICE_STATE_INIT;
break;
}
}
}
}