Simple implementation of LoRaWAN-demo-76 by Semtech.

Dependencies:   mbed LoRaWAN-lib SX1276Lib

Dependents:   simple-demo-76_revised_20171113 simple-demo-76_revised_20171208

Fork of LoRaWAN-demo-76 by Semtech

Files at this revision

API Documentation at this revision

Comitter:
mluis
Date:
Thu Nov 26 12:59:52 2015 +0000
Parent:
0:92bca02df485
Child:
2:01e3c65c7c3a
Commit message:
Changed application architecture to mimic GitHub LoRaMac-node repository.

Changed in this revision

app/SerialDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
app/main.cpp Show annotated file Show diff for this revision Revisions of this file
board/board.cpp Show annotated file Show diff for this revision Revisions of this file
board/board.h Show annotated file Show diff for this revision Revisions of this file
mac/LoRaWAN-lib.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
radio/SX1276Lib.lib Show annotated file Show diff for this revision Revisions of this file
system/crypto/aes.cpp Show annotated file Show diff for this revision Revisions of this file
system/crypto/aes.h Show annotated file Show diff for this revision Revisions of this file
system/crypto/cmac.cpp Show annotated file Show diff for this revision Revisions of this file
system/crypto/cmac.h Show annotated file Show diff for this revision Revisions of this file
system/timer.cpp Show annotated file Show diff for this revision Revisions of this file
system/timer.h Show annotated file Show diff for this revision Revisions of this file
system/utilities.cpp Show annotated file Show diff for this revision Revisions of this file
system/utilities.h Show annotated file Show diff for this revision Revisions of this file
--- a/app/SerialDisplay.cpp	Tue Oct 20 13:23:35 2015 +0000
+++ b/app/SerialDisplay.cpp	Thu Nov 26 12:59:52 2015 +0000
@@ -16,27 +16,6 @@
 #include "vt100.h"
 #include "SerialDisplay.h"
 
-//extern struct sLoRaMacUplinkStatus
-//{
-//    uint8_t Acked;
-//    int8_t Datarate;
-//    uint16_t UplinkCounter;
-//    uint8_t Port;
-//    uint8_t *Buffer;
-//    uint8_t BufferSize;
-//}LoRaMacUplinkStatus;
-//
-//extern struct sLoRaMacDownlinkStatus
-//{
-//    int16_t Rssi;
-//    int8_t Snr;
-//    uint16_t DownlinkCounter;
-//    bool RxData;
-//    uint8_t Port;
-//    uint8_t *Buffer;
-//    uint8_t BufferSize;
-//}LoRaMacDownlinkStatus;
-
 VT100 vt( USBTX, USBRX );
 
 void SerialPrintCheckBox( bool activated, uint8_t color )
--- a/app/main.cpp	Tue Oct 20 13:23:35 2015 +0000
+++ b/app/main.cpp	Thu Nov 26 12:59:52 2015 +0000
@@ -43,19 +43,19 @@
  *
  * \remark must be written as a little endian value (reverse order of normal reading)
  */
-#define LORAWAN_DEVICE_EUI                          { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }
+#define LORAWAN_DEVICE_EUI                          { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }
 
 /*!
  * Application IEEE EUI
  *
  * \remark must be written as a little endian value (reverse order of normal reading)
  */
-#define LORAWAN_APPLICATION_EUI                     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+#define LORAWAN_APPLICATION_EUI                     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
 
 /*!
  * AES encryption/decryption cipher application key
  */
-#define LORAWAN_APPLICATION_KEY                     { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 }
+#define LORAWAN_APPLICATION_KEY                     { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01 }
 
 #else
 
@@ -69,25 +69,30 @@
  *
  * \remark must be written as a big endian value (normal reading order)
  */
-#define LORAWAN_DEVICE_ADDRESS                      ( uint32_t )0x12345678
+#define LORAWAN_DEVICE_ADDRESS                      ( uint32_t )0xFF000001
 
 /*!
  * 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 }
+#define LORAWAN_NWKSKEY                             { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01 }
 
 /*!
  * 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 }
+#define LORAWAN_APPSKEY                             { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01 }
 
 #endif
 
 /*!
- * Defines the application data transmission duty cycle
+ * Defines the application data transmission duty cycle. 5s, value in [us].
  */
-#define APP_TX_DUTYCYCLE                            5000000  // 5 [s] value in us
-#define APP_TX_DUTYCYCLE_RND                        1000000  // 1 [s] value in us
+#define APP_TX_DUTYCYCLE                            5000000
+
+/*!
+ * Defines a random delay for application data transmission duty cycle. 1s,
+ * value in [us].
+ */
+#define APP_TX_DUTYCYCLE_RND                        1000000
 
 /*!
  * LoRaWAN confirmed messages
@@ -101,6 +106,8 @@
  */
 #define LORAWAN_ADR_ON                              1
 
+#if defined( USE_BAND_868 )
+
 /*!
  * LoRaWAN ETSI duty cycle control enable/disable
  *
@@ -108,6 +115,8 @@
  */
 #define LORAWAN_DUTYCYCLE_ON                        false
 
+#endif
+
 /*!
  * LoRaWAN application port
  */
@@ -144,23 +153,46 @@
 static bool IsNetworkJoinedStatusUpdate = false;
 
 /*!
+ * Application port
+ */
+static uint8_t AppPort = LORAWAN_APP_PORT;
+
+/*!
+ * User application data size
+ */
+static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE;
+
+/*!
+ * User application data buffer size
+ */
+#define LORAWAN_APP_DATA_MAX_SIZE                           64
+
+/*!
  * User application data
  */
-static uint8_t AppData[LORAWAN_APP_DATA_SIZE];
+static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
+
+/*!
+ * Indicates if the node is sending confirmed or unconfirmed messages
+ */
+static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
 
 /*!
  * Defines the application data transmission duty cycle
  */
 static uint32_t TxDutyCycleTime;
 
-TimerEvent_t TxNextPacketTimer;
+/*!
+ * Timer to handle the application data transmission duty cycle
+ */
+static TimerEvent_t TxNextPacketTimer;
 
 #if( OVER_THE_AIR_ACTIVATION != 0 )
 
 /*!
  * Defines the join request timer
  */
-TimerEvent_t JoinReqTimer;
+static TimerEvent_t JoinReqTimer;
 
 #endif
 
@@ -170,20 +202,28 @@
 static bool TxNextPacket = true;
 static bool ScheduleNextTx = false;
 
-static bool AppLedStateOn = false;
+static LoRaMacCallbacks_t LoRaMacCallbacks;
 
-static LoRaMacEvent_t LoRaMacEvents;
-
-TimerEvent_t Led1Timer;
+static TimerEvent_t Led1Timer;
+volatile bool Led1State = false;
 volatile bool Led1StateChanged = false;
 
-TimerEvent_t Led2Timer;
+static TimerEvent_t Led2Timer;
+volatile bool Led2State = false;
 volatile bool Led2StateChanged = false;
 
+static bool AppLedStateOn = false;
 volatile bool Led3StateChanged = false;
 
 volatile bool LinkStatusUpdated = false;
 
+static bool ComplianceTestOn = false;
+static uint8_t ComplianceTestState = 0;
+static uint16_t ComplianceTestDownLinkCounter = 0;
+static bool ComplianceTestLinkCheck = false;
+static uint8_t ComplianceTestDemodMargin = 0;
+static uint8_t ComplianceTestNbGateways = 0;
+
 struct sLoRaMacUplinkStatus
 {
     uint8_t Acked;
@@ -223,7 +263,11 @@
     SerialDisplayUpdateNetworkIsJoined( IsNetworkJoined );
 
     SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
+#if defined( USE_BAND_868 )
     SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
+#else
+    SerialDisplayUpdateDutyCycle( false );
+#endif
     SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
     
     SerialDisplayUpdateLedState( 3, AppLedStateOn );
@@ -251,14 +295,47 @@
  */
 static void PrepareTxFrame( uint8_t port )
 {
-    AppData[0] = AppLedStateOn;
-#if ( LORAWAN_CONFIRMED_MSG_ON == true )
-    AppData[1] = LoRaMacDownlinkStatus.DownlinkCounter >> 8;
-    AppData[2] = LoRaMacDownlinkStatus.DownlinkCounter;
-    AppData[3] = LoRaMacDownlinkStatus.Rssi >> 8;
-    AppData[4] = LoRaMacDownlinkStatus.Rssi;
-    AppData[5] = LoRaMacDownlinkStatus.Snr;
-#endif
+    switch( port )
+    {
+    case 15:
+        {
+            AppData[0] = AppLedStateOn;
+            if( IsTxConfirmed == true )
+            {
+                AppData[1] = LoRaMacDownlinkStatus.DownlinkCounter >> 8;
+                AppData[2] = LoRaMacDownlinkStatus.DownlinkCounter;
+                AppData[3] = LoRaMacDownlinkStatus.Rssi >> 8;
+                AppData[4] = LoRaMacDownlinkStatus.Rssi;
+                AppData[5] = LoRaMacDownlinkStatus.Snr;
+            }
+        }
+        break;
+    case 224:
+        if( ComplianceTestLinkCheck == true )
+        {
+            ComplianceTestLinkCheck = false;
+            AppDataSize = 3;
+            AppData[0] = 5;
+            AppData[1] = ComplianceTestDemodMargin;
+            AppData[2] = ComplianceTestNbGateways;
+            ComplianceTestState = 1;
+        }
+        else
+        {
+            switch( ComplianceTestState )
+            {
+            case 4:
+                ComplianceTestState = 1;
+                break;
+            case 1:
+                AppDataSize = 2;
+                AppData[0] = ComplianceTestDownLinkCounter >> 8;
+                AppData[1] = ComplianceTestDownLinkCounter;
+                break;
+            }
+        }
+        break;
+    }
 }
 
 static void ProcessRxFrame( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info )
@@ -273,6 +350,84 @@
                 Led3StateChanged = true;
             }
             break;
+        case 224:
+            if( ComplianceTestOn == false )
+            {
+                // Check compliance test enable command (i)
+                if( ( info->RxBufferSize == 4 ) && 
+                    ( info->RxBuffer[0] == 0x01 ) &&
+                    ( info->RxBuffer[1] == 0x01 ) &&
+                    ( info->RxBuffer[2] == 0x01 ) &&
+                    ( info->RxBuffer[3] == 0x01 ) )
+                {
+                    IsTxConfirmed = false;
+                    AppPort = 224;
+                    AppDataSize = 2;
+                    ComplianceTestDownLinkCounter = 0;
+                    ComplianceTestLinkCheck = false;
+                    ComplianceTestDemodMargin = 0;
+                    ComplianceTestNbGateways = 0;
+                    ComplianceTestOn = true;
+                    ComplianceTestState = 1;
+                    
+                    LoRaMacSetAdrOn( true );
+#if defined( USE_BAND_868 )
+                    LoRaMacTestSetDutyCycleOn( false );
+#endif
+                }
+            }
+            else
+            {
+                ComplianceTestState = info->RxBuffer[0];
+                switch( ComplianceTestState )
+                {
+                case 0: // Check compliance test disable command (ii)
+                    IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
+                    AppPort = LORAWAN_APP_PORT;
+                    if( IsTxConfirmed == true )
+                    {
+                        AppDataSize = 6;
+                    }
+                    else
+                    {
+                        AppDataSize = 1;
+                    }
+                    ComplianceTestDownLinkCounter = 0;
+                    ComplianceTestOn = false;
+                    
+                    LoRaMacSetAdrOn( LORAWAN_ADR_ON );
+#if defined( USE_BAND_868 )
+                    LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
+#endif
+                    break;
+                case 1: // (iii, iv)
+                    AppDataSize = 2;
+                    break;
+                case 2: // Enable confirmed messages (v)
+                    IsTxConfirmed = true;
+                    ComplianceTestState = 1;
+                    break;
+                case 3:  // Disable confirmed messages (vi)
+                    IsTxConfirmed = false;
+                    ComplianceTestState = 1;
+                    break;
+                case 4: // (vii)
+                    AppDataSize = info->RxBufferSize;
+
+                    AppData[0] = 4;
+                    for( uint8_t i = 1; i < AppDataSize; i++ )
+                    {
+                        AppData[i] = info->RxBuffer[i] + 1;
+                    }
+                    break;
+                case 5: // (viii)
+                    LoRaMacLinkCheckReq( );
+                    break;
+                default:
+                    break;
+                }
+            }
+            break;
         default:
             break;
     }
@@ -283,16 +438,21 @@
     uint8_t sendFrameStatus = 0;
 
     LoRaMacUplinkStatus.Acked = false;
-    LoRaMacUplinkStatus.Port = LORAWAN_APP_PORT;
+    LoRaMacUplinkStatus.Port = AppPort;
     LoRaMacUplinkStatus.Buffer = AppData;
-    LoRaMacUplinkStatus.BufferSize = LORAWAN_APP_DATA_SIZE;
+    LoRaMacUplinkStatus.BufferSize = AppDataSize;
     
-    SerialDisplayUpdateFrameType( LORAWAN_CONFIRMED_MSG_ON );
-#if( LORAWAN_CONFIRMED_MSG_ON == false )
-    sendFrameStatus = LoRaMacSendFrame( LORAWAN_APP_PORT, AppData, LORAWAN_APP_DATA_SIZE );
-#else
-    sendFrameStatus = LoRaMacSendConfirmedFrame( LORAWAN_APP_PORT, AppData, LORAWAN_APP_DATA_SIZE, 8 );
-#endif
+    SerialDisplayUpdateFrameType( IsTxConfirmed );
+
+    if( IsTxConfirmed == false )
+    {
+        sendFrameStatus = LoRaMacSendFrame( AppPort, AppData, AppDataSize );
+    }
+    else
+    {
+        sendFrameStatus = LoRaMacSendConfirmedFrame( AppPort, AppData, AppDataSize, 8 );
+    }
+
     switch( sendFrameStatus )
     {
     case 5: // NO_FREE_CHANNEL
@@ -331,6 +491,7 @@
 static void OnLed1TimerEvent( void )
 {
     TimerStop( &Led1Timer );
+    Led1State = false;
     Led1StateChanged = true;
 }
 
@@ -340,6 +501,7 @@
 static void OnLed2TimerEvent( void )
 {
     TimerStop( &Led2Timer );
+    Led2State = false;
     Led2StateChanged = true;
 }
 
@@ -364,6 +526,16 @@
 
         if( flags->Bits.Rx == 1 )
         {
+            if( ComplianceTestOn == true )
+            {
+                ComplianceTestDownLinkCounter++;
+                if( flags->Bits.LinkCheck == 1 )
+                {
+                    ComplianceTestLinkCheck = true;
+                    ComplianceTestDemodMargin = info->DemodMargin;
+                    ComplianceTestNbGateways = info->NbGateways;
+                }
+            }
             if( flags->Bits.RxData == true )
             {
                 ProcessRxFrame( flags, info );
@@ -387,14 +559,17 @@
             LoRaMacDownlinkStatus.Buffer = info->RxBuffer;
             LoRaMacDownlinkStatus.BufferSize = info->RxBufferSize;
             
-            LoRaMacUplinkStatus.Acked = info->TxAckReceived;
-            LoRaMacUplinkStatus.Datarate = info->TxDatarate;
-            LoRaMacUplinkStatus.UplinkCounter = LoRaMacGetUpLinkCounter( ) - 1;
-            
-            LinkStatusUpdated = true;
+            Led2State = true;
+            Led2StateChanged = true;
             TimerStart( &Led2Timer );
         }
+        
+        LoRaMacUplinkStatus.Acked = info->TxAckReceived;
+        LoRaMacUplinkStatus.Datarate = info->TxDatarate;
+        LoRaMacUplinkStatus.UplinkCounter = LoRaMacGetUpLinkCounter( ) - 1;
     }
+
+    LinkStatusUpdated = true;
     // Schedule a new transmission
     ScheduleNextTx = true;
 }
@@ -413,8 +588,9 @@
 
     BoardInit( );
 
-    LoRaMacEvents.MacEvent = OnMacEvent;
-    LoRaMacInit( &LoRaMacEvents, &BoardGetBatterieLevel );
+    LoRaMacCallbacks.MacEvent = OnMacEvent;
+    LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
+    LoRaMacInit( &LoRaMacCallbacks );
 
     IsNetworkJoined = false;
 
@@ -451,11 +627,17 @@
     TimerSetValue( &Led2Timer, 500000 );
 
     LoRaMacSetAdrOn( LORAWAN_ADR_ON );
+#if defined( USE_BAND_868 )
     LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
+#endif
     LoRaMacSetPublicNetwork( LORAWAN_PUBLIC_NETWORK );
 
     SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
+#if defined( USE_BAND_868 )
     SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
+#else
+    SerialDisplayUpdateDutyCycle( false );
+#endif
     SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
     
     LoRaMacDownlinkStatus.DownlinkCounter = 0;
@@ -499,12 +681,12 @@
         if( Led1StateChanged == true )
         {
             Led1StateChanged = false;
-            SerialDisplayUpdateLedState( 1, 0 );
+            SerialDisplayUpdateLedState( 1, Led1State );
         }
         if( Led2StateChanged == true )
         {
             Led2StateChanged = false;
-            SerialDisplayUpdateLedState( 2, 0 );
+            SerialDisplayUpdateLedState( 2, Led2State );
         }
         if( Led3StateChanged == true )
         {
@@ -514,7 +696,7 @@
         if( LinkStatusUpdated == true )
         {
             LinkStatusUpdated = false;
-            SerialDisplayUpdateLedState( 2, 1 );
+            SerialDisplayUpdateLedState( 2, Led2State );
             SerialDisplayUpdateUplink( LoRaMacUplinkStatus.Acked, LoRaMacUplinkStatus.Datarate, LoRaMacUplinkStatus.UplinkCounter, LoRaMacUplinkStatus.Port, LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize );
             SerialDisplayUpdateDownlink( LoRaMacDownlinkStatus.RxData, LoRaMacDownlinkStatus.Rssi, LoRaMacDownlinkStatus.Snr, LoRaMacDownlinkStatus.DownlinkCounter, LoRaMacDownlinkStatus.Port, LoRaMacDownlinkStatus.Buffer, LoRaMacDownlinkStatus.BufferSize );
         }
@@ -522,10 +704,18 @@
         if( ScheduleNextTx == true )
         {
             ScheduleNextTx = false;
-            // Schedule next packet transmission
-            TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
-            TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
-            TimerStart( &TxNextPacketTimer );
+ 
+//            if( ComplianceTestOn == true )
+//            {
+//                TxNextPacket = true;
+//            }
+//            else
+//            {
+                // Schedule next packet transmission
+                TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
+                TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
+                TimerStart( &TxNextPacketTimer );
+//            }
         }
 
         if( trySendingFrameAgain == true )
@@ -538,9 +728,10 @@
         
             SerialDisplayUpdateDonwlinkRxData( false );
             
-            PrepareTxFrame( LORAWAN_APP_PORT );
+            PrepareTxFrame( AppPort );
             
-            SerialDisplayUpdateLedState( 1, 1 );
+            Led1State = true;
+            SerialDisplayUpdateLedState( 1, Led1State );
             TimerStart( &Led1Timer );
 
             trySendingFrameAgain = SendFrame( );
--- a/board/board.cpp	Tue Oct 20 13:23:35 2015 +0000
+++ b/board/board.cpp	Thu Nov 26 12:59:52 2015 +0000
@@ -15,13 +15,15 @@
 #include "mbed.h"
 #include "board.h"
 
+SX1276MB1xAS Radio( NULL );
+
 void BoardInit( void )
 {
     TimerTimeCounterInit( );
 }
 
 
-uint8_t BoardGetBatterieLevel( void ) 
+uint8_t BoardGetBatteryLevel( void ) 
 {
     return 0xFE;
 }
--- a/board/board.h	Tue Oct 20 13:23:35 2015 +0000
+++ b/board/board.h	Thu Nov 26 12:59:52 2015 +0000
@@ -16,9 +16,14 @@
 #define __BOARD_H__
 
 #include "mbed.h"
-#include "timer.h"
+#include "system/timer.h"
 #include "debug.h"
-#include "utilities.h"
+#include "system/utilities.h"
+#include "sx1276-hal.h"
+
+#define USE_BAND_915_HYBRID
+
+extern SX1276MB1xAS Radio;
 
 /*!
  * \brief Initializes the target board peripherals.
@@ -30,7 +35,7 @@
  *
  * \retval value  battery level ( 0: very low, 254: fully charged )
  */
-uint8_t BoardGetBatterieLevel( void );
+uint8_t BoardGetBatteryLevel( void );
 
 
 #endif // __BOARD_H__
--- a/mac/LoRaWAN-lib.lib	Tue Oct 20 13:23:35 2015 +0000
+++ b/mac/LoRaWAN-lib.lib	Thu Nov 26 12:59:52 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/teams/Semtech/code/LoRaWAN-lib/#91d1a7783bb9
+http://developer.mbed.org/teams/Semtech/code/LoRaWAN-lib/#91e4e6c60d1e
--- a/mbed.bld	Tue Oct 20 13:23:35 2015 +0000
+++ b/mbed.bld	Thu Nov 26 12:59:52 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/34e6b704fe68
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/165afa46840b
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/radio/SX1276Lib.lib	Thu Nov 26 12:59:52 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/Semtech/code/SX1276Lib/#2e496deb7858
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/crypto/aes.cpp	Thu Nov 26 12:59:52 2015 +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 1
+#  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	Thu Nov 26 12:59:52 2015 +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	Thu Nov 26 12:59:52 2015 +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	Thu Nov 26 12:59:52 2015 +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/timer.cpp	Thu Nov 26 12:59:52 2015 +0000
@@ -0,0 +1,62 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (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 );
+}
+
+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	Thu Nov 26 12:59:52 2015 +0000
@@ -0,0 +1,92 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (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 );
+
+
+#endif // __TIMER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/utilities.cpp	Thu Nov 26 12:59:52 2015 +0000
@@ -0,0 +1,76 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (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 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	Thu Nov 26 12:59:52 2015 +0000
@@ -0,0 +1,90 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (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 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__