1
Dependencies: X_NUCLEO_IKS01A1 LoRaWAN-lib SX1276Lib mbed
Revision 0:42863a11464a, committed 2016-08-26
- Comitter:
- ubhat
- Date:
- Fri Aug 26 19:36:35 2016 +0000
- Child:
- 1:80c1daf19aa4
- Commit message:
- SX1276 Shield based Applications
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/Comissioning.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,78 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: End device comissioning parameters + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __LORA_COMISSIONING_H__ +#define __LORA_COMISSIONING_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 + +/*! + * Indicates if the end-device is to be connected to a private or public network + */ +#define LORAWAN_PUBLIC_NETWORK true + +#if( OVER_THE_AIR_ACTIVATION != 0 ) + +/*! + * Mote device IEEE OUI (big endian) + * \remark This is unique to a company or organization + */ +#define IEEE_OUI 0x00, 0x00, 0x00 + +/*! + * Mote device IEEE EUI (big endian) + * + * \remark In this application, if the last 4 bytes are all 0, then the 32 bit address is automatically generated using a pseudo random generator seeded with a value derived from BoardUniqueId value + * If provided by user, e.g. { IEEE_OUI, 0x00, 0x00, 0x00, 0xFF, 0x01 }, then this value is used by the application + */ +#define LORAWAN_DEVICE_EUI { IEEE_OUI, 0x00, 0x00, 0x00, 0x00, 0x00 } + +/*! + * Application IEEE EUI (big endian) + */ +#define LORAWAN_APPLICATION_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + +/*! + * AES encryption/decryption cipher application key + */ +#define LORAWAN_APPLICATION_KEY { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } + +#else + +/*! + * Device address on the network (big endian) + * + * \remark In this application, if the value is 0, then the address is automatically generated using a pseudo random generator seeded with a value derived from BoardUniqueId value + * If provided by user, e.g. 0x78563412, then this value is used by the application + */ +#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x0 + +/*! + * AES encryption/decryption cipher network session key + */ +#define LORAWAN_NWKSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + +/*! + * AES encryption/decryption cipher application session key + */ +#define LORAWAN_APPSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + +#endif + + +#endif // __LORA_COMISSIONING_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/Common.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,72 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Extern declaration of parameters defined in main.cpp + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include "Comissioning.h" +#include "board.h" + +/*! + * User application data buffer size + */ +#define LORAWAN_APP_DATA_MAX_SIZE 64 + +/*! + * Current network ID + */ +#define LORAWAN_NETWORK_ID ( uint32_t )0 + + +#if( OVER_THE_AIR_ACTIVATION != 0 ) +/*! + * Over the Air Activation + */ + +extern uint8_t DevEui[]; +extern uint8_t AppEui[]; +extern uint8_t AppKey[]; + +#else +/*! + * Activation by Personalization + */ + +extern uint8_t NwkSKey[]; +extern uint8_t AppSKey[]; +extern uint32_t DevAddr; + +#endif + +extern uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE]; // User application data size + +extern uint8_t AppPort; // Application port + +extern uint8_t AppDataSize; // Application size + +extern uint8_t IsTxConfirmed; // Indicates if the node is sending confirmed or unconfirmed messages + +extern bool IsTxIntUpdate; // Indicates if a new transmit interrupt can be set + +extern bool NextTx; // Indicates if a new packet can be sent + +extern bool IsNetworkJoinedStatusUpdate; // Indicates if the MAC layer network join status has changed. + +extern bool IsTxUpdate; // Indicates if the message sent + +extern bool IsRxUpdate; // Indicates if the message received in the RX window. + +extern TimerEvent_t TxNextPacketTimer; // Timer to handle the application data transmission duty cycle + +#endif // __COMMON_H__ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/ComplianceTest.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,117 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Compliance Test for LoRaWAN End-Device + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ + +#include "ComplianceTest.h" + + +void PrepareComplianceTestFrame( McpsIndication_t *McpsIndication ) +{ + uint8_t *pData; + + pData = &McpsIndication->Buffer[0]; + + if( ComplianceTest.Running == false ) + { + // Check compliance test enable command (i) + if( ( McpsIndication->BufferSize == 4 ) && + ( pData[0] == 0x01 ) && ( pData[1] == 0x01 ) && ( pData[2] == 0x01 ) && (pData[3] == 0x01 ) ) + { + AppPort = 224; + AppDataSize = 2; + ComplianceTest.DownLinkCounter = 0; + ComplianceTest.LinkCheck = false; + ComplianceTest.DemodMargin = 0; + ComplianceTest.NbGateways = 0; + ComplianceTest.Running = true; + ComplianceTest.State = 1; + } + } + else + { + ComplianceTest.State = pData[0]; + switch( ComplianceTest.State ) + { + case 0: // Check compliance test disable command (ii) + IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; + AppPort = LORAWAN_APP_PORT; + AppDataSize = LORAWAN_APP_DATA_SIZE; + ComplianceTest.DownLinkCounter = 0; + ComplianceTest.Running = false; + + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_ADR; + mibReq.Param.AdrEnable = LORAWAN_ADR_ON; + LoRaMacMibSetRequestConfirm( &mibReq ); + break; + case 1: // (iii, iv) + AppDataSize = 2; + break; + case 2: // Enable confirmed messages (v) + IsTxConfirmed = true; + ComplianceTest.State = 1; + break; + case 3: // Disable confirmed messages (vi) + IsTxConfirmed = false; + ComplianceTest.State = 1; + break; + case 4: // (vii) + AppDataSize = McpsIndication->BufferSize; + + AppData[0] = 4; + for( uint8_t i = 1; i < AppDataSize; i++ ) + { + AppData[i] = McpsIndication->Buffer[i] + 1; + } + break; + case 5: // (viii) + { + MlmeReq_t mlmeReq; + mlmeReq.Type = MLME_LINK_CHECK; + LoRaMacMlmeRequest( &mlmeReq ); + } + break; + default: + break; + } + } +} + +void RunComplianceTest( void ) +{ + if( ComplianceTest.LinkCheck == true ) + { + ComplianceTest.LinkCheck = false; + AppDataSize = 3; + AppData[0] = 5; + AppData[1] = ComplianceTest.DemodMargin; + AppData[2] = ComplianceTest.NbGateways; + ComplianceTest.State = 1; + } + else + { + switch( ComplianceTest.State ) + { + case 1: + AppDataSize = 2; + AppData[0] = ComplianceTest.DownLinkCounter >> 8; + AppData[1] = ComplianceTest.DownLinkCounter; + break; + + case 4: + ComplianceTest.State = 1; + break; + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/ComplianceTest.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,44 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Definition of parameters for Compliance Test + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __COMPLIANCE_H__ +#define __COMPLIANCE_H__ + +#include "mbed.h" +#include "Common.h" +#include "Config.h" +#include "LoRaMac.h" + +#define COMPLIANCE_TX_DUTYCYCLE 5000000 // 5sec + +struct ComplianceTest_s +{ + bool Running; + uint8_t State; + bool IsTxConfirmed; + uint8_t AppPort; + uint8_t AppDataSize; + uint8_t *AppDataBuffer; + uint16_t DownLinkCounter; + bool LinkCheck; + uint8_t DemodMargin; + uint8_t NbGateways; +}; + +extern ComplianceTest_s ComplianceTest; + +void PrepareComplianceTestFrame( McpsIndication_t *McpsIndication ); +void RunComplianceTest( void ); + +#endif // __COMPLIANCE_H__ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/Config.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,138 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: End device communication parameters + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ + +#ifndef __LORA_CONFIG_H__ +#define __LORA_CONFIG_H__ + +/*! + * Configure End-Device to use 8-channels corresponding to Block A + * Comment/Uncomment to disable/enable Hybrid mode + */ +#define USE_BAND_915_HYBRID + +#ifndef USE_BAND_915_HYBRID +/*! + * Configure End-Device to use 64-channels across to Block A thru Block H + */ +#define USE_BAND_915 + +#endif + +/*! + * Join requests trials periodicity. It is the time between RX1/RX2 and next TX + */ +#define OVER_THE_AIR_ACTIVATION_DUTYCYCLE 5000000 // value in us + +/*! + * Defines the application data transmission periodicity. It is the time between RX1/RX2 and next TX + */ +#define APP_TX_DUTYCYCLE 5000000 // value in us + +/*! + * LoRaWAN confirmed messages + * \remark 1 : Confirmed messages enabled. Must receive ACK from network server + 0 : Confirmed messages disabled. + */ +#define LORAWAN_CONFIRMED_MSG_ON 1 + +/*! + * LoRaWAN Adaptive Data Rate + * + * \remark Please note that when ADR is enabled the end-device uses default datarate of DR_0 + */ +#define LORAWAN_ADR_ON 0 + +/*! + * Default mote datarate + * \remark DR_0 : 980 bps; DR_1 : 1760 bps; DR_2 : 3125 bps; DR_3 : 5470 bps; DR_4 : 12500 bps + */ +#define LORAWAN_DEFAULT_DATARATE DR_0 + +/*! + * LoRaWAN application port + */ +#define LORAWAN_APP_PORT 5 + +/*! + * LoRaWAN User defined Tx Power + * + * \remark The Tx power level is set as TX_POWER_P_DBM, where 10 <= P <= 30 and P is even value { i.e. P = 10, 12, 14 ... 28 or 30 } + */ +#define LORAWAN_TX_POWER TX_POWER_20_DBM + +#if ( LORAWAN_APP_PORT == 5 ) +/*==================================================== + US01 GPS APPLICATION DEMO (PORT 5) +====================================================*/ + +/*! + * User application data buffer size + */ +#define LORAWAN_APP_DATA_SIZE 11 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#elif ( LORAWAN_APP_PORT == 6 ) +/*==================================================== + SENET M2X DEMO (PORT 6) +====================================================*/ + +/*! + * User application data buffer size + */ +#define LORAWAN_APP_DATA_SIZE 2 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#elif ( LORAWAN_APP_PORT == 7 ) +/*==================================================== + SENET GPS DEMO (PORT 7) +====================================================*/ + +/*! + * User application data buffer size + */ +#define LORAWAN_APP_DATA_SIZE 11 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#elif ( LORAWAN_APP_PORT == 11 ) +/*==================================================== + PUSH BUTTON DEMO (PORT 11) +====================================================*/ + +/*! + * User application data buffer size + */ +#define LORAWAN_APP_DATA_SIZE 2 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#elif ( LORAWAN_APP_PORT == 12 ) +/*==================================================== + TRANSMIT ON VERTICAL ORIENTATION DEMO (PORT 12) +====================================================*/ + +/*! + * User application data buffer size + */ +#define LORAWAN_APP_DATA_SIZE 2 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +#endif + +#endif // __LORA_CONFIG_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/LoRaApp.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,404 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: User-defined applications such as GPS, Temp, Accelerometer, LED indications etc. + Event based actions such as LED blink on Tx, LED toggle on downlink etc + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ + +#include "LoRaApp.h" + +bool VerticalStatus = false; + + +Application::Application( uint8_t * memptr ) +{ + BuffAddr = memptr; + memset( BuffAddr, 0, LORAWAN_APP_DATA_MAX_SIZE ); + BuffPtr = 0; +} + +Application::~Application( ) +{ +} + +void Application::ApplicationAppendData( uint8_t *pData, uint8_t len ) +{ + memcpy( BuffAddr + BuffPtr, pData, len ); + BuffPtr += len; +} + +void Application::ApplicationPtrPos( uint8_t ptrPos ) +{ + BuffPtr = ptrPos; +} + +void Application::ApplicationCall( eAppType App ) +{ + switch( App ) + { + // Appends 8 Bytes (3 bytes longitude, 3 bytes latitude, 2 bytes altitude) to TX buffer + case AppGps: + { + /* + Gps.service( ); + + uint16_t altitudeGps = atoi( Gps.NmeaGpsData.NmeaAltitude ); + + if( ( BuffPtr + 8 ) <= LORAWAN_APP_DATA_SIZE ) + { + BuffAddr[BuffPtr++] = ( Gps.LatitudeBinary >> 16 ) & 0xFF; + BuffAddr[BuffPtr++] = ( Gps.LatitudeBinary >> 8 ) & 0xFF; + BuffAddr[BuffPtr++] = Gps.LatitudeBinary & 0xFF; + BuffAddr[BuffPtr++] = ( Gps.LongitudeBinary >> 16 ) & 0xFF; + BuffAddr[BuffPtr++] = ( Gps.LongitudeBinary >> 8 ) & 0xFF; + BuffAddr[BuffPtr++] = Gps.LongitudeBinary & 0xFF; + BuffAddr[BuffPtr++] = ( altitudeGps >> 8 ) & 0xFF; + BuffAddr[BuffPtr++] = altitudeGps & 0xFF; + } + */ + break; + } + + // Appends 1 Byte to TX buffer + case AppTemp: + { + /* + Mpl3115a2.ReadTemperature( ); + if( ( BuffPtr + 1 ) <= LORAWAN_APP_DATA_SIZE ) + { + BuffAddr[BuffPtr++] = ( int32_t )Mpl3115a2.Temperature; // Signed degrees Celcius in half degree units. So, +/-63 °C + } + */ + break; + } + + // Appends 1 Byte to TX buffer + case AppBat: + { + if( ( BuffPtr + 1 ) <= LORAWAN_APP_DATA_SIZE ) + { + BuffAddr[BuffPtr++] = BoardGetBatteryLevel( ); // Per LoRaWAN spec; 0 = Charging; 1...254 = level, 255 = N/A + } + break; + } + + // Appends incremental values of 1 Byte each to TX buffer until Full + case AppRamp: + { + int32_t i, j; + + // Populate Tx Buffer with increasing byte values starting from 0x00, 0x01, 0x02 ... + for( i = BuffPtr, j = 0; i < LORAWAN_APP_DATA_SIZE; i++ ) + { + BuffAddr[i] = j++; + } + BuffPtr = LORAWAN_APP_DATA_SIZE; + break; + } + + // Appends 2 Bytes to TX buffer + case AppAccl: + { + /* + uint8_t statusReg; + + // Read the PS_STATUS register + statusReg = Mma8451q.read_single( MMA8451_PL_STATUS ); + + // Display Orientation of NAMote on Serial Port + SerialAcclMetrDisplay( statusReg ); + + // If Orientation of the Mote changed then let Green LED ON + if( ( statusReg & 0x80 ) != 0 ) + { + AppLed = 1; + CtrlLED( Green, LED_ON ); + } + + // Read and populate device orientation in Tx Buffer + if( ( BuffPtr + 2 ) <= LORAWAN_APP_DATA_SIZE ) + { + if( statusReg & 0x40 ) + { + if( statusReg & 0x01 ) + { + BuffAddr[BuffPtr++] = 0x66; // horizontal + faceup + } + else + { + BuffAddr[BuffPtr++] = 0x99; // horizontal + facedown + } + + BuffAddr[BuffPtr++] = 0; // vertical = false + } + else + { + BuffAddr[BuffPtr++] = 0; // horizontal = false + BuffAddr[BuffPtr++] = 0x11; // vertical = true + } + } + */ + break; + } + + case AppAcclSenet: + { + /* + uint8_t statusReg; + + // Read the PS_STATUS register + statusReg = Mma8451q.read_single( MMA8451_PL_STATUS ); + + // Display Orientation of NAMote on Serial Port + SerialAcclMetrDisplay( statusReg ); + + // If Orientation of the Mote changed then populate Upper Nibble of 0th Byte of Tx Buffer + if( ( statusReg & 0x40 ) != 0 ) + { + AppLed = 0; + CtrlLED( Green, LED_OFF ); + BuffAddr[BuffPtr++] = 0; // horizontal + } + else + { + AppLed = 1; + CtrlLED( Green, LED_ON ); + BuffAddr[BuffPtr++] = 10; // vertical + } + */ + break; + } + + case AppPushButton: + { + uint16_t PushButtonCnt; + uint8_t *p = (uint8_t *) &PushButtonCnt; + + PushButtonCnt = LoRaMacUplinkStatus.UplinkCounter; + + memcpy( &BuffAddr[BuffPtr], p, sizeof(uint16_t) ); + + break; + } + + default: + { + break; + } + } +} + +/* +static void OnRedLedTimerEvent( void ) +{ + TimerStop( &RedLedTimer.LedTimer ); + + if( RedLed == LED_OFF ) + { + RedLed = LED_ON; + } + else + { + RedLed = LED_OFF; + } +} + +static void OnYellowLedTimerEvent( void ) +{ + TimerStop( &YellowLedTimer.LedTimer ); + + if( YellowLed == LED_OFF ) + { + YellowLed = LED_ON; + } + else + { + YellowLed = LED_OFF; + } +} + +static void OnGreenLedTimerEvent( void ) +{ + TimerStop( &GreenLedTimer.LedTimer ); + + if( GreenLed == LED_OFF ) + { + GreenLed = LED_ON; + } + else + { + GreenLed = LED_OFF; + } +} + +TimerLed::TimerLed( eLedType led ) +{ + switch( led ) + { + case Red: + { + TimerInit( &LedTimer, OnRedLedTimerEvent ); + break; + } + + case Yellow: + { + TimerInit( &LedTimer, OnYellowLedTimerEvent ); + break; + } + + case Green: + { + TimerInit( &LedTimer, OnGreenLedTimerEvent ); + break; + } + } + +} + +TimerLed::~TimerLed( ) +{ +} + +void BlinkLED( eLedType led, uint32_t time ) +{ + switch( led ) + { + case Red: + { + TimerSetValue( &RedLedTimer.LedTimer, time ); + TimerStart( &RedLedTimer.LedTimer ); + RedLed = LED_ON; + break; + } + + case Yellow: + { + TimerSetValue( &YellowLedTimer.LedTimer, time ); + TimerStart( &YellowLedTimer.LedTimer ); + YellowLed = LED_ON; + break; + } + + case Green: + { + TimerSetValue( &GreenLedTimer.LedTimer, time ); + TimerStart( &GreenLedTimer.LedTimer ); + GreenLed = LED_ON; + break; + } + } +} + +void ToggleLED( eLedType led ) +{ + switch( led ) + { + case Red: + { + if( RedLed == LED_OFF ) + { + RedLed = LED_ON; + } + else + { + RedLed = LED_OFF; + } + break; + } + + case Yellow: + { + if( YellowLed == LED_OFF ) + { + YellowLed = LED_ON; + } + else + { + YellowLed = LED_OFF; + } + break; + } + + case Green: + { + if( GreenLed == LED_OFF ) + { + GreenLed = LED_ON; + } + else + { + GreenLed = LED_OFF; + } + break; + } + } +} + +void CtrlLED( eLedType led, uint8_t state ) +{ + switch( led ) + { + case Red: + { + RedLed = state; + break; + } + + case Yellow: + { + YellowLed = state; + break; + } + + case Green: + { + GreenLed = state; + break; + } + + case Usr: + { + if( state ) + { + UsrLed = LED_ON; + } + else + { + UsrLed = LED_OFF; + } + break; + } + } +} +*/ +void CheckOrientation( void ) +{ + /* + uint8_t statusReg; + + // Read the PS_STATUS register + statusReg = Mma8451q.read_single( MMA8451_PL_STATUS ); + + // If Orientation of the Mote changed then populate Upper Nibble of 0th Byte of Tx Buffer + if( ( statusReg & 0x40 ) != 0 ) + { + CtrlLED( Green, LED_OFF ); + VerticalStatus = false; // horizontal + } + else + { + CtrlLED( Green, LED_ON ); + VerticalStatus = true; // vertical + } + */ +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/LoRaApp.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,151 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: User-defined applications such as GPS, Temp, Accelerometer, LED indications etc. + Event based actions such as LED blink on Tx, LED toggle on downlink etc + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ + +#ifndef __APPLICATION_H__ +#define __APPLICATION_H__ + +#include "board.h" +#include "Common.h" +#include "SerialDisplay.h" + +/*! + * LED ON/OFF definition + */ +#define LED_ON 0 +#define LED_OFF 1 + +/*! + * LED types + */ +enum eLedType +{ + Red = 0,// Red LED + Yellow = 1, // Yellow LED + Green = 2, // Green LED + Usr = 3, // USR LED +}; + +/*! + * user-defined Application names + */ +enum eAppType +{ + AppGps = 0, // GPS application + AppTemp = 1, // Temperature measurement application + AppBat = 2, // Battery measurement application + AppRamp = 3, // Generate Ramp bytes + AppAccl = 4, // Accelerometer application + AppAcclSenet = 5, // Senet + M2X application example + AppPushButton = 6, // Push button application example +}; + +/*! + * Application + */ +class Application +{ +public: + /*! + * \brief Initializes TX buffer address to private pointer + * + * \param [IN] memptr pointer to TX buffer + */ + Application( uint8_t * memptr ); + + /*! + * \brief Application Destructor + */ + ~Application( ); + + /*! + * \brief Call application type and append to application buffer + * + * \param [IN] AppType application type: GPS, Battery, Temp etc. + */ + void ApplicationCall( eAppType AppType ); + + /*! + * \brief Append data to the TX buffer + * + * \param [IN] pData pointer to the data to be appended to TX buffer + * \param [IN] Len lenght of the data to be appended to TX buffer + */ + void ApplicationAppendData( uint8_t *pData, uint8_t len ); + + /*! + * \brief Point the pointer corresponding to the TX buffer to specified index + * + * \param [IN] ptrPos index to where to point to in the TX buffer + */ + void ApplicationPtrPos( uint8_t ptrPos ); + +private: + /*! + * Index to the application buffer + */ + uint8_t BuffPtr; + /*! + * Application buffer address pointer + */ + uint8_t *BuffAddr; +}; + +class TimerLed +{ +public: + TimerEvent_t LedTimer; + TimerLed( eLedType ); + ~TimerLed( ); +}; + +extern TimerLed RedLedTimer; + +extern TimerLed YellowLedTimer; + +extern TimerLed GreenLedTimer; + +extern Application LoRaApp; + +extern bool AppLed; + +extern bool VerticalStatus; + +/*! +* \brief Blink LED +* +* \param [IN] led Red, yellow or green LED +* \param [IN] time time in usec for which the LED must be ON + */ +void BlinkLED( eLedType led, uint32_t time ); + +/*! +* \brief Turn LED ON if OFF; OFF if ON +* +* \param [IN] led Red, yellow or green LED +*/ +void ToggleLED( eLedType led ); + +/*! +* \brief Control the State of the LED +* +* \param [IN] led Red, yellow or green LED +* \param [IN] state ON or OFF +*/ +void CtrlLED( eLedType led, uint8_t state ); + +void CheckOrientation( void ); + +#endif // __APPLICATION_H__ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/LoRaDeviceStateProc.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,225 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Process function calls from various Device states + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ + +#include "LoRaDeviceStateProc.h" +#include "LoRaMacLayerService.h" + +eDevicState DeviceState; + +sLoRaMacUplinkStatus LoRaMacUplinkStatus; + +sLoRaMacDownlinkStatus LoRaMacDownlinkStatus; + +LoRaMacPrimitives_t LoRaPrimitives; + +LoRaMacCallback_t LoRaCallbacks; + +MibRequestConfirm_t LoRaMibReq; + +MlmeReq_t mlmeReq; + + +/*! + * \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; + } + else + { + DeviceState = DEVICE_STATE_JOIN; + } + NextTx = true; + } +} + +void DeviceInit( void ) +{ + LoRaPrimitives.MacMcpsConfirm = McpsConfirm; + LoRaPrimitives.MacMcpsIndication = McpsIndication; + LoRaPrimitives.MacMlmeConfirm = MlmeConfirm; + LoRaCallbacks.GetBatteryLevel = BoardGetBatteryLevel; + LoRaMacInitialization( &LoRaPrimitives, &LoRaCallbacks ); + + TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent ); + + LoRaMibReq.Type = MIB_ADR; + LoRaMibReq.Param.AdrEnable = LORAWAN_ADR_ON; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_PUBLIC_NETWORK; + LoRaMibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_CHANNELS_TX_POWER; + LoRaMibReq.Param.ChannelsTxPower = LORAWAN_TX_POWER; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMacDownlinkStatus.DownlinkCounter = 0; +} + +void DeviceJoinUpdate( void ) +{ + LoRaMibReq.Type = MIB_NETWORK_JOINED; + LoRaMacMibGetRequestConfirm( &LoRaMibReq ); +} + +void DeviceJoin( void ) +{ +#if( OVER_THE_AIR_ACTIVATION != 0 ) + + mlmeReq.Type = MLME_JOIN; + + mlmeReq.Req.Join.DevEui = DevEui; + mlmeReq.Req.Join.AppEui = AppEui; + mlmeReq.Req.Join.AppKey = AppKey; + + if( NextTx == true ) + { + LoRaMacMlmeRequest( &mlmeReq ); + } + +#else + // Choose a random device address if not already defined in Config.h + if( DevAddr == 0 ) + { + // Random seed initialization + srand1( BoardGetRandomSeed( ) ); + DevAddr = randr( 0, 0x01FFFFFF ); + } + + LoRaMibReq.Type = MIB_NET_ID; + LoRaMibReq.Param.NetID = LORAWAN_NETWORK_ID; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_DEV_ADDR; + LoRaMibReq.Param.DevAddr = DevAddr; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_NWK_SKEY; + LoRaMibReq.Param.NwkSKey = NwkSKey; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_APP_SKEY; + LoRaMibReq.Param.AppSKey = AppSKey; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_NETWORK_JOINED; + LoRaMibReq.Param.IsNetworkJoined = true; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + +#endif +} + +/*! + * \brief Prepares the payload of the frame + */ +void PrepareTxFrame( uint8_t port ) +{ + MibRequestConfirm_t mibReq; + + if( BoardGetBatteryLevel( ) < LOW_BAT_THRESHOLD ) + { + mibReq.Type = MIB_CHANNELS_TX_POWER; + LoRaMacMibGetRequestConfirm( &mibReq ); + // TX_POWER_30_DBM = 0, TX_POWER_28_DBM = 1, ..., TX_POWER_20_DBM = 5, ..., TX_POWER_10_DBM = 10 + // The if condition is then "less than" to check if the power is greater than 20 dBm + if( mibReq.Param.ChannelsTxPower < TX_POWER_20_DBM ) + { + mibReq.Param.ChannelsTxPower = TX_POWER_20_DBM; + LoRaMacMibSetRequestConfirm( &mibReq ); + } + } + + if( port == 224 ) + { + RunComplianceTest( ); + } + else + { + PrepareLoRaFrame( port ); + } +} + +/*! + * \brief Prepares the payload of the frame + * + * \retval [0: frame could be send, 1: error] + */ +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; + + LoRaMacUplinkStatus.Acked = false; + LoRaMacUplinkStatus.Port = 0; + LoRaMacUplinkStatus.Buffer = NULL; + LoRaMacUplinkStatus.BufferSize = 0; + } + else + { + LoRaMacUplinkStatus.Acked = false; + LoRaMacUplinkStatus.Port = AppPort; + LoRaMacUplinkStatus.Buffer = AppData; + LoRaMacUplinkStatus.BufferSize = AppDataSize; + + if( ( IsTxConfirmed == false ) || ( LoRaMacUplinkStatus.UplinkCounter == 0 ) ) + { + 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; + } + } + + LoRaMacUplinkStatus.Type = mcpsReq.Type; + + if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK ) + { + return false; + } + return true; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/LoRaDeviceStateProc.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,105 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Process function calls from various Device states + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ +#ifndef __LORA_DEVICE_STATE_H__ +#define __LORA_DEVICE_STATE_H__ + +#include "Common.h" +#include "board.h" +#include "LoRaMac.h" +#include "LoRaEventProc.h" +#include "SerialDisplay.h" +#include "mbed.h" +#include "LoRaMacLayerService.h" + +/*! + * Strucure containing the Uplink status + */ +struct sLoRaMacUplinkStatus +{ + /*! + * MCPS-Request type + */ + Mcps_t Type; + uint8_t Acked; + int8_t Datarate; + uint16_t UplinkCounter; + uint8_t Port; + uint8_t *Buffer; + uint8_t BufferSize; + int8_t TxPower; +}; + +/*! + * 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; + uint8_t RxSlot; +}; + +/*! + * Device states + */ +enum eDevicState +{ + DEVICE_STATE_INIT, + DEVICE_STATE_JOIN, + DEVICE_STATE_SEND, + DEVICE_STATE_SLEEP +}; + +extern sLoRaMacUplinkStatus LoRaMacUplinkStatus; + +extern sLoRaMacDownlinkStatus LoRaMacDownlinkStatus; + +extern eDevicState DeviceState; + +/*! + * \brief Initialize Device: Timer, MAC Services, MAC + */ +void DeviceInit( void ); + +/*! + * \brief Device Join update + */ +void DeviceJoinUpdate( void ); + +/*! + * \brief OTA: if device not joined, send JOIN REQUEST to network + * ABP: Request DevAddr if not already set + */ +void DeviceJoin( void ); + +/*! + * \brief Prepares the payload of the frame to be transmitted + * + * \param [IN] port application port corresponding to which payload is generated + */ +void PrepareTxFrame( uint8_t port ); + +/*! + * \brief Send the frame + * + */ +bool SendFrame( void ); + +#endif // __LORA_DEVICE_STATE_H__ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/LoRaEventProc.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,312 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Define events during Join, Tx & Rx + Prepare TX packet by appending with appropriate application data + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ + +#include "LoRaEventProc.h" + +/*! + * Defines the application data transmission duty cycle + */ +uint32_t TxDutyCycleTime = APP_TX_DUTYCYCLE; + +bool AppLed = 0; + +/*! + * \brief Prepares the payload of the frame based on application port + */ +void PrepareLoRaFrame( uint8_t port ) +{ + + switch( port ) + { + case 5: + { + uint8_t tmp; + uint8_t tmpLength; + uint8_t ptrIndex = 0; + + // Point the pointer to position index of Tx Buffer + LoRaApp.ApplicationPtrPos( ptrIndex ); + + tmp = ( AppLed != 0 ) ? 0x0F : 0x00; + tmpLength = 1; + + LoRaApp.ApplicationAppendData( &tmp, tmpLength ); // Populate lower nibble of 0th Byte with LED state + + /*! + * Read Temperature + * Appends 1 Byte to TX buffer + */ + LoRaApp.ApplicationCall( AppTemp ); + + /*! + * Read Battery + * Appends 1 Byte to TX buffer + */ + LoRaApp.ApplicationCall( AppBat ); + + /*! + * Read GPS coordinates + * Appends 8 Bytes (3 bytes longitude, 3 bytes latitude, 2 bytes altitude) to TX buffer + */ + LoRaApp.ApplicationCall( AppGps ); + + /*! + * Read Accelerometer + * Appends 2 Bytes to TX buffer + * Value Orientation + * 0x99 0x00 horizontal + faceup + * 0x66 0x00 horizontal + facedown + * 0x00 0x11 vertical + */ + LoRaApp.ApplicationCall( AppAccl ); // Generate Accelerometer data bytes + + /*! + * Generate Ramp data bytes + * Appends incremental values of 1 Byte each to TX buffer until Full + */ + LoRaApp.ApplicationCall( AppRamp ); + + break; + } + + // Senet M2X ORIENTATION Demo + // Set LORAWAN_APP_DATA_SIZE to 2 + case 6: + { + uint8_t ptrIndex = 1; + + //Point the pointer to position index of Tx Buffer + LoRaApp.ApplicationPtrPos( ptrIndex ); + + LoRaApp.ApplicationCall( AppAcclSenet ); // Generate Accelerometer data bytes + + + + break; + } + + /* Senet GPS Demo + Data Format (in Hex): + [01, 02, Lattitude (3 bytes), Longitude (3 Bytes), Elevation (2 bytes), Tx Power (1 byte)] + */ + case 7: + { + uint8_t ptrIndex = 0; + uint8_t tmp[] = {0x01, 0x02}; + + //Point the pointer to position index of Tx Buffer + LoRaApp.ApplicationPtrPos( ptrIndex ); + + LoRaApp.ApplicationAppendData( tmp, 2 ); + + LoRaApp.ApplicationCall( AppGps ); // Generate Accelerometer data bytes + + uint8_t pow = 30 - 2*(( uint8_t ) LoRaMacUplinkStatus.TxPower); + LoRaApp.ApplicationAppendData( &pow, 1 ); + + break; + } + + // Push-Button Demo + case 11: + { + uint8_t ptrIndex = 0; + + //Point the pointer to position index of Tx Buffer + LoRaApp.ApplicationPtrPos( ptrIndex ); + + LoRaApp.ApplicationCall( AppPushButton ); // Transmit uplink counter + + break; + } + + // Transmit on Vertical Orientation Demo + case 12: + { + uint8_t ptrIndex = 0; + + //Point the pointer to position index of Tx Buffer + LoRaApp.ApplicationPtrPos( ptrIndex ); + + LoRaApp.ApplicationCall( AppPushButton ); // Transmit uplink counter + + break; + } + + default: + break; + } +} + + +/*! + * \brief Sets Interrupt for next payload transmission + */ +void InitNextTxInterrupt( uint8_t port ) +{ + switch( port ) + { + /* GPS Application Demo + Set Timer interrupt for next uplink + */ + case 5: + { + } + + /* Senet + M2X demo + Set Timer interrupt for next uplink + */ + case 6: + { + + } + + /* Senet GPS Demo + Set Timer interrupt for next uplink + */ + case 7: + { + // Schedule next packet transmission + TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); + TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime ); + TimerStart( &TxNextPacketTimer ); + break; + } + + /* Push Button Demo + Send Packet Immedietly if PC0 = GND + */ + case 11: + { + /* + volatile bool PushButtonStatus; + + PushButtonStatus = PC0; + + if(PushButtonStatus == 0) + { + // Send Pkt immedietly if PC = GND + DeviceState = DEVICE_STATE_SEND; + NextTx = true; + } + else + { + // Keep polling + IsTxIntUpdate = true; + } + */ + break; + } + + /* Orientation Demo + Send Packet Immedietly if Mote is Vertical + */ + case 12: + { + CheckOrientation( ); + + if(VerticalStatus == true) + { + // Send Pkt immedietly if PC = GND + DeviceState = DEVICE_STATE_SEND; + NextTx = true; + } + else + { + // Keep polling + IsTxIntUpdate = true; + } + break; + } + + /* Compliance Test + Set Timer interrupt for next uplink + */ + case 224: + { + // Schedule next packet transmission + TimerSetValue( &TxNextPacketTimer, COMPLIANCE_TX_DUTYCYCLE ); + TimerStart( &TxNextPacketTimer ); + break; + } + + default: + { + // Schedule next packet transmission + TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime ); + TimerStart( &TxNextPacketTimer ); + break; + } + } + +} + +/*! + * \brief What to do during JOIN process ? blink/toggle LED etc. + */ +void JoinEvent( void ) +{ + // CtrlLED is defined in LoRaBoardAppIf.h + // param 1: LED color (Red, Yellow or Green) + // param 2: LED_ON or LED_OFF + //CtrlLED( Red, LED_ON ); +} + + +/*! + * \brief What to do during TX ? blink/toggle LED etc. + */ +void TxEvent( void ) +{ + int blinkTime = 25000; + + // Blink Red LED for 25msec + //BlinkLED( Red, blinkTime ); +} + +void RxEvent() +{ + // Toggle yellow LED + //ToggleLED( Yellow ); + + // If Rx Data is 0x01 turn on Green LED else if 0x0 Turn Green LED off + if( LoRaMacDownlinkStatus.BufferSize == 1 ) + { + if( LoRaMacDownlinkStatus.Buffer[0] == 0x01 ) + { + AppLed = 1; + } + else + { + if( LoRaMacDownlinkStatus.Buffer[0] == 0x00 ) + { + AppLed = 0; + } + } + } + + if( AppLed != 0 ) + { + // Turn USR_LED ON + //CtrlLED( Usr, LED_ON ); + } + else + { + // Turn USR_LED OFF + //CtrlLED( Usr, LED_OFF ); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/LoRaEventProc.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,53 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Define events during Join, Tx & Rx + Prepare TX packet by appending with appropriate application data + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ + +#ifndef __LORA_EVENT_PROC_H__ +#define __LORA_EVENT_PROC_H__ + +#include "board.h" +#include "LoRaApp.h" +#include "LoRaDeviceStateProc.h" + +#define APP_TX_DUTYCYCLE_RND 1000000 + +/*! + * \brief Prepares the payload of the frame specific to the application port + * + * \param [IN] port application port + */ +void PrepareLoRaFrame( uint8_t port ); + +/*! + * \brief Prepares the payload of the frame based on application port + */ +void InitNextTxInterrupt( uint8_t port ); + +/*! + * \brief Define action during the Network Join process: Blink, Toggle or Set LED ON + */ +void JoinEvent( void ); + +/*! + * \brief Define action during the Transmit process: Blink, Toggle or Set LED ON + */ +void TxEvent( void ); + +/*! + * \brief Define action when downlink received: Blink, Toggle or Set LED ON + */ +void RxEvent( void ); + +#endif // __LORA_EVENT_PROC_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/LoRaMacLayerService.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,195 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: MAC Layer Services: MLME & MCPS + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ + +#include "LoRaMacLayerService.h" + +/*! + * \brief MCPS-Confirm event function + * + * \param [IN] McpsConfirm - Pointer to the confirm structure, + * containing confirm attributes. + */ +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 + LoRaMacUplinkStatus.Acked = McpsConfirm->AckReceived; + break; + } + case MCPS_PROPRIETARY: + { + break; + } + default: + break; + } + } + + LoRaMacUplinkStatus.Datarate = McpsConfirm->Datarate; + LoRaMacUplinkStatus.UplinkCounter = McpsConfirm->UpLinkCounter; + LoRaMacUplinkStatus.TxPower = McpsConfirm->TxPower; + + IsTxIntUpdate = true; +} + +/*! + * \brief MCPS-Indication event function + * + * \param [IN] McpsIndication - Pointer to the indication structure, + * containing indication attributes. + */ +void McpsIndication( McpsIndication_t *McpsIndication ) +{ + uint8_t port; + + if( McpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK ) + { + 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; + LoRaMacDownlinkStatus.RxSlot = McpsIndication->RxSlot; + + if( ComplianceTest.Running == 1 ) + { + port = 224; + ComplianceTest.DownLinkCounter++; + } + else + { + port = McpsIndication->Port; + } + + if( McpsIndication->RxData == true ) + { + switch( port ) + { + case 1: // The application LED can be controlled on port 1 or 2 + case 2: + break; + case 224: + PrepareComplianceTestFrame( McpsIndication ); + break; + default: + break; + } + } + + IsRxUpdate = true; + +} + +/*! + * \brief MLME-Confirm event function + * + * \param [IN] MlmeConfirm - Pointer to the confirm structure, + * containing confirm attributes. + */ +void MlmeConfirm( MlmeConfirm_t *MlmeConfirm ) +{ + if( MlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) + { + switch( MlmeConfirm->MlmeRequest ) + { + case MLME_JOIN: + { + // Status is OK, node has joined the network + IsNetworkJoinedStatusUpdate = true; + break; + } + case MLME_LINK_CHECK: + { + // Check DemodMargin + // Check NbGateways + if( ComplianceTest.Running == true ) + { + ComplianceTest.LinkCheck = true; + ComplianceTest.DemodMargin = MlmeConfirm->DemodMargin; + ComplianceTest.NbGateways = MlmeConfirm->NbGateways; + } + break; + } + default: + break; + } + } + + // Schedule next packet transmission + TimerSetValue( &TxNextPacketTimer, OVER_THE_AIR_ACTIVATION_DUTYCYCLE ); + TimerStart( &TxNextPacketTimer ); + + DeviceState = DEVICE_STATE_SLEEP; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/LoRaMacLayerService.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,33 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: MAC Layer Services: MLME & MCPS + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ + +#ifndef __LORA_MAC_LAYER_SERVICE__ +#define __LORA_MAC_LAYER_SERVICE__ + +#include "board.h" +#include "LoRaMac.h" +#include "Common.h" +#include "LoRaEventProc.h" +#include "ComplianceTest.h" +#include "SerialDisplay.h" +#include "mbed.h" + + +void McpsConfirm( McpsConfirm_t *McpsConfirm ); +void McpsIndication( McpsIndication_t *McpsIndication ); +void MlmeConfirm( MlmeConfirm_t *MlmeConfirm ); + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/SerialDisplay.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,157 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: VT100 serial display management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ + +#include "SerialDisplay.h" + +VT100 vt( USBTX, USBRX ); + +void SerialDisplayJoinUpdate( void ) +{ + printf( "###### ===== JOINING ==== ######\r\n" ); + + DisplayNetworkParam( ); + + printf( "\r\n" ); +} + +void SerialDisplayTxUpdate(void) +{ + printf( "###### ===== UPLINK FRAME %d ==== ######\r\n", LoRaMacUplinkStatus.UplinkCounter ); + + DisplayNetworkParam( ); + + printf( "TX PORT: %d\r\n", LoRaMacUplinkStatus.Port ); + + if( LoRaMacUplinkStatus.BufferSize != 0 ) + { + printf( "TX DATA: " ); + if( LoRaMacUplinkStatus.Type == MCPS_CONFIRMED ) + { + printf( "CONFIRMED\r\n" ); + } + else + { + printf( "UNCONFIRMED\r\n" ); + } + SerialDisplayHex( LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize ); + } + + printf( "DATA RATE: DR%d\r\n", LoRaMacUplinkStatus.Datarate ); + + printf( "TX POWER: %d dBm\r\n", 30 - ( LoRaMacUplinkStatus.TxPower << 1 ) ); + + printf( "BATTERY: %2.2fV\r\n", BoardGetBatteryLevel( ) ); + + printf( "\r\n"); +} + +void SerialDisplayRxUpdate( void ) +{ + printf( "###### ===== DOWNLINK FRAME %d ==== ######\r\n", LoRaMacDownlinkStatus.DownlinkCounter ); + + printf( "RX WINDOW: %d\r\n", LoRaMacDownlinkStatus.RxSlot + 1 ); + + printf( "RX PORT: %d\r\n", LoRaMacDownlinkStatus.Port ); + + if( LoRaMacDownlinkStatus.BufferSize != 0 ) + { + printf( "RX DATA: \r\n" ); + SerialDisplayHex( LoRaMacDownlinkStatus.Buffer, LoRaMacDownlinkStatus.BufferSize ); + } + + printf( "RX RSSI: %d\r\n", LoRaMacDownlinkStatus.Rssi ); + + printf( "RX SNR: %d\r\n", LoRaMacDownlinkStatus.Snr ); + + printf( "\r\n" ); +} + +void SerialDisplayHex( uint8_t *pData, uint8_t len ) +{ + int i; + bool newline = 0; + + for( i = 0; i < len; i++ ) + { + if( newline != 0 ) + { + printf( "\r\n" ); + newline = 0; + } + + printf( "%02X ", pData[i] ); + + if( ( ( i + 1 ) % 16 ) == 0 ) + { + newline = 1; + } + } + printf( "\r\n" ); +} + +void SerialAcclMetrDisplay( uint8_t statusReg ) +{ + printf( "===== DEVICE ORIENTATION ====\r\n" ); + if( ( statusReg & 0x40 ) != 0 ) + { + printf( "HORIZONTAL + " ); + if( ( statusReg & 0x01 ) != 0 ) + { + printf( "FACE DOWN" ); + } + else + { + printf( "FACE UP" ); + } + } + else + { + printf( "VERTICAL" ); + } + printf( "\r\n\r\n" ); +} + +void DisplayNetworkParam( void ) +{ +#if( OVER_THE_AIR_ACTIVATION != 0 ) + + printf( "DEVEUI: " ); + SerialDisplayHex( DevEui, 8 ); + + printf( "APPEUI: " ); + SerialDisplayHex( AppEui, 8 ); + + printf( "APPKEY: " ); + SerialDisplayHex( AppKey, 16 ); + +#else + + printf( "DEVADDR: " ); + + uint8_t *pData = ( uint8_t* )&DevAddr; + for( int32_t i = 3; i >= 0; i-- ) + { + printf( "%02X ", pData[i] ); + } + printf( "\r\n" ); + + printf( "NWKSKEY: " ); + SerialDisplayHex( NwkSKey, 16 ); + + printf( "APPSKEY: " ); + SerialDisplayHex( AppSKey, 16 ); + +#endif +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/SerialDisplay.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,32 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Serial display management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ +#ifndef __SERIAL_DISPLAY_H__ +#define __SERIAL_DISPLAY_H__ + +#include "board.h" +#include "vt100.h" +#include "Comissioning.h" +#include "LoRaMac.h" +#include "Common.h" +#include "LoRaDeviceStateProc.h" + +void SerialDisplayJoinUpdate( void ); +void SerialDisplayTxUpdate( void ); +void SerialDisplayRxUpdate( void ); +void SerialDisplayHex( uint8_t *pData, uint8_t len ); +void SerialAcclMetrDisplay( uint8_t statusReg ); +void DisplayNetworkParam( void ); + +#endif // __SERIAL_DISPLAY_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,229 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (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 "radio.h" + +#include "LoRaMac.h" +#include "Comissioning.h" +#include "SerialDisplay.h" +#include "ComplianceTest.h" +#include "LoRaDeviceStateProc.h" +#include "LoRaEventProc.h" +#include "LoRaApp.h" + +/*! + * Defines a random delay for application data transmission duty cycle. 1s, + * value in [us]. + */ + + +#if( OVER_THE_AIR_ACTIVATION != 0 ) + +uint8_t DevEui[] = LORAWAN_DEVICE_EUI; +uint8_t AppEui[] = LORAWAN_APPLICATION_EUI; +uint8_t AppKey[] = LORAWAN_APPLICATION_KEY; + +#else + +uint8_t NwkSKey[] = LORAWAN_NWKSKEY; +uint8_t AppSKey[] = LORAWAN_APPSKEY; + +/*! + * Device address + */ +uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS; + +#endif + +/*! + * Application port + */ +uint8_t AppPort = LORAWAN_APP_PORT; + +/*! + * User application data size + */ +uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE; + +/*! + * User application data + */ +uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE]; + +/*! + * Application to handle functions + */ +Application LoRaApp( AppData ); + +/*! + * Indicates if the node is sending confirmed or unconfirmed messages + */ +uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; + +/*! + * Timer to handle the application data transmission duty cycle + */ +TimerEvent_t TxNextPacketTimer; + +/*! + * Indicates if a new transmit interrupt can be set + */ +bool IsTxIntUpdate = false; + +/*! + * Indicates if a new packet can be sent + */ +bool NextTx = true; + +/*! + * LoRaWAN compliance tests support data + */ +ComplianceTest_s ComplianceTest; + +/*! + * Indicates if the MAC layer network join status has changed. + */ +bool IsNetworkJoinedStatusUpdate = false; + +/*! + * Indicates if the message sent. + */ +bool IsTxUpdate = false; + +/*! + * Indicates if the message received in the RX window. + */ +bool IsRxUpdate = false; + + +/** + * Main application entry point. + */ +int main( void ) +{ + + // Initialize board peripherals + BoardInit( ); + + // Initialize Device state + DeviceState = DEVICE_STATE_INIT; + + while( 1 ) + { + if( IsNetworkJoinedStatusUpdate == true ) + { + IsNetworkJoinedStatusUpdate = false; + + DeviceJoinUpdate( ); + } + + if( IsTxUpdate == true ) + { + // If downlink received then update Serial Terminal and execute Rx event + IsTxUpdate = false; + + // Update serial terminal + SerialDisplayTxUpdate( ); + } + + if( IsTxIntUpdate == true ) + { + IsTxIntUpdate = false; + + // Initialize next Tx Interrupt + InitNextTxInterrupt( AppPort ); + } + + if( IsRxUpdate == true ) + { + // If downlink received then update Serial Terminal and execute Rx event + IsRxUpdate = false; + RxEvent( ); + SerialDisplayRxUpdate( ); + } + + switch( DeviceState ) + { + case DEVICE_STATE_INIT: + { + // Initialize MAC, MAC services, Primitives + DeviceInit( ); + + // Change Device state + DeviceState = DEVICE_STATE_JOIN; + break; + } + case DEVICE_STATE_JOIN: + { +#if( OVER_THE_AIR_ACTIVATION != 0 ) // OTA + + // Generate DevEUI if not defined by User + BoardGetDevEUI( DevEui ); + + // Join N/w server + DeviceJoin( ); + + // Show on serial terminal + SerialDisplayJoinUpdate( ); + + // Execute Join event + JoinEvent( ); + + DeviceState = DEVICE_STATE_SLEEP; + +#else // ABP + DeviceJoin( ); + + DeviceState = DEVICE_STATE_SEND; +#endif + IsNetworkJoinedStatusUpdate = true; + break; + } + case DEVICE_STATE_SEND: + { + if( NextTx == true ) + { + // Prepare payload frame based on application port + PrepareTxFrame( AppPort ); + + // Send payload over the air + NextTx = SendFrame( ); + + // Execute transmit event + TxEvent( ); + } + + if( NextTx == false ) + { + IsTxUpdate = true; + } + + DeviceState = DEVICE_STATE_SLEEP; + break; + } + case DEVICE_STATE_SLEEP: + { + // Wake up through events + break; + } + default: + { + DeviceState = DEVICE_STATE_INIT; + break; + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/vt100.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,213 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: VT100 terminal support class + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __VT100_H__ +#define __VT100_H__ + +#ifndef STRING_STACK_LIMIT +#define STRING_STACK_LIMIT 120 +#endif + +/** + * Implements VT100 terminal commands support. + * Implments also the same behaviour has RawSerial class. The only difference + * is located in putc fucntion where writeable check is made befor sending the character. + */ +class VT100 : public SerialBase +{ +public: + enum TextAttributes + { + ATTR_OFF = 0, + BOLD = 1, + USCORE = 4, + BLINK = 5, + REVERSE = 7, + BOLD_OFF = 21, + USCORE_OFF = 24, + BLINK_OFF = 25, + REVERSE_OFF = 27, + }; + + enum Colors + { + BLACK = 0, + RED = 1, + GREEN = 2, + BROWN = 3, + BLUE = 4, + MAGENTA = 5, + CYAN = 6, + WHITE = 7, + }; + + VT100( PinName tx, PinName rx ): SerialBase( tx, rx ) + { + this->baud( 115200 ); + // initializes terminal to "power-on" settings + // ESC c + this->printf( "\x1B\x63" ); + } + + void ClearScreen( uint8_t param ) + { + // ESC [ Ps J + // 0 Clear screen from cursor down + // 1 Clear screen from cursor up + // 2 Clear entire screen + this->printf( "\x1B[%dJ", param ); + } + + void ClearLine( uint8_t param ) + { + // ESC [ Ps K + // 0 Erase from the active position to the end of the line, inclusive (default) + // 1 Erase from the start of the screen to the active position, inclusive + // 2 Erase all of the line, inclusive + this->printf( "\x1B[%dK", param ); + } + + void SetAttribute( uint8_t attr ) + { + // ESC [ Ps;...;Ps m + this->printf( "\x1B[%dm", attr ); + } + + void SetAttribute( uint8_t attr, uint8_t fgcolor, uint8_t bgcolor ) + { + // ESC [ Ps;...;Ps m + this->printf( "\x1B[%d;%d;%dm", attr, fgcolor + 30, bgcolor + 40 ); + } + + void SetCursorMode( uint8_t visible ) + { + if( visible == true ) + { + // ESC [ ? 25 h + this->printf( "\x1B[?25h" ); + } + else + { + // ESC [ ? 25 l + this->printf( "\x1B[?25l" ); + } + } + + void SetCursorPos( uint8_t line, uint8_t col ) + { + // ESC [ Pl ; Pc H + this->printf( "\x1B[%d;%dH", line, col ); + } + + void PutStringAt( uint8_t line, uint8_t col, const char *s ) + { + this->SetCursorPos( line, col ); + this->printf( "%s", s ); + } + + void PutCharAt( uint8_t line, uint8_t col, uint8_t c ) + { + this->SetCursorPos( line, col ); + this->printf( "%c", c ); + } + + void PutHexAt( uint8_t line, uint8_t col, uint16_t n ) + { + this->SetCursorPos( line, col ); + this->printf( "%X", n ); + } + + void PutBoxDrawingChar( uint8_t c ) + { + this->printf( "\x1B(0%c\x1b(B", c ); + } + + bool Readable( void ) + { + return this->readable( ); + } + + uint8_t GetChar( void ) + { + return this->getc( ); + } + + /* + * RawSerial class implmentation copy. + */ + /** Read a char from the serial port + * + * @returns The char read from the serial port + */ + int getc( ) + { + return _base_getc(); + } + + /** Write a char to the serial port + * + * @param c The char to write + * + * @returns The written char or -1 if an error occured + */ + int putc( int c ) + { + while( this->writeable( ) != 1 ); + return _base_putc( c ); + } + + /** Write a string to the serial port + * + * @param str The string to write + * + * @returns 0 if the write succeeds, EOF for error + */ + int puts( const char *str ) + { + while( *str ) + putc( *str++ ); + return 0; + } + + // Experimental support for printf in RawSerial. No Stream inheritance + // means we can't call printf() directly, so we use sprintf() instead. + // We only call malloc() for the sprintf() buffer if the buffer + // length is above a certain threshold, otherwise we use just the stack. + int printf( const char *format, ... ) + { + std::va_list arg; + va_start( arg, format ); + int len = vsnprintf( NULL, 0, format, arg ); + if( len < STRING_STACK_LIMIT ) + { + char temp[STRING_STACK_LIMIT]; + vsprintf( temp, format, arg ); + puts( temp ); + } + else + { + char *temp = new char[len + 1]; + vsprintf( temp, format, arg ); + puts( temp ); + delete[] temp; + } + va_end( arg ); + return len; + } + +private: + +}; + +#endif // __VT100_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/board/board.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,69 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Target board general functions 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" + +MoteVersion_t BoardGetVersion( void ); + +DigitalIn I2cInterrupt( PB_4 ); +I2C I2c(I2C_SDA, I2C_SCL); + +DigitalOut Pc7( PC_7 ); +DigitalIn Pc1( PC_1 ); + +#define AIN_VREF 3.3 // STM32 internal refernce +#define AIN_VBAT_DIV 2 // Resistor divider + +SX1276MB1xAS Radio( NULL ); + +void BoardInit( void ) +{ + TimerTimeCounterInit( ); +} + + +uint8_t BoardGetBatteryLevel( void ) +{ + return 0xFE; +} + +uint32_t BoardGetRandomSeed( void ) +{ + return ( ( *( uint32_t* )ID1 ) ^ ( *( uint32_t* )ID2 ) ^ ( *( uint32_t* )ID3 ) ); +} + +void BoardGetDevEUI( uint8_t *id ) +{ + uint32_t *pDevEuiHWord = ( uint32_t* )&id[4]; + + if( *pDevEuiHWord == 0 ) + { + *pDevEuiHWord = BoardGetRandomSeed( ); + } + +} + +void BoardGetUniqueId( uint8_t *id ) +{ + id[7] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 24; + id[6] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 16; + id[5] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 8; + id[4] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ); + id[3] = ( ( *( uint32_t* )ID2 ) ) >> 24; + id[2] = ( ( *( uint32_t* )ID2 ) ) >> 16; + id[1] = ( ( *( uint32_t* )ID2 ) ) >> 8; + id[0] = ( ( *( uint32_t* )ID2 ) ); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/board/board.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,77 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Target board general functions implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "Config.h" +#include "mbed.h" +#include "system/timer.h" +#include "debug.h" +#include "system/utilities.h" +#include "sx1276-hal.h" + +/*! + * Unique Devices IDs register set ( STM32L1xxx ) + */ +#define ID1 ( 0x1FF800D0 ) +#define ID2 ( 0x1FF800D4 ) +#define ID3 ( 0x1FF800E4 ) + +#define LOW_BAT_THRESHOLD 3.45 + +extern SX1276MB1xAS Radio; + +typedef enum +{ + MOTE_VERSION_NONE = 0, + MOTE_VERSION_2, + MOTE_VERSION_3, +}MoteVersion_t; + + +/*! + * \brief Initializes the target board peripherals. + */ +void BoardInit( void ); + +/*! + * \brief Measure the Battery level + * + * \retval value battery level ( 0: very low, 254: fully charged ) + */ +uint8_t BoardGetBatteryLevel( void ); + +/*! + * Returns a pseudo random seed generated using the MCU Unique ID + * + * \retval seed Generated pseudo random seed + */ +uint32_t BoardGetRandomSeed( void ); + +/*! + * \brief Generates Lower 32 bits of DEVEUI using 96 bits unique device ID + * + * \param [IN] id Pointer to an array that will contain the Unique ID + */ +void BoardGetDevEUI( uint8_t *id ); + +/*! + * \brief Gets the board 64 bits unique ID + * + * \param [IN] id Pointer to an array that will contain the Unique ID + */ +void BoardGetUniqueId( uint8_t *id ); + +#endif // __BOARD_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mac/LoRaWAN-lib.lib Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/teams/Semtech/code/LoRaWAN-lib/#d7a34ded7c87
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/radio/SX1276Lib.lib Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/teams/Semtech/code/SX1276Lib/#3778e6204cc1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/crypto/aes.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,936 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state (there are options to use 32-bit types if available). + + The combination of mix columns and byte substitution used here is based on + that developed by Karl Malbrain. His contribution is acknowledged. + */ + +/* define if you have a fast memcpy function on your system */ +#if 0 +# define HAVE_MEMCPY +# include <string.h> +# if defined( _MSC_VER ) +# include <intrin.h> +# pragma intrinsic( memcpy ) +# endif +#endif + + +#include <stdlib.h> +#include <stdint.h> + +/* define if you have fast 32-bit types on your system */ +#if ( __CORTEX_M != 0 ) // if Cortex is different from M0/M0+ +# define HAVE_UINT_32T +#endif + +/* define if you don't want any tables */ +#if 1 +# define USE_TABLES +#endif + +/* On Intel Core 2 duo VERSION_1 is faster */ + +/* alternative versions (test for performance on your system) */ +#if 1 +# define VERSION_1 +#endif + +#include "aes.h" + +//#if defined( HAVE_UINT_32T ) +// typedef unsigned long uint32_t; +//#endif + +/* functions for finite field multiplication in the AES Galois field */ + +#define WPOLY 0x011b +#define BPOLY 0x1b +#define DPOLY 0x008d + +#define f1(x) (x) +#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY)) +#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY)) +#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \ + ^ (((x >> 5) & 4) * WPOLY)) +#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0)) + +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#if defined( USE_TABLES ) + +#define sb_data(w) { /* S Box data values */ \ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } + +#define isb_data(w) { /* inverse S Box data values */ \ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } + +#define mm_data(w) { /* basic data for forming finite field tables */ \ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } + +static const uint8_t sbox[256] = sb_data(f1); + +#if defined( AES_DEC_PREKEYED ) +static const uint8_t isbox[256] = isb_data(f1); +#endif + +static const uint8_t gfm2_sbox[256] = sb_data(f2); +static const uint8_t gfm3_sbox[256] = sb_data(f3); + +#if defined( AES_DEC_PREKEYED ) +static const uint8_t gfmul_9[256] = mm_data(f9); +static const uint8_t gfmul_b[256] = mm_data(fb); +static const uint8_t gfmul_d[256] = mm_data(fd); +static const uint8_t gfmul_e[256] = mm_data(fe); +#endif + +#define s_box(x) sbox[(x)] +#if defined( AES_DEC_PREKEYED ) +#define is_box(x) isbox[(x)] +#endif +#define gfm2_sb(x) gfm2_sbox[(x)] +#define gfm3_sb(x) gfm3_sbox[(x)] +#if defined( AES_DEC_PREKEYED ) +#define gfm_9(x) gfmul_9[(x)] +#define gfm_b(x) gfmul_b[(x)] +#define gfm_d(x) gfmul_d[(x)] +#define gfm_e(x) gfmul_e[(x)] +#endif +#else + +/* this is the high bit of x right shifted by 1 */ +/* position. Since the starting polynomial has */ +/* 9 bits (0x11b), this right shift keeps the */ +/* values of all top bits within a byte */ + +static uint8_t hibit(const uint8_t x) +{ uint8_t r = (uint8_t)((x >> 1) | (x >> 2)); + + r |= (r >> 2); + r |= (r >> 4); + return (r + 1) >> 1; +} + +/* return the inverse of the finite field element x */ + +static uint8_t gf_inv(const uint8_t x) +{ uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; + + if(x < 2) + return x; + + for( ; ; ) + { + if(n1) + while(n2 >= n1) /* divide polynomial p2 by p1 */ + { + n2 /= n1; /* shift smaller polynomial left */ + p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */ + v2 ^= (v1 * n2); /* shift accumulated value and */ + n2 = hibit(p2); /* add into result */ + } + else + return v1; + + if(n2) /* repeat with values swapped */ + while(n1 >= n2) + { + n1 /= n2; + p1 ^= p2 * n1; + v1 ^= v2 * n1; + n1 = hibit(p1); + } + else + return v2; + } +} + +/* The forward and inverse affine transformations used in the S-box */ +uint8_t fwd_affine(const uint8_t x) +{ +#if defined( HAVE_UINT_32T ) + uint32_t w = x; + w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4); + return 0x63 ^ ((w ^ (w >> 8)) & 0xff); +#else + return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4) + ^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4); +#endif +} + +uint8_t inv_affine(const uint8_t x) +{ +#if defined( HAVE_UINT_32T ) + uint32_t w = x; + w = (w << 1) ^ (w << 3) ^ (w << 6); + return 0x05 ^ ((w ^ (w >> 8)) & 0xff); +#else + return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6) + ^ (x >> 7) ^ (x >> 5) ^ (x >> 2); +#endif +} + +#define s_box(x) fwd_affine(gf_inv(x)) +#define is_box(x) gf_inv(inv_affine(x)) +#define gfm2_sb(x) f2(s_box(x)) +#define gfm3_sb(x) f3(s_box(x)) +#define gfm_9(x) f9(x) +#define gfm_b(x) fb(x) +#define gfm_d(x) fd(x) +#define gfm_e(x) fe(x) + +#endif + +#if defined( HAVE_MEMCPY ) +# define block_copy_nn(d, s, l) memcpy(d, s, l) +# define block_copy(d, s) memcpy(d, s, N_BLOCK) +#else +# define block_copy_nn(d, s, l) copy_block_nn(d, s, l) +# define block_copy(d, s) copy_block(d, s) +#endif + +static void copy_block( void *d, const void *s ) +{ +#if defined( HAVE_UINT_32T ) + ((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0]; + ((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1]; + ((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2]; + ((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3]; +#else + ((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0]; + ((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1]; + ((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2]; + ((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3]; + ((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4]; + ((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5]; + ((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6]; + ((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7]; + ((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8]; + ((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9]; + ((uint8_t*)d)[10] = ((uint8_t*)s)[10]; + ((uint8_t*)d)[11] = ((uint8_t*)s)[11]; + ((uint8_t*)d)[12] = ((uint8_t*)s)[12]; + ((uint8_t*)d)[13] = ((uint8_t*)s)[13]; + ((uint8_t*)d)[14] = ((uint8_t*)s)[14]; + ((uint8_t*)d)[15] = ((uint8_t*)s)[15]; +#endif +} + +static void copy_block_nn( uint8_t * d, const uint8_t *s, uint8_t nn ) +{ + while( nn-- ) + //*((uint8_t*)d)++ = *((uint8_t*)s)++; + *d++ = *s++; +} + +static void xor_block( void *d, const void *s ) +{ +#if defined( HAVE_UINT_32T ) + ((uint32_t*)d)[ 0] ^= ((uint32_t*)s)[ 0]; + ((uint32_t*)d)[ 1] ^= ((uint32_t*)s)[ 1]; + ((uint32_t*)d)[ 2] ^= ((uint32_t*)s)[ 2]; + ((uint32_t*)d)[ 3] ^= ((uint32_t*)s)[ 3]; +#else + ((uint8_t*)d)[ 0] ^= ((uint8_t*)s)[ 0]; + ((uint8_t*)d)[ 1] ^= ((uint8_t*)s)[ 1]; + ((uint8_t*)d)[ 2] ^= ((uint8_t*)s)[ 2]; + ((uint8_t*)d)[ 3] ^= ((uint8_t*)s)[ 3]; + ((uint8_t*)d)[ 4] ^= ((uint8_t*)s)[ 4]; + ((uint8_t*)d)[ 5] ^= ((uint8_t*)s)[ 5]; + ((uint8_t*)d)[ 6] ^= ((uint8_t*)s)[ 6]; + ((uint8_t*)d)[ 7] ^= ((uint8_t*)s)[ 7]; + ((uint8_t*)d)[ 8] ^= ((uint8_t*)s)[ 8]; + ((uint8_t*)d)[ 9] ^= ((uint8_t*)s)[ 9]; + ((uint8_t*)d)[10] ^= ((uint8_t*)s)[10]; + ((uint8_t*)d)[11] ^= ((uint8_t*)s)[11]; + ((uint8_t*)d)[12] ^= ((uint8_t*)s)[12]; + ((uint8_t*)d)[13] ^= ((uint8_t*)s)[13]; + ((uint8_t*)d)[14] ^= ((uint8_t*)s)[14]; + ((uint8_t*)d)[15] ^= ((uint8_t*)s)[15]; +#endif +} + +static void copy_and_key( void *d, const void *s, const void *k ) +{ +#if defined( HAVE_UINT_32T ) + ((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0] ^ ((uint32_t*)k)[ 0]; + ((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1] ^ ((uint32_t*)k)[ 1]; + ((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2] ^ ((uint32_t*)k)[ 2]; + ((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3] ^ ((uint32_t*)k)[ 3]; +#elif 1 + ((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0] ^ ((uint8_t*)k)[ 0]; + ((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1] ^ ((uint8_t*)k)[ 1]; + ((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2] ^ ((uint8_t*)k)[ 2]; + ((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3] ^ ((uint8_t*)k)[ 3]; + ((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4] ^ ((uint8_t*)k)[ 4]; + ((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5] ^ ((uint8_t*)k)[ 5]; + ((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6] ^ ((uint8_t*)k)[ 6]; + ((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7] ^ ((uint8_t*)k)[ 7]; + ((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8] ^ ((uint8_t*)k)[ 8]; + ((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9] ^ ((uint8_t*)k)[ 9]; + ((uint8_t*)d)[10] = ((uint8_t*)s)[10] ^ ((uint8_t*)k)[10]; + ((uint8_t*)d)[11] = ((uint8_t*)s)[11] ^ ((uint8_t*)k)[11]; + ((uint8_t*)d)[12] = ((uint8_t*)s)[12] ^ ((uint8_t*)k)[12]; + ((uint8_t*)d)[13] = ((uint8_t*)s)[13] ^ ((uint8_t*)k)[13]; + ((uint8_t*)d)[14] = ((uint8_t*)s)[14] ^ ((uint8_t*)k)[14]; + ((uint8_t*)d)[15] = ((uint8_t*)s)[15] ^ ((uint8_t*)k)[15]; +#else + block_copy(d, s); + xor_block(d, k); +#endif +} + +static void add_round_key( uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK] ) +{ + xor_block(d, k); +} + +static void shift_sub_rows( uint8_t st[N_BLOCK] ) +{ uint8_t tt; + + st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]); + st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]); + + tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]); + st[ 9] = s_box(st[13]); st[13] = s_box( tt ); + + tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt ); + tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt ); + + tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]); + st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt ); +} + +#if defined( AES_DEC_PREKEYED ) + +static void inv_shift_sub_rows( uint8_t st[N_BLOCK] ) +{ uint8_t tt; + + st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]); + st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]); + + tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]); + st[ 5] = is_box(st[1]); st[ 1] = is_box( tt ); + + tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt ); + tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt ); + + tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]); + st[11] = is_box(st[15]); st[15] = is_box( tt ); +} + +#endif + +#if defined( VERSION_1 ) + static void mix_sub_columns( uint8_t dt[N_BLOCK] ) + { uint8_t st[N_BLOCK]; + block_copy(st, dt); +#else + static void mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] ) + { +#endif + dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]); + dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]); + dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]); + dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]); + + dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]); + dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]); + dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]); + dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]); + + dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]); + dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]); + dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]); + dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]); + + dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]); + dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]); + dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]); + dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]); + } + +#if defined( AES_DEC_PREKEYED ) + +#if defined( VERSION_1 ) + static void inv_mix_sub_columns( uint8_t dt[N_BLOCK] ) + { uint8_t st[N_BLOCK]; + block_copy(st, dt); +#else + static void inv_mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] ) + { +#endif + dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3])); + dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3])); + dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3])); + dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3])); + + dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7])); + dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7])); + dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7])); + dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7])); + + dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11])); + dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11])); + dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11])); + dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11])); + + dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15])); + dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15])); + dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15])); + dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15])); + } + +#endif + +#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) + +/* Set the cipher key for the pre-keyed version */ + +return_type aes_set_key( const uint8_t key[], length_type keylen, aes_context ctx[1] ) +{ + uint8_t cc, rc, hi; + + switch( keylen ) + { + case 16: + case 24: + case 32: + break; + default: + ctx->rnd = 0; + return ( uint8_t )-1; + } + block_copy_nn(ctx->ksch, key, keylen); + hi = (keylen + 28) << 2; + ctx->rnd = (hi >> 4) - 1; + for( cc = keylen, rc = 1; cc < hi; cc += 4 ) + { uint8_t tt, t0, t1, t2, t3; + + t0 = ctx->ksch[cc - 4]; + t1 = ctx->ksch[cc - 3]; + t2 = ctx->ksch[cc - 2]; + t3 = ctx->ksch[cc - 1]; + if( cc % keylen == 0 ) + { + tt = t0; + t0 = s_box(t1) ^ rc; + t1 = s_box(t2); + t2 = s_box(t3); + t3 = s_box(tt); + rc = f2(rc); + } + else if( keylen > 24 && cc % keylen == 16 ) + { + t0 = s_box(t0); + t1 = s_box(t1); + t2 = s_box(t2); + t3 = s_box(t3); + } + tt = cc - keylen; + ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0; + ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1; + ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2; + ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3; + } + return 0; +} + +#endif + +#if defined( AES_ENC_PREKEYED ) + +/* Encrypt a single block of 16 bytes */ + +return_type aes_encrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] ) +{ + if( ctx->rnd ) + { + uint8_t s1[N_BLOCK], r; + copy_and_key( s1, in, ctx->ksch ); + + for( r = 1 ; r < ctx->rnd ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns( s1 ); + add_round_key( s1, ctx->ksch + r * N_BLOCK); + } +#else + { uint8_t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK); + } +#endif + shift_sub_rows( s1 ); + copy_and_key( out, s1, ctx->ksch + r * N_BLOCK ); + } + else + return ( uint8_t )-1; + return 0; +} + +/* CBC encrypt a number of blocks (input and return an IV) */ + +return_type aes_cbc_encrypt( const uint8_t *in, uint8_t *out, + int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] ) +{ + + while(n_block--) + { + xor_block(iv, in); + if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) + return EXIT_FAILURE; + //memcpy(out, iv, N_BLOCK); + block_copy(out, iv); + in += N_BLOCK; + out += N_BLOCK; + } + return EXIT_SUCCESS; +} + +#endif + +#if defined( AES_DEC_PREKEYED ) + +/* Decrypt a single block of 16 bytes */ + +return_type aes_decrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] ) +{ + if( ctx->rnd ) + { + uint8_t s1[N_BLOCK], r; + copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK ); + inv_shift_sub_rows( s1 ); + + for( r = ctx->rnd ; --r ; ) +#if defined( VERSION_1 ) + { + add_round_key( s1, ctx->ksch + r * N_BLOCK ); + inv_mix_sub_columns( s1 ); + } +#else + { uint8_t s2[N_BLOCK]; + copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + copy_and_key( out, s1, ctx->ksch ); + } + else + return -1; + return 0; +} + +/* CBC decrypt a number of blocks (input and return an IV) */ + +return_type aes_cbc_decrypt( const uint8_t *in, uint8_t *out, + int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] ) +{ + while(n_block--) + { uint8_t tmp[N_BLOCK]; + + //memcpy(tmp, in, N_BLOCK); + block_copy(tmp, in); + if(aes_decrypt(in, out, ctx) != EXIT_SUCCESS) + return EXIT_FAILURE; + xor_block(out, iv); + //memcpy(iv, tmp, N_BLOCK); + block_copy(iv, tmp); + in += N_BLOCK; + out += N_BLOCK; + } + return EXIT_SUCCESS; +} + +#endif + +#if defined( AES_ENC_128_OTFK ) + +/* The 'on the fly' encryption key update for for 128 bit keys */ + +static void update_encrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc ) +{ uint8_t cc; + + k[0] ^= s_box(k[13]) ^ *rc; + k[1] ^= s_box(k[14]); + k[2] ^= s_box(k[15]); + k[3] ^= s_box(k[12]); + *rc = f2( *rc ); + + for(cc = 4; cc < 16; cc += 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } +} + +/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ + +void aes_encrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] ) +{ uint8_t s1[N_BLOCK], r, rc = 1; + + if(o_key != key) + block_copy( o_key, key ); + copy_and_key( s1, in, o_key ); + + for( r = 1 ; r < 10 ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns( s1 ); + update_encrypt_key_128( o_key, &rc ); + add_round_key( s1, o_key ); + } +#else + { uint8_t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + update_encrypt_key_128( o_key, &rc ); + copy_and_key( s1, s2, o_key ); + } +#endif + + shift_sub_rows( s1 ); + update_encrypt_key_128( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_DEC_128_OTFK ) + +/* The 'on the fly' decryption key update for for 128 bit keys */ + +static void update_decrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc ) +{ uint8_t cc; + + for( cc = 12; cc > 0; cc -= 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + *rc = d2(*rc); + k[0] ^= s_box(k[13]) ^ *rc; + k[1] ^= s_box(k[14]); + k[2] ^= s_box(k[15]); + k[3] ^= s_box(k[12]); +} + +/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ + +void aes_decrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] ) +{ + uint8_t s1[N_BLOCK], r, rc = 0x6c; + if(o_key != key) + block_copy( o_key, key ); + + copy_and_key( s1, in, o_key ); + inv_shift_sub_rows( s1 ); + + for( r = 10 ; --r ; ) +#if defined( VERSION_1 ) + { + update_decrypt_key_128( o_key, &rc ); + add_round_key( s1, o_key ); + inv_mix_sub_columns( s1 ); + } +#else + { uint8_t s2[N_BLOCK]; + update_decrypt_key_128( o_key, &rc ); + copy_and_key( s2, s1, o_key ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + update_decrypt_key_128( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_ENC_256_OTFK ) + +/* The 'on the fly' encryption key update for for 256 bit keys */ + +static void update_encrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc ) +{ uint8_t cc; + + k[0] ^= s_box(k[29]) ^ *rc; + k[1] ^= s_box(k[30]); + k[2] ^= s_box(k[31]); + k[3] ^= s_box(k[28]); + *rc = f2( *rc ); + + for(cc = 4; cc < 16; cc += 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + k[16] ^= s_box(k[12]); + k[17] ^= s_box(k[13]); + k[18] ^= s_box(k[14]); + k[19] ^= s_box(k[15]); + + for( cc = 20; cc < 32; cc += 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } +} + +/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */ + +void aes_encrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] ) +{ + uint8_t s1[N_BLOCK], r, rc = 1; + if(o_key != key) + { + block_copy( o_key, key ); + block_copy( o_key + 16, key + 16 ); + } + copy_and_key( s1, in, o_key ); + + for( r = 1 ; r < 14 ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns(s1); + if( r & 1 ) + add_round_key( s1, o_key + 16 ); + else + { + update_encrypt_key_256( o_key, &rc ); + add_round_key( s1, o_key ); + } + } +#else + { uint8_t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + if( r & 1 ) + copy_and_key( s1, s2, o_key + 16 ); + else + { + update_encrypt_key_256( o_key, &rc ); + copy_and_key( s1, s2, o_key ); + } + } +#endif + + shift_sub_rows( s1 ); + update_encrypt_key_256( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_DEC_256_OTFK ) + +/* The 'on the fly' encryption key update for for 256 bit keys */ + +static void update_decrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc ) +{ uint8_t cc; + + for(cc = 28; cc > 16; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + k[16] ^= s_box(k[12]); + k[17] ^= s_box(k[13]); + k[18] ^= s_box(k[14]); + k[19] ^= s_box(k[15]); + + for(cc = 12; cc > 0; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + *rc = d2(*rc); + k[0] ^= s_box(k[29]) ^ *rc; + k[1] ^= s_box(k[30]); + k[2] ^= s_box(k[31]); + k[3] ^= s_box(k[28]); +} + +/* Decrypt a single block of 16 bytes with 'on the fly' + 256 bit keying +*/ +void aes_decrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] ) +{ + uint8_t s1[N_BLOCK], r, rc = 0x80; + + if(o_key != key) + { + block_copy( o_key, key ); + block_copy( o_key + 16, key + 16 ); + } + + copy_and_key( s1, in, o_key ); + inv_shift_sub_rows( s1 ); + + for( r = 14 ; --r ; ) +#if defined( VERSION_1 ) + { + if( ( r & 1 ) ) + { + update_decrypt_key_256( o_key, &rc ); + add_round_key( s1, o_key + 16 ); + } + else + add_round_key( s1, o_key ); + inv_mix_sub_columns( s1 ); + } +#else + { uint8_t s2[N_BLOCK]; + if( ( r & 1 ) ) + { + update_decrypt_key_256( o_key, &rc ); + copy_and_key( s2, s1, o_key + 16 ); + } + else + copy_and_key( s2, s1, o_key ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + copy_and_key( out, s1, o_key ); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/crypto/aes.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,160 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state. + */ + +#ifndef AES_H +#define AES_H + +#if 1 +# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */ +#endif +#if 0 +# define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */ +#endif +#if 0 +# define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */ +#endif +#if 0 +# define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */ +#endif +#if 0 +# define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */ +#endif +#if 0 +# define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */ +#endif + +#define N_ROW 4 +#define N_COL 4 +#define N_BLOCK (N_ROW * N_COL) +#define N_MAX_ROUNDS 14 + +typedef uint8_t return_type; + +/* Warning: The key length for 256 bit keys overflows a byte + (see comment below) +*/ + +typedef uint8_t length_type; + +typedef struct +{ uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK]; + uint8_t rnd; +} aes_context; + +/* The following calls are for a precomputed key schedule + + NOTE: If the length_type used for the key length is an + unsigned 8-bit character, a key length of 256 bits must + be entered as a length in bytes (valid inputs are hence + 128, 192, 16, 24 and 32). +*/ + +#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) + +return_type aes_set_key( const uint8_t key[], + length_type keylen, + aes_context ctx[1] ); +#endif + +#if defined( AES_ENC_PREKEYED ) + +return_type aes_encrypt( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const aes_context ctx[1] ); + +return_type aes_cbc_encrypt( const uint8_t *in, + uint8_t *out, + int32_t n_block, + uint8_t iv[N_BLOCK], + const aes_context ctx[1] ); +#endif + +#if defined( AES_DEC_PREKEYED ) + +return_type aes_decrypt( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const aes_context ctx[1] ); + +return_type aes_cbc_decrypt( const uint8_t *in, + uint8_t *out, + int32_t n_block, + uint8_t iv[N_BLOCK], + const aes_context ctx[1] ); +#endif + +/* The following calls are for 'on the fly' keying. In this case the + encryption and decryption keys are different. + + The encryption subroutines take a key in an array of bytes in + key[L] where L is 16, 24 or 32 bytes for key lengths of 128, + 192, and 256 bits respectively. They then encrypts the input + data, in[] with this key and put the reult in the output array + out[]. In addition, the second key array, o_key[L], is used + to output the key that is needed by the decryption subroutine + to reverse the encryption operation. The two key arrays can + be the same array but in this case the original key will be + overwritten. + + In the same way, the decryption subroutines output keys that + can be used to reverse their effect when used for encryption. + + Only 128 and 256 bit keys are supported in these 'on the fly' + modes. +*/ + +#if defined( AES_ENC_128_OTFK ) +void aes_encrypt_128( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], + uint8_t o_key[N_BLOCK] ); +#endif + +#if defined( AES_DEC_128_OTFK ) +void aes_decrypt_128( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], + uint8_t o_key[N_BLOCK] ); +#endif + +#if defined( AES_ENC_256_OTFK ) +void aes_encrypt_256( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], + uint8_t o_key[2 * N_BLOCK] ); +#endif + +#if defined( AES_DEC_256_OTFK ) +void aes_decrypt_256( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], + uint8_t o_key[2 * N_BLOCK] ); +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/crypto/cmac.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,153 @@ +/************************************************************************** +Copyright (C) 2009 Lander Casado, Philippas Tsigas + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files +(the "Software"), to deal with the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimers. Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimers in the documentation and/or +other materials provided with the distribution. + +In no event shall the authors or copyright holders be liable for any special, +incidental, indirect or consequential damages of any kind, or any damages +whatsoever resulting from loss of use, data or profits, whether or not +advised of the possibility of damage, and on any theory of liability, +arising out of or in connection with the use or performance of this software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS WITH THE SOFTWARE + +*****************************************************************************/ +//#include <sys/param.h> +//#include <sys/systm.h> +#include <stdint.h> +#include "aes.h" +#include "cmac.h" +#include "utilities.h" + +#define LSHIFT(v, r) do { \ + int32_t i; \ + for (i = 0; i < 15; i++) \ + (r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7; \ + (r)[15] = (v)[15] << 1; \ + } while (0) + +#define XOR(v, r) do { \ + int32_t i; \ + for (i = 0; i < 16; i++) \ + { \ + (r)[i] = (r)[i] ^ (v)[i]; \ + } \ + } while (0) \ + + +void AES_CMAC_Init(AES_CMAC_CTX *ctx) +{ + memset1(ctx->X, 0, sizeof ctx->X); + ctx->M_n = 0; + memset1(ctx->rijndael.ksch, '\0', 240); +} + +void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]) +{ + //rijndael_set_key_enc_only(&ctx->rijndael, key, 128); + aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael); +} + +void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len) +{ + uint32_t mlen; + uint8_t in[16]; + + if (ctx->M_n > 0) { + mlen = MIN(16 - ctx->M_n, len); + memcpy1(ctx->M_last + ctx->M_n, data, mlen); + ctx->M_n += mlen; + if (ctx->M_n < 16 || len == mlen) + return; + XOR(ctx->M_last, ctx->X); + //rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X); + aes_encrypt( ctx->X, ctx->X, &ctx->rijndael); + data += mlen; + len -= mlen; + } + while (len > 16) { /* not last block */ + + XOR(data, ctx->X); + //rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X); + + memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten + aes_encrypt( in, in, &ctx->rijndael); + memcpy1(&ctx->X[0], in, 16); + + data += 16; + len -= 16; + } + /* potential last block, save it */ + memcpy1(ctx->M_last, data, len); + ctx->M_n = len; +} + +void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx) +{ + uint8_t K[16]; + uint8_t in[16]; + /* generate subkey K1 */ + memset1(K, '\0', 16); + + //rijndael_encrypt(&ctx->rijndael, K, K); + + aes_encrypt( K, K, &ctx->rijndael); + + if (K[0] & 0x80) { + LSHIFT(K, K); + K[15] ^= 0x87; + } else + LSHIFT(K, K); + + + if (ctx->M_n == 16) { + /* last block was a complete block */ + XOR(K, ctx->M_last); + + } else { + /* generate subkey K2 */ + if (K[0] & 0x80) { + LSHIFT(K, K); + K[15] ^= 0x87; + } else + LSHIFT(K, K); + + /* padding(M_last) */ + ctx->M_last[ctx->M_n] = 0x80; + while (++ctx->M_n < 16) + ctx->M_last[ctx->M_n] = 0; + + XOR(K, ctx->M_last); + + + } + XOR(ctx->M_last, ctx->X); + + //rijndael_encrypt(&ctx->rijndael, ctx->X, digest); + + memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten + aes_encrypt(in, digest, &ctx->rijndael); + memset1(K, 0, sizeof K); + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/crypto/cmac.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,63 @@ +/************************************************************************** +Copyright (C) 2009 Lander Casado, Philippas Tsigas + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files +(the "Software"), to deal with the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimers. Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimers in the documentation and/or +other materials provided with the distribution. + +In no event shall the authors or copyright holders be liable for any special, +incidental, indirect or consequential damages of any kind, or any damages +whatsoever resulting from loss of use, data or profits, whether or not +advised of the possibility of damage, and on any theory of liability, +arising out of or in connection with the use or performance of this software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS WITH THE SOFTWARE + +*****************************************************************************/ + +#ifndef _CMAC_H_ +#define _CMAC_H_ + +#include "aes.h" + +#define AES_CMAC_KEY_LENGTH 16 +#define AES_CMAC_DIGEST_LENGTH 16 + +typedef struct _AES_CMAC_CTX { + aes_context rijndael; + uint8_t X[16]; + uint8_t M_last[16]; + uint32_t M_n; + } AES_CMAC_CTX; + +//#include <sys/cdefs.h> + +//__BEGIN_DECLS +void AES_CMAC_Init(AES_CMAC_CTX * ctx); +void AES_CMAC_SetKey(AES_CMAC_CTX * ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]); +void AES_CMAC_Update(AES_CMAC_CTX * ctx, const uint8_t * data, uint32_t len); + // __attribute__((__bounded__(__string__,2,3))); +void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX * ctx); + // __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH))); +//__END_DECLS + +#endif /* _CMAC_H_ */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/mbed.bld Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/7c328cabac7e \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/timer.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,78 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: Timer objects and scheduling management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#include "board.h" + +Timer TimeCounter; +Ticker LoadTimeCounter; + +volatile uint32_t CurrentTime = 0; + +void TimerResetTimeCounter( void ) +{ + CurrentTime = CurrentTime + TimeCounter.read_us( ); + TimeCounter.reset( ); + TimeCounter.start( ); +} + +void TimerTimeCounterInit( void ) +{ + TimeCounter.start( ); + LoadTimeCounter.attach( &TimerResetTimeCounter, 10 ); +} + +TimerTime_t TimerGetCurrentTime( void ) +{ + CurrentTime += TimeCounter.read_us( ); + TimeCounter.reset( ); + TimeCounter.start( ); + return ( ( TimerTime_t )CurrentTime ); +} + +TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime ) +{ + CurrentTime += TimeCounter.read_us( ); + TimeCounter.reset( ); + TimeCounter.start( ); + return ( TimerTime_t )( CurrentTime - savedTime ); +} + +TimerTime_t TimerGetFutureTime( TimerTime_t eventInFuture ) +{ + CurrentTime += TimeCounter.read_us( ); + TimeCounter.reset( ); + TimeCounter.start( ); + return ( TimerTime_t )( CurrentTime + eventInFuture ); +} + +void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) ) +{ + obj->value = 0; + obj->Callback = callback; +} + +void TimerStart( TimerEvent_t *obj ) +{ + obj->Timer.attach_us( obj->Callback, obj->value ); +} + +void TimerStop( TimerEvent_t *obj ) +{ + obj->Timer.detach( ); +} + +void TimerSetValue( TimerEvent_t *obj, uint32_t value ) +{ + obj->value = value; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/timer.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,107 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: Timer objects and scheduling management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __TIMER_H__ +#define __TIMER_H__ + +#include "mbed.h" + +/*! + * \brief Timer object description + */ +typedef struct TimerEvent_s +{ + uint32_t value; + void ( *Callback )( void ); + Ticker Timer; +}TimerEvent_t; + +/*! + * \brief Timer time variable definition + */ +#ifndef TimerTime_t +typedef uint32_t TimerTime_t; +#endif + +/*! + * \brief Inializes the timer used to get current time. + * + * \remark Current time corresponds to the time since system startup + */ +void TimerTimeCounterInit( void ); + +/*! + * \brief Initializes the timer object + * + * \remark TimerSetValue function must be called before starting the timer. + * this function initializes timestamp and reload value at 0. + * + * \param [IN] obj Structure containing the timer object parameters + * \param [IN] callback Function callback called at the end of the timeout + */ +void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) ); + +/*! + * \brief Starts and adds the timer object to the list of timer events + * + * \param [IN] obj Structure containing the timer object parameters + */ +void TimerStart( TimerEvent_t *obj ); + +/*! + * \brief Stops and removes the timer object from the list of timer events + * + * \param [IN] obj Structure containing the timer object parameters + */ +void TimerStop( TimerEvent_t *obj ); + +/*! + * \brief Resets the timer object + * + * \param [IN] obj Structure containing the timer object parameters + */ +void TimerReset( TimerEvent_t *obj ); + +/*! + * \brief Set timer new timeout value + * + * \param [IN] obj Structure containing the timer object parameters + * \param [IN] value New timer timeout value + */ +void TimerSetValue( TimerEvent_t *obj, uint32_t value ); + +/*! + * \brief Read the current time + * + * \retval time returns current time + */ +TimerTime_t TimerGetCurrentTime( void ); + +/*! + * \brief Return the Time elapsed since a fix moment in Time + * + * \param [IN] savedTime fix moment in Time + * \retval time returns elapsed time + */ +TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime ); + +/*! + * \brief Return the Time elapsed since a fix moment in Time + * + * \param [IN] eventInFuture fix moment in the future + * \retval time returns difference between now and future event + */ +TimerTime_t TimerGetFutureTime( TimerTime_t eventInFuture ); + +#endif // __TIMER_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/utilities.cpp Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,85 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: Helper functions implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#include <stdlib.h> +#include <stdio.h> +#include "board.h" +#include "utilities.h" + +/*! + * Redefinition of rand() and srand() standard C functions. + * These functions are redefined in order to get the same behavior across + * different compiler toolchains implementations. + */ +// Standard random functions redefinition start +#define RAND_LOCAL_MAX 2147483647L + +static uint32_t next = 1; + +int32_t rand1( void ) +{ + return ( ( next = next * 1103515245L + 12345L ) % RAND_LOCAL_MAX ); +} + +void srand1( uint32_t seed ) +{ + next = seed; +} +// Standard random functions redefinition end + +int32_t randr( int32_t min, int32_t max ) +{ + return ( int32_t )rand1( ) % ( max - min + 1 ) + min; +} + +void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ) +{ + while( size-- ) + { + *dst++ = *src++; + } +} + +void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ) +{ + dst = dst + ( size - 1 ); + while( size-- ) + { + *dst-- = *src++; + } +} + +void memset1( uint8_t *dst, uint8_t value, uint16_t size ) +{ + while( size-- ) + { + *dst++ = value; + } +} + +int8_t Nibble2HexChar( uint8_t a ) +{ + if( a < 10 ) + { + return '0' + a; + } + else if( a < 16 ) + { + return 'A' + ( a - 10 ); + } + else + { + return '?'; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/utilities.h Fri Aug 26 19:36:35 2016 +0000 @@ -0,0 +1,99 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: Helper functions implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __UTILITIES_H__ +#define __UTILITIES_H__ + +/*! + * \brief Returns the minimum value betwen a and b + * + * \param [IN] a 1st value + * \param [IN] b 2nd value + * \retval minValue Minimum value + */ +#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) + +/*! + * \brief Returns the maximum value betwen a and b + * + * \param [IN] a 1st value + * \param [IN] b 2nd value + * \retval maxValue Maximum value + */ +#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) + +/*! + * \brief Returns 2 raised to the power of n + * + * \param [IN] n power value + * \retval result of raising 2 to the power n + */ +#define POW2( n ) ( 1 << n ) + +/*! + * \brief Initializes the pseudo ramdom generator initial value + * + * \param [IN] seed Pseudo ramdom generator initial value + */ +void srand1( uint32_t seed ); + +/*! + * \brief Computes a random number between min and max + * + * \param [IN] min range minimum value + * \param [IN] max range maximum value + * \retval random random value in range min..max + */ +int32_t randr( int32_t min, int32_t max ); + +/*! + * \brief Copies size elements of src array to dst array + * + * \remark STM32 Standard memcpy function only works on pointers that are aligned + * + * \param [OUT] dst Destination array + * \param [IN] src Source array + * \param [IN] size Number of bytes to be copied + */ +void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ); + +/*! + * \brief Copies size elements of src array to dst array reversing the byte order + * + * \param [OUT] dst Destination array + * \param [IN] src Source array + * \param [IN] size Number of bytes to be copied + */ +void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ); + +/*! + * \brief Set size elements of dst array with value + * + * \remark STM32 Standard memset function only works on pointers that are aligned + * + * \param [OUT] dst Destination array + * \param [IN] value Default value + * \param [IN] size Number of bytes to be copied + */ +void memset1( uint8_t *dst, uint8_t value, uint16_t size ); + +/*! + * \brief Converts a nibble to an hexadecimal character + * + * \param [IN] a Nibble to be converted + * \retval hexChar Converted hexadecimal character + */ +int8_t Nibble2HexChar( uint8_t a ); + +#endif // __UTILITIES_H__