works with TTN and cheap STM32F103C8T6 boards

Dependencies:   LMiC_CFG_eu868 SX1276Lib mbed-STM32F103C8T6 mbed

Fork of LoRaWAN-lmic-app by Semtech

STM32F103C8T6 + RFM95 LoRa Node

flash board wirh STLink

openocd -f interface/stlink-v2.cfg -f target/stm32f1x_stlink.cfg \
         -c "program STM32F103C8T6_LoRaWAN-lmic-app_NUCLEO_F103RB.bin exit verify reset 0x08000000"
Committer:
orangeway
Date:
Thu Nov 10 23:21:44 2016 +0000
Revision:
7:4fd11bbd131e
Parent:
6:b2e833061c1f
works with TTN and cheap STM32F103C8T6 boards

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 */
mluis 0:a2929fa6e4f0 24 #define OVER_THE_AIR_ACTIVATION 0
mluis 0:a2929fa6e4f0 25
mluis 1:60184eda0066 26 /*!
mluis 1:60184eda0066 27 * Defines the application data transmission duty cycle
mluis 1:60184eda0066 28 */
mluis 1:60184eda0066 29 #define APP_TX_DUTYCYCLE 5000 // 5 [s] value in ms
mluis 1:60184eda0066 30 #define APP_TX_DUTYCYCLE_RND 1000 // 1 [s] value in ms
mluis 1:60184eda0066 31
mluis 1:60184eda0066 32 /*!
mluis 1:60184eda0066 33 * LoRaWAN Adaptative Data Rate
mluis 1:60184eda0066 34 */
mluis 1:60184eda0066 35 #define LORAWAN_ADR_ON 1
mluis 1:60184eda0066 36
mluis 1:60184eda0066 37 /*!
mluis 1:60184eda0066 38 * LoRaWAN confirmed messages
mluis 1:60184eda0066 39 */
orangeway 6:b2e833061c1f 40 #define LORAWAN_CONFIRMED_MSG_ON 0
mluis 1:60184eda0066 41
mluis 1:60184eda0066 42 /*!
mluis 1:60184eda0066 43 * LoRaWAN application port
mluis 1:60184eda0066 44 */
mluis 1:60184eda0066 45 #define LORAWAN_APP_PORT 15
mluis 1:60184eda0066 46
mluis 1:60184eda0066 47 /*!
mluis 1:60184eda0066 48 * User application data buffer size
mluis 1:60184eda0066 49 */
mluis 1:60184eda0066 50 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
mluis 1:60184eda0066 51 #define LORAWAN_APP_DATA_SIZE 6
mluis 1:60184eda0066 52
mluis 1:60184eda0066 53 #else
mluis 1:60184eda0066 54 #define LORAWAN_APP_DATA_SIZE 1
mluis 1:60184eda0066 55
mluis 1:60184eda0066 56 #endif
mluis 0:a2929fa6e4f0 57
mluis 0:a2929fa6e4f0 58 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 59 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
mluis 0:a2929fa6e4f0 60 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 61
mluis 0:a2929fa6e4f0 62 // application router ID (LSBF)
orangeway 6:b2e833061c1f 63 static const uint8_t AppEui[8] = { 0x5F, 0x14, 0x00, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
mluis 0:a2929fa6e4f0 64
mluis 0:a2929fa6e4f0 65 // unique device ID (LSBF)
orangeway 6:b2e833061c1f 66 static const u1_t DevEui[8] = { 0xDE, 0x3B, 0x5D, 0xEA, 0x00, 0x00, 0x00, 0x00 };
mluis 0:a2929fa6e4f0 67
mluis 0:a2929fa6e4f0 68 // device-specific AES key (derived from device EUI)
orangeway 6:b2e833061c1f 69 static const uint8_t DevKey[16] = { 0x3C, 0x4F, 0xCF, 0x09, 0x88, 0x15, 0xF7, 0xAB,
orangeway 6:b2e833061c1f 70 0xA6, 0xD2, 0xAE, 0x28, 0x16, 0x15, 0x7E, 0x2B };
mluis 0:a2929fa6e4f0 71
mluis 1:60184eda0066 72 #if( OVER_THE_AIR_ACTIVATION == 0 )
mluis 1:60184eda0066 73 // network session key
orangeway 6:b2e833061c1f 74 static uint8_t NwkSKey[] = { 0x3C, 0x4F, 0xCF, 0x09, 0x88, 0x15, 0xF7, 0xAB,
orangeway 6:b2e833061c1f 75 0xA6, 0xD2, 0xAE, 0x28, 0x16, 0x15, 0x7E, 0x2B };
mluis 0:a2929fa6e4f0 76
mluis 1:60184eda0066 77 // application session key
orangeway 6:b2e833061c1f 78 static uint8_t ArtSKey[] = { 0x0D, 0xAB, 0x37, 0x36, 0xB4, 0x49, 0x6B, 0xC3,
orangeway 6:b2e833061c1f 79 0xFA, 0x68, 0x0D, 0x28, 0x52, 0x73, 0x12, 0x6F };
orangeway 6:b2e833061c1f 80
orangeway 6:b2e833061c1f 81 // LoRaWAN network ID
orangeway 6:b2e833061c1f 82 static const uint32_t NetId = 0x00000001;
orangeway 6:b2e833061c1f 83
orangeway 6:b2e833061c1f 84 // LoRaWAN end-device address (DevAddr)
orangeway 6:b2e833061c1f 85 // See http://thethingsnetwork.org/wiki/AddressSpace
orangeway 6:b2e833061c1f 86 static const uint32_t DevAddr = 0xEA5D3BDE ; // <-- Change this address for every node!
mluis 0:a2929fa6e4f0 87
mluis 1:60184eda0066 88 #endif
mluis 1:60184eda0066 89
orangeway 6:b2e833061c1f 90
mluis 0:a2929fa6e4f0 91 // LEDs and Frame jobs
mluis 0:a2929fa6e4f0 92 osjob_t rxLedJob;
mluis 0:a2929fa6e4f0 93 osjob_t txLedJob;
mluis 0:a2929fa6e4f0 94 osjob_t sendFrameJob;
mluis 0:a2929fa6e4f0 95
mluis 1:60184eda0066 96 // LED state
mluis 0:a2929fa6e4f0 97 static bool AppLedStateOn = false;
mluis 0:a2929fa6e4f0 98
mluis 0:a2929fa6e4f0 99 //////////////////////////////////////////////////
mluis 1:60184eda0066 100 // Utility functions
mluis 1:60184eda0066 101 //////////////////////////////////////////////////
mluis 1:60184eda0066 102 /*!
mluis 1:60184eda0066 103 * \brief Computes a random number between min and max
mluis 1:60184eda0066 104 *
mluis 1:60184eda0066 105 * \param [IN] min range minimum value
mluis 1:60184eda0066 106 * \param [IN] max range maximum value
mluis 1:60184eda0066 107 * \retval random random value in range min..max
mluis 1:60184eda0066 108 */
mluis 1:60184eda0066 109 int32_t randr( int32_t min, int32_t max )
mluis 1:60184eda0066 110 {
mluis 1:60184eda0066 111 return ( int32_t )rand( ) % ( max - min + 1 ) + min;
mluis 1:60184eda0066 112 }
mluis 1:60184eda0066 113
mluis 1:60184eda0066 114 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 115 // APPLICATION CALLBACKS
mluis 0:a2929fa6e4f0 116 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 117
mluis 0:a2929fa6e4f0 118 // provide application router ID (8 bytes, LSBF)
mluis 1:60184eda0066 119 void os_getArtEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 120 {
mluis 0:a2929fa6e4f0 121 memcpy( buf, AppEui, 8 );
mluis 0:a2929fa6e4f0 122 }
mluis 0:a2929fa6e4f0 123
mluis 0:a2929fa6e4f0 124 // provide device ID (8 bytes, LSBF)
mluis 1:60184eda0066 125 void os_getDevEui( uint8_t *buf )
mluis 0:a2929fa6e4f0 126 {
mluis 0:a2929fa6e4f0 127 memcpy( buf, DevEui, 8 );
mluis 0:a2929fa6e4f0 128 }
mluis 0:a2929fa6e4f0 129
mluis 0:a2929fa6e4f0 130 // provide device key (16 bytes)
mluis 1:60184eda0066 131 void os_getDevKey( uint8_t *buf )
mluis 0:a2929fa6e4f0 132 {
mluis 0:a2929fa6e4f0 133 memcpy( buf, DevKey, 16 );
mluis 0:a2929fa6e4f0 134 }
mluis 0:a2929fa6e4f0 135
mluis 0:a2929fa6e4f0 136 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 137 // MAIN - INITIALIZATION AND STARTUP
mluis 0:a2929fa6e4f0 138 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 139
mluis 0:a2929fa6e4f0 140 static void onRxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 141 {
mluis 1:60184eda0066 142 debug_val("LED2 = ", 0 );
mluis 0:a2929fa6e4f0 143 }
mluis 0:a2929fa6e4f0 144
mluis 0:a2929fa6e4f0 145 static void onTxLed( osjob_t* j )
mluis 0:a2929fa6e4f0 146 {
mluis 1:60184eda0066 147 debug_val("LED1 = ", 0 );
mluis 0:a2929fa6e4f0 148 }
mluis 0:a2929fa6e4f0 149
mluis 0:a2929fa6e4f0 150 static void prepareTxFrame( void )
mluis 0:a2929fa6e4f0 151 {
mluis 0:a2929fa6e4f0 152 LMIC.frame[0] = AppLedStateOn;
mluis 1:60184eda0066 153 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
mluis 1:60184eda0066 154 LMIC.frame[1] = LMIC.seqnoDn >> 8;
mluis 1:60184eda0066 155 LMIC.frame[2] = LMIC.seqnoDn;
mluis 1:60184eda0066 156 LMIC.frame[3] = LMIC.rssi >> 8;
mluis 1:60184eda0066 157 LMIC.frame[4] = LMIC.rssi;
mluis 1:60184eda0066 158 LMIC.frame[5] = LMIC.snr;
mluis 1:60184eda0066 159 #endif
mluis 0:a2929fa6e4f0 160 }
mluis 0:a2929fa6e4f0 161
mluis 0:a2929fa6e4f0 162 void processRxFrame( void )
mluis 0:a2929fa6e4f0 163 {
mluis 0:a2929fa6e4f0 164 switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number
mluis 0:a2929fa6e4f0 165 {
mluis 0:a2929fa6e4f0 166 case 1: // The application LED can be controlled on port 1 or 2
mluis 0:a2929fa6e4f0 167 case 2:
mluis 0:a2929fa6e4f0 168 if( LMIC.dataLen == 1 )
mluis 0:a2929fa6e4f0 169 {
mluis 0:a2929fa6e4f0 170 AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
mluis 1:60184eda0066 171 debug_val( "LED3 = ", AppLedStateOn );
mluis 0:a2929fa6e4f0 172 }
mluis 0:a2929fa6e4f0 173 break;
mluis 0:a2929fa6e4f0 174 default:
mluis 0:a2929fa6e4f0 175 break;
mluis 0:a2929fa6e4f0 176 }
mluis 0:a2929fa6e4f0 177 }
mluis 0:a2929fa6e4f0 178
mluis 0:a2929fa6e4f0 179 static void onSendFrame( osjob_t* j )
mluis 0:a2929fa6e4f0 180 {
mluis 0:a2929fa6e4f0 181 prepareTxFrame( );
mluis 1:60184eda0066 182 LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LORAWAN_APP_DATA_SIZE, LORAWAN_CONFIRMED_MSG_ON );
mluis 1:60184eda0066 183
mluis 1:60184eda0066 184 // Blink Tx LED
mluis 1:60184eda0066 185 debug_val( "LED1 = ", 1 );
mluis 1:60184eda0066 186 os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
mluis 0:a2929fa6e4f0 187 }
mluis 0:a2929fa6e4f0 188
mluis 1:60184eda0066 189 // Initialization job
mluis 1:60184eda0066 190 static void onInit( osjob_t* j )
mluis 1:60184eda0066 191 {
mluis 1:60184eda0066 192 // reset MAC state
mluis 1:60184eda0066 193 LMIC_reset( );
mluis 1:60184eda0066 194 LMIC_setAdrMode( LORAWAN_ADR_ON );
mluis 5:1b2fcc2582e8 195 #if defined(CFG_eu868)
mluis 1:60184eda0066 196 LMIC_setDrTxpow( DR_SF12, 14 );
mluis 5:1b2fcc2582e8 197 #elif defined(CFG_us915)
mluis 5:1b2fcc2582e8 198 LMIC_setDrTxpow( DR_SF10, 14 );
mluis 5:1b2fcc2582e8 199 #endif
mluis 1:60184eda0066 200
mluis 1:60184eda0066 201 // start joining
mluis 1:60184eda0066 202 #if( OVER_THE_AIR_ACTIVATION != 0 )
mluis 1:60184eda0066 203 LMIC_startJoining( );
mluis 1:60184eda0066 204 #else
orangeway 6:b2e833061c1f 205 LMIC_setSession( NetId, DevAddr, NwkSKey, ArtSKey );
mluis 1:60184eda0066 206 onSendFrame( NULL );
mluis 1:60184eda0066 207 #endif
mluis 1:60184eda0066 208 // init done - onEvent( ) callback will be invoked...
mluis 1:60184eda0066 209 }
mluis 1:60184eda0066 210
mluis 1:60184eda0066 211 int main( void )
mluis 0:a2929fa6e4f0 212 {
mluis 0:a2929fa6e4f0 213 osjob_t initjob;
orangeway 6:b2e833061c1f 214
orangeway 6:b2e833061c1f 215 debug_init ();
mluis 0:a2929fa6e4f0 216
mluis 0:a2929fa6e4f0 217 // initialize runtime env
mluis 0:a2929fa6e4f0 218 os_init( );
mluis 0:a2929fa6e4f0 219 // setup initial job
mluis 0:a2929fa6e4f0 220 os_setCallback( &initjob, onInit );
mluis 0:a2929fa6e4f0 221 // execute scheduled jobs and events
mluis 0:a2929fa6e4f0 222 os_runloop( );
mluis 0:a2929fa6e4f0 223 // (not reached)
mluis 0:a2929fa6e4f0 224 }
mluis 0:a2929fa6e4f0 225
mluis 0:a2929fa6e4f0 226 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 227 // LMIC EVENT CALLBACK
mluis 0:a2929fa6e4f0 228 //////////////////////////////////////////////////
mluis 0:a2929fa6e4f0 229 void onEvent( ev_t ev )
mluis 0:a2929fa6e4f0 230 {
mluis 0:a2929fa6e4f0 231 bool txOn = false;
mluis 1:60184eda0066 232 debug_event( ev );
mluis 0:a2929fa6e4f0 233
mluis 0:a2929fa6e4f0 234 switch( ev )
mluis 0:a2929fa6e4f0 235 {
mluis 0:a2929fa6e4f0 236 // network joined, session established
mluis 0:a2929fa6e4f0 237 case EV_JOINED:
mluis 1:60184eda0066 238 debug_val( "Net ID = ", LMIC.netid );
mluis 0:a2929fa6e4f0 239 txOn = true;
mluis 0:a2929fa6e4f0 240 break;
mluis 0:a2929fa6e4f0 241 // scheduled data sent (optionally data received)
mluis 0:a2929fa6e4f0 242 case EV_TXCOMPLETE:
mluis 1:60184eda0066 243 debug_val( "Datarate = ", LMIC.datarate );
mluis 0:a2929fa6e4f0 244 // Check if we have a downlink on either Rx1 or Rx2 windows
mluis 1:60184eda0066 245 if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 )
mluis 0:a2929fa6e4f0 246 {
mluis 1:60184eda0066 247 debug_val( "LED2 = ", 1 );
mluis 1:60184eda0066 248 os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed );
mluis 0:a2929fa6e4f0 249
mluis 1:60184eda0066 250 if( LMIC.dataLen != 0 )
mluis 0:a2929fa6e4f0 251 { // data received in rx slot after tx
mluis 1:60184eda0066 252 debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
mluis 0:a2929fa6e4f0 253 processRxFrame( );
mluis 0:a2929fa6e4f0 254 }
mluis 0:a2929fa6e4f0 255 }
mluis 0:a2929fa6e4f0 256 txOn = true;
mluis 0:a2929fa6e4f0 257 break;
mluis 0:a2929fa6e4f0 258 default:
mluis 0:a2929fa6e4f0 259 break;
mluis 0:a2929fa6e4f0 260 }
mluis 0:a2929fa6e4f0 261 if( txOn == true )
mluis 0:a2929fa6e4f0 262 {
mluis 1:60184eda0066 263 //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited)
mluis 1:60184eda0066 264 os_setTimedCallback( &sendFrameJob,
mluis 1:60184eda0066 265 os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ),
mluis 1:60184eda0066 266 onSendFrame );
mluis 0:a2929fa6e4f0 267
mluis 1:60184eda0066 268 ////Sends frame as soon as possible (duty cylce limitations)
mluis 1:60184eda0066 269 //onSendFrame( NULL );
mluis 0:a2929fa6e4f0 270 }
mluis 0:a2929fa6e4f0 271 }