first draft

Dependencies:   LMiC SX1272Libx mbed

Fork of LoRaWAN-lmic-app by Semtech

Committer:
tmulrooney
Date:
Fri Feb 26 13:27:54 2016 +0000
Revision:
10:497ef83ca19f
Parent:
9:0b63a0a90205
version 0.1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sam_grove 3:ce28e3313a88 1 /*
mluis 0:a2929fa6e4f0 2 / _____) _ | |
mluis 0:a2929fa6e4f0 3 ( (____ _____ ____ _| |_ _____ ____| |__
mluis 0:a2929fa6e4f0 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
mluis 0:a2929fa6e4f0 5 _____) ) ____| | | || |_| ____( (___| | | |
mluis 0:a2929fa6e4f0 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
mluis 1:60184eda0066 7 (C)2015 Semtech
mluis 0:a2929fa6e4f0 8
mluis 1:60184eda0066 9 Description: MBED LoRaWAN example application
mluis 0:a2929fa6e4f0 10
mluis 0:a2929fa6e4f0 11 License: Revised BSD License, see LICENSE.TXT file include in the project
mluis 0:a2929fa6e4f0 12
mluis 0:a2929fa6e4f0 13 Maintainer: Miguel Luis and Gregory Cristian
mluis 0:a2929fa6e4f0 14 */
mluis 1:60184eda0066 15 #include "mbed.h"
mluis 1:60184eda0066 16
mluis 0:a2929fa6e4f0 17 #include "lmic.h"
mluis 1:60184eda0066 18 #include "debug.h"
mluis 0:a2929fa6e4f0 19
mluis 0:a2929fa6e4f0 20 /*!
mluis 0:a2929fa6e4f0 21 * When set to 1 the application uses the Over-the-Air activation procedure
mluis 0:a2929fa6e4f0 22 * When set to 0 the application uses the Personalization activation procedure
mluis 0:a2929fa6e4f0 23 */
tmulrooney 6:fc465060b63e 24 #define OVER_THE_AIR_ACTIVATION 1
mluis 0:a2929fa6e4f0 25
mluis 1:60184eda0066 26 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 1:60184eda0066 27
mluis 1:60184eda0066 28 /*!
mluis 1:60184eda0066 29 * Defines the network ID when using personalization activation procedure
mluis 1:60184eda0066 30 */
mluis 1:60184eda0066 31 #define LORAWAN_NET_ID ( uint32_t )0x00000000
mluis 1:60184eda0066 32
mluis 1:60184eda0066 33 /*!
mluis 1:60184eda0066 34 * Defines the device address when using personalization activation procedure
mluis 1:60184eda0066 35 */
mluis 1:60184eda0066 36 #define LORAWAN_DEV_ADDR ( uint32_t )0x12345678
mluis 1:60184eda0066 37
mluis 1:60184eda0066 38 #endif
mluis 1:60184eda0066 39
mluis 1:60184eda0066 40 /*!
mluis 1:60184eda0066 41 * Defines the application data transmission duty cycle
mluis 1:60184eda0066 42 */
mluis 1:60184eda0066 43 #define APP_TX_DUTYCYCLE 5000 // 5 [s] value in ms
mluis 1:60184eda0066 44 #define APP_TX_DUTYCYCLE_RND 1000 // 1 [s] value in ms
mluis 1:60184eda0066 45
mluis 1:60184eda0066 46 /*!
mluis 1:60184eda0066 47 * LoRaWAN Adaptative Data Rate
mluis 1:60184eda0066 48 */
mluis 1:60184eda0066 49 #define LORAWAN_ADR_ON 1
mluis 1:60184eda0066 50
mluis 1:60184eda0066 51 /*!
mluis 1:60184eda0066 52 * LoRaWAN confirmed messages
mluis 1:60184eda0066 53 */
mluis 1:60184eda0066 54 #define LORAWAN_CONFIRMED_MSG_ON 1
mluis 1:60184eda0066 55
mluis 1:60184eda0066 56 /*!
mluis 1:60184eda0066 57 * LoRaWAN application port
mluis 1:60184eda0066 58 */
mluis 1:60184eda0066 59 #define LORAWAN_APP_PORT 15
mluis 1:60184eda0066 60
mluis 1:60184eda0066 61 /*!
mluis 1:60184eda0066 62 * User application data buffer size
mluis 1:60184eda0066 63 */
mluis 1:60184eda0066 64 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
mluis 1:60184eda0066 65 #define LORAWAN_APP_DATA_SIZE 6
mluis 1:60184eda0066 66
mluis 1:60184eda0066 67 #else
mluis 1:60184eda0066 68 #define LORAWAN_APP_DATA_SIZE 1
mluis 1:60184eda0066 69
mluis 1:60184eda0066 70 #endif
tmulrooney 6:fc465060b63e 71 Serial pc(PTE0, PTE1);
tmulrooney 8:0137acc9a6cd 72 #define LED_RED PTA1
tmulrooney 8:0137acc9a6cd 73 #define LED_YEL PTA2
tmulrooney 8:0137acc9a6cd 74
tmulrooney 10:497ef83ca19f 75 /* version history */
tmulrooney 10:497ef83ca19f 76 /* version date comments */
tmulrooney 10:497ef83ca19f 77 /* 0.1 02/26/16 first working join - no tx/rx */
tmulrooney 10:497ef83ca19f 78
tmulrooney 10:497ef83ca19f 79 #define MAJOR 0
tmulrooney 10:497ef83ca19f 80 #define MINOR 1
tmulrooney 10:497ef83ca19f 81
tmulrooney 8:0137acc9a6cd 82 DigitalOut led1(LED_RED);
tmulrooney 8:0137acc9a6cd 83 DigitalOut led2(LED_YEL);
mluis 0:a2929fa6e4f0 84
mluis 0:a2929fa6e4f0 85 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 86 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
mluis 0:a2929fa6e4f0 87 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 88 // application router ID (LSBF)
tmulrooney 8:0137acc9a6cd 89 //static const u1_t AppEui[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
tmulrooney 8:0137acc9a6cd 90 static const u1_t AppEui[8] = { 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 };
mluis 0:a2929fa6e4f0 91
mluis 0:a2929fa6e4f0 92 // unique device ID (LSBF)
tmulrooney 6:fc465060b63e 93 static const u1_t DevEui[8] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0xee, 0xff, 0xc0 };
mluis 0:a2929fa6e4f0 94
mluis 0:a2929fa6e4f0 95 // device-specific AES key (derived from device EUI)
tmulrooney 6:fc465060b63e 96 static const u1_t DevKey[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, };
tmulrooney 6:fc465060b63e 97 // E4 -72 -71 -C5 -F5 -30 -A9 -9F -CF -C4 -0E -AB -EA -D7 -19 -42
mluis 1:60184eda0066 98 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 1:60184eda0066 99 // network session key
mluis 0:a2929fa6e4f0 100 static uint8_t NwkSKey[] =
mluis 0:a2929fa6e4f0 101 {
mluis 0:a2929fa6e4f0 102 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
mluis 0:a2929fa6e4f0 103 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
mluis 0:a2929fa6e4f0 104 };
mluis 0:a2929fa6e4f0 105
mluis 1:60184eda0066 106 // application session key
mluis 0:a2929fa6e4f0 107 static uint8_t ArtSKey[] =
mluis 0:a2929fa6e4f0 108 {
mluis 0:a2929fa6e4f0 109 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
mluis 0:a2929fa6e4f0 110 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
mluis 0:a2929fa6e4f0 111 };
mluis 0:a2929fa6e4f0 112
mluis 1:60184eda0066 113 #endif
mluis 1:60184eda0066 114
mluis 0:a2929fa6e4f0 115 // LEDs and Frame jobs
mluis 0:a2929fa6e4f0 116 osjob_t rxLedJob;
mluis 0:a2929fa6e4f0 117 osjob_t txLedJob;
mluis 0:a2929fa6e4f0 118 osjob_t sendFrameJob;
mluis 0:a2929fa6e4f0 119
mluis 1:60184eda0066 120 // LED state
mluis 0:a2929fa6e4f0 121 static bool AppLedStateOn = false;
mluis 0:a2929fa6e4f0 122
mluis 0:a2929fa6e4f0 123 //////////////////////////////////////////////////
mluis 1:60184eda0066 124 // Utility functions
mluis 1:60184eda0066 125 //////////////////////////////////////////////////
mluis 1:60184eda0066 126 /*!
mluis 1:60184eda0066 127 * \brief Computes a random number between min and max
mluis 1:60184eda0066 128 *
mluis 1:60184eda0066 129 * \param [IN] min range minimum value
mluis 1:60184eda0066 130 * \param [IN] max range maximum value
mluis 1:60184eda0066 131 * \retval random random value in range min..max
mluis 1:60184eda0066 132 */
mluis 1:60184eda0066 133 int32_t randr( int32_t min, int32_t max )
mluis 1:60184eda0066 134 {
mluis 1:60184eda0066 135 return ( int32_t )rand( ) % ( max - min + 1 ) + min;
mluis 1:60184eda0066 136 }
mluis 1:60184eda0066 137
mluis 1:60184eda0066 138 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 139 // APPLICATION CALLBACKS
mluis 0:a2929fa6e4f0 140 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 141
mluis 0:a2929fa6e4f0 142 // provide application router ID (8 bytes, LSBF)
mluis 1:60184eda0066 143 void os_getArtEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 144 {
mluis 0:a2929fa6e4f0 145 memcpy( buf, AppEui, 8 );
tmulrooney 6:fc465060b63e 146 debug("os_getArtEui enter");
tmulrooney 6:fc465060b63e 147 for(int i=0;i<8;i++)
tmulrooney 6:fc465060b63e 148 debug(" %02X",buf[i]);
tmulrooney 6:fc465060b63e 149 debug("\r\n");
mluis 0:a2929fa6e4f0 150 }
mluis 0:a2929fa6e4f0 151
mluis 0:a2929fa6e4f0 152 // provide device ID (8 bytes, LSBF)
mluis 1:60184eda0066 153 void os_getDevEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 154 {
mluis 0:a2929fa6e4f0 155 memcpy( buf, DevEui, 8 );
tmulrooney 6:fc465060b63e 156 debug("os_getDevEui enter");
tmulrooney 6:fc465060b63e 157 for(int i=0;i<8;i++)
tmulrooney 6:fc465060b63e 158 debug(" %02X",buf[i]);
tmulrooney 6:fc465060b63e 159 debug("\r\n");
mluis 0:a2929fa6e4f0 160 }
mluis 0:a2929fa6e4f0 161
mluis 0:a2929fa6e4f0 162 // provide device key (16 bytes)
mluis 1:60184eda0066 163 void os_getDevKey( uint8_t *buf )
mluis 0:a2929fa6e4f0 164 {
mluis 0:a2929fa6e4f0 165 memcpy( buf, DevKey, 16 );
tmulrooney 6:fc465060b63e 166 debug("os_getDevKey enter");
tmulrooney 6:fc465060b63e 167 for(int i=0;i<16;i++)
tmulrooney 6:fc465060b63e 168 debug(" %02X",buf[i]);
tmulrooney 6:fc465060b63e 169 debug("\r\n");
mluis 0:a2929fa6e4f0 170 }
mluis 0:a2929fa6e4f0 171
mluis 0:a2929fa6e4f0 172 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 173 // MAIN - INITIALIZATION AND STARTUP
mluis 0:a2929fa6e4f0 174 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 175
mluis 0:a2929fa6e4f0 176 static void onRxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 177 {
tmulrooney 10:497ef83ca19f 178 led2 = 0;
mluis 1:60184eda0066 179 debug_val("LED2 = ", 0 );
mluis 0:a2929fa6e4f0 180 }
mluis 0:a2929fa6e4f0 181
mluis 0:a2929fa6e4f0 182 static void onTxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 183 {
tmulrooney 9:0b63a0a90205 184 led1 = 0;
mluis 1:60184eda0066 185 debug_val("LED1 = ", 0 );
mluis 0:a2929fa6e4f0 186 }
mluis 0:a2929fa6e4f0 187
mluis 0:a2929fa6e4f0 188 static void prepareTxFrame( void )
mluis 0:a2929fa6e4f0 189 {
mluis 0:a2929fa6e4f0 190 LMIC.frame[0] = AppLedStateOn;
mluis 1:60184eda0066 191 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
mluis 1:60184eda0066 192 LMIC.frame[1] = LMIC.seqnoDn >> 8;
mluis 1:60184eda0066 193 LMIC.frame[2] = LMIC.seqnoDn;
mluis 1:60184eda0066 194 LMIC.frame[3] = LMIC.rssi >> 8;
mluis 1:60184eda0066 195 LMIC.frame[4] = LMIC.rssi;
mluis 1:60184eda0066 196 LMIC.frame[5] = LMIC.snr;
mluis 1:60184eda0066 197 #endif
mluis 0:a2929fa6e4f0 198 }
mluis 0:a2929fa6e4f0 199
mluis 0:a2929fa6e4f0 200 void processRxFrame( void )
mluis 0:a2929fa6e4f0 201 {
tmulrooney 6:fc465060b63e 202 debug("processRxFrame enter\r\n");
tmulrooney 6:fc465060b63e 203 switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number
mluis 0:a2929fa6e4f0 204 {
mluis 0:a2929fa6e4f0 205 case 1: // The application LED can be controlled on port 1 or 2
mluis 0:a2929fa6e4f0 206 case 2:
mluis 0:a2929fa6e4f0 207 if( LMIC.dataLen == 1 )
mluis 0:a2929fa6e4f0 208 {
mluis 0:a2929fa6e4f0 209 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
mluis 1:60184eda0066 210 debug_val( "LED3 = ", AppLedStateOn );
mluis 0:a2929fa6e4f0 211 }
mluis 0:a2929fa6e4f0 212 break;
mluis 0:a2929fa6e4f0 213 default:
mluis 0:a2929fa6e4f0 214 break;
mluis 0:a2929fa6e4f0 215 }
mluis 0:a2929fa6e4f0 216 }
mluis 0:a2929fa6e4f0 217
mluis 0:a2929fa6e4f0 218 static void onSendFrame( osjob_t* j )
mluis 0:a2929fa6e4f0 219 {
tmulrooney 6:fc465060b63e 220 debug("onSendFrame enter\r\n");
mluis 0:a2929fa6e4f0 221 prepareTxFrame( );
mluis 1:60184eda0066 222 LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LORAWAN_APP_DATA_SIZE, LORAWAN_CONFIRMED_MSG_ON );
mluis 1:60184eda0066 223
mluis 1:60184eda0066 224 // Blink Tx LED
tmulrooney 9:0b63a0a90205 225 led1 = 1;
mluis 1:60184eda0066 226 debug_val( "LED1 = ", 1 );
mluis 1:60184eda0066 227 os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
mluis 0:a2929fa6e4f0 228 }
mluis 0:a2929fa6e4f0 229
tmulrooney 8:0137acc9a6cd 230 #if 1
mluis 1:60184eda0066 231 // Initialization job
mluis 1:60184eda0066 232 static void onInit( osjob_t* j )
mluis 1:60184eda0066 233 {
tmulrooney 6:fc465060b63e 234 debug("onInit enter\r\n");
mluis 1:60184eda0066 235 // reset MAC state
mluis 1:60184eda0066 236 LMIC_reset( );
mluis 1:60184eda0066 237 LMIC_setAdrMode( LORAWAN_ADR_ON );
mluis 5:1b2fcc2582e8 238 #if defined(CFG_eu868)
mluis 1:60184eda0066 239 LMIC_setDrTxpow( DR_SF12, 14 );
mluis 5:1b2fcc2582e8 240 #elif defined(CFG_us915)
mluis 5:1b2fcc2582e8 241 LMIC_setDrTxpow( DR_SF10, 14 );
mluis 5:1b2fcc2582e8 242 #endif
mluis 1:60184eda0066 243
mluis 1:60184eda0066 244 // start joining
mluis 1:60184eda0066 245 #if( OVER_THE_AIR_ACTIVATION != 0 )
mluis 1:60184eda0066 246 LMIC_startJoining( );
mluis 1:60184eda0066 247 #else
mluis 1:60184eda0066 248 LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey );
mluis 1:60184eda0066 249 onSendFrame( NULL );
mluis 1:60184eda0066 250 #endif
mluis 1:60184eda0066 251 // init done - onEvent( ) callback will be invoked...
mluis 1:60184eda0066 252 }
tmulrooney 8:0137acc9a6cd 253 #endif
tmulrooney 8:0137acc9a6cd 254
tmulrooney 8:0137acc9a6cd 255 #if 0
tmulrooney 8:0137acc9a6cd 256 // counter static
tmulrooney 8:0137acc9a6cd 257 int cnt = 0;
tmulrooney 8:0137acc9a6cd 258 // log text to USART and toggle LED
tmulrooney 8:0137acc9a6cd 259 static void onInit (osjob_t* job)
tmulrooney 8:0137acc9a6cd 260 {
tmulrooney 8:0137acc9a6cd 261 // say hello
tmulrooney 8:0137acc9a6cd 262 debug_str("Hello World!\r\n");
tmulrooney 8:0137acc9a6cd 263 // log counter
tmulrooney 8:0137acc9a6cd 264 debug_val("cnt = ", cnt);
tmulrooney 8:0137acc9a6cd 265 // toggle LED
tmulrooney 8:0137acc9a6cd 266 if((cnt & 1) == 1)
tmulrooney 8:0137acc9a6cd 267 {
tmulrooney 8:0137acc9a6cd 268 led1 = 1;
tmulrooney 8:0137acc9a6cd 269 }
tmulrooney 8:0137acc9a6cd 270 else
tmulrooney 8:0137acc9a6cd 271 {
tmulrooney 8:0137acc9a6cd 272 led1 = 0;
tmulrooney 8:0137acc9a6cd 273 }
tmulrooney 8:0137acc9a6cd 274 debug_led(cnt & 1);
tmulrooney 8:0137acc9a6cd 275 cnt++;
tmulrooney 8:0137acc9a6cd 276 // reschedule job every second
tmulrooney 8:0137acc9a6cd 277 os_setTimedCallback(job, os_getTime()+sec2osticks(1), onInit);
tmulrooney 8:0137acc9a6cd 278 }
tmulrooney 8:0137acc9a6cd 279 #endif
mluis 1:60184eda0066 280
mluis 1:60184eda0066 281 int main( void )
mluis 0:a2929fa6e4f0 282 {
mluis 0:a2929fa6e4f0 283 osjob_t initjob;
tmulrooney 6:fc465060b63e 284
tmulrooney 9:0b63a0a90205 285 led1=1;
tmulrooney 10:497ef83ca19f 286 led2=1;
tmulrooney 8:0137acc9a6cd 287 pc.baud(115200);
tmulrooney 10:497ef83ca19f 288 printf( "\r\nLoRaWan Demo Application TJM V %d.%d\r\n",MAJOR, MINOR );
mluis 0:a2929fa6e4f0 289 // initialize runtime env
mluis 0:a2929fa6e4f0 290 os_init( );
mluis 0:a2929fa6e4f0 291 // setup initial job
mluis 0:a2929fa6e4f0 292 os_setCallback( &initjob, onInit );
mluis 0:a2929fa6e4f0 293 // execute scheduled jobs and events
mluis 0:a2929fa6e4f0 294 os_runloop( );
mluis 0:a2929fa6e4f0 295 // (not reached)
mluis 0:a2929fa6e4f0 296 }
mluis 0:a2929fa6e4f0 297
mluis 0:a2929fa6e4f0 298 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 299 // LMIC EVENT CALLBACK
mluis 0:a2929fa6e4f0 300 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 301 void onEvent( ev_t ev )
mluis 0:a2929fa6e4f0 302 {
tmulrooney 6:fc465060b63e 303 debug("onEvent enter %d\r\n",ev);
mluis 0:a2929fa6e4f0 304 bool txOn = false;
mluis 1:60184eda0066 305 debug_event( ev );
mluis 0:a2929fa6e4f0 306
mluis 0:a2929fa6e4f0 307 switch( ev )
mluis 0:a2929fa6e4f0 308 {
mluis 0:a2929fa6e4f0 309 // network joined, session established
mluis 0:a2929fa6e4f0 310 case EV_JOINED:
mluis 1:60184eda0066 311 debug_val( "Net ID = ", LMIC.netid );
mluis 0:a2929fa6e4f0 312 txOn = true;
mluis 0:a2929fa6e4f0 313 break;
mluis 0:a2929fa6e4f0 314 // scheduled data sent (optionally data received)
mluis 0:a2929fa6e4f0 315 case EV_TXCOMPLETE:
mluis 1:60184eda0066 316 debug_val( "Datarate = ", LMIC.datarate );
mluis 0:a2929fa6e4f0 317 // Check if we have a downlink on either Rx1 or Rx2 windows
mluis 1:60184eda0066 318 if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 )
mluis 0:a2929fa6e4f0 319 {
tmulrooney 10:497ef83ca19f 320 led2 = 1;
mluis 1:60184eda0066 321 debug_val( "LED2 = ", 1 );
mluis 1:60184eda0066 322 os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed );
mluis 0:a2929fa6e4f0 323
mluis 1:60184eda0066 324 if( LMIC.dataLen != 0 )
mluis 0:a2929fa6e4f0 325 { // data received in rx slot after tx
mluis 1:60184eda0066 326 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
mluis 0:a2929fa6e4f0 327 processRxFrame( );
mluis 0:a2929fa6e4f0 328 }
mluis 0:a2929fa6e4f0 329 }
mluis 0:a2929fa6e4f0 330 txOn = true;
mluis 0:a2929fa6e4f0 331 break;
mluis 0:a2929fa6e4f0 332 default:
mluis 0:a2929fa6e4f0 333 break;
mluis 0:a2929fa6e4f0 334 }
mluis 0:a2929fa6e4f0 335 if( txOn == true )
mluis 0:a2929fa6e4f0 336 {
mluis 1:60184eda0066 337 //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited)
mluis 1:60184eda0066 338 os_setTimedCallback( &sendFrameJob,
mluis 1:60184eda0066 339 os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ),
mluis 1:60184eda0066 340 onSendFrame );
mluis 0:a2929fa6e4f0 341
mluis 1:60184eda0066 342 ////Sends frame as soon as possible (duty cylce limitations)
mluis 1:60184eda0066 343 //onSendFrame( NULL );
mluis 0:a2929fa6e4f0 344 }
mluis 0:a2929fa6e4f0 345 }