Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: LMiC SX1276Lib mbed
Fork of LoRaWAN-lmic-app by
Revision 1:60184eda0066, committed 2015-03-31
- Comitter:
- mluis
- Date:
- Tue Mar 31 13:38:08 2015 +0000
- Parent:
- 0:a2929fa6e4f0
- Child:
- 2:4eb7f3e46f44
- Commit message:
- Updated main application.; Moved debug and hal files from LMiC to main application.
Changed in this revision
--- a/LMiC.lib Thu Jan 22 13:02:55 2015 +0000 +++ b/LMiC.lib Tue Mar 31 13:38:08 2015 +0000 @@ -1,1 +1,1 @@ -http://developer.mbed.org/users/mluis/code/LMiC/#62d1edcc13d1 +http://developer.mbed.org/users/mluis/code/LMiC/#d3b7bde3995c
--- a/SX1276Lib.lib Thu Jan 22 13:02:55 2015 +0000 +++ b/SX1276Lib.lib Tue Mar 31 13:38:08 2015 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/GregCr/code/SX1276Lib/#04374b1c33fa +http://mbed.org/users/GregCr/code/SX1276Lib/#d447f8d2d2d6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/debug.cpp Tue Mar 31 13:38:08 2015 +0000
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Zurich Research Lab - initial API, implementation and documentation
+ * Semtech Apps Team - Adapted for MBED
+ *******************************************************************************/
+#include <stdio.h>
+#include "lmic.h"
+#include "debug.h"
+
+void debug_init () {
+ // print banner
+ debug_str("\r\n============== DEBUG STARTED ==============\r\n");
+}
+
+void debug_led (u1_t val) {
+ debug_val( "LED = ", val );
+}
+
+void debug_char (u1_t c) {
+ fprintf(stderr, "%c", c );
+}
+
+void debug_hex (u1_t b) {
+ fprintf(stderr, "%02X", b );
+}
+
+void debug_buf (const u1_t* buf, u2_t len) {
+ while( len-- ) {
+ debug_hex( *buf++ );
+ debug_char( ' ' );
+ }
+ debug_char( '\r' );
+ debug_char( '\n' );
+}
+
+void debug_uint (u4_t v) {
+ for( s1_t n = 24; n >= 0; n -= 8 ) {
+ debug_hex( v >> n );
+ }
+}
+
+void debug_str (const u1_t* str) {
+ while( *str ) {
+ debug_char( *str++ );
+ }
+}
+
+void debug_val (const u1_t* label, u4_t val) {
+ debug_str( label );
+ debug_uint( val );
+ debug_char( '\r' );
+ debug_char( '\n' );
+}
+
+void debug_event (int ev) {
+ static const u1_t* evnames[] = {
+ [EV_SCAN_TIMEOUT] = "SCAN_TIMEOUT",
+ [EV_BEACON_FOUND] = "BEACON_FOUND",
+ [EV_BEACON_MISSED] = "BEACON_MISSED",
+ [EV_BEACON_TRACKED] = "BEACON_TRACKED",
+ [EV_JOINING] = "JOINING",
+ [EV_JOINED] = "JOINED",
+ [EV_RFU1] = "RFU1",
+ [EV_JOIN_FAILED] = "JOIN_FAILED",
+ [EV_REJOIN_FAILED] = "REJOIN_FAILED",
+ [EV_TXCOMPLETE] = "TXCOMPLETE",
+ [EV_LOST_TSYNC] = "LOST_TSYNC",
+ [EV_RESET] = "RESET",
+ [EV_RXCOMPLETE] = "RXCOMPLETE",
+ [EV_LINK_DEAD] = "LINK_DEAD",
+ [EV_LINK_ALIVE] = "LINK_ALIVE",
+ };
+ debug_str(evnames[ev]);
+ debug_char('\r');
+ debug_char('\n');
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/debug.h Tue Mar 31 13:38:08 2015 +0000 @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2014-2015 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Zurich Research Lab - initial API, implementation and documentation + * Semtech Apps Team - Adapted for MBED + *******************************************************************************/ +#ifndef _debug_hpp_ +#define _debug_hpp_ + +// intialize debug library +void debug_init (void); + +// set LED state +void debug_led (u1_t val); + +// write character to USART +void debug_char (u1_t c); + +// write byte as two hex digits to USART +void debug_hex (u1_t b); + +// write buffer as hex dump to USART +void debug_buf (const u1_t* buf, u2_t len); + +// write 32-bit integer as eight hex digits to USART +void debug_uint (u4_t v); + +// write nul-terminated string to USART +void debug_str (const u1_t* str); + +// write LMiC event name to USART +void debug_event (int ev); + +// write label and 32-bit value as hex to USART +void debug_val (const u1_t* label, u4_t val); + +#endif // _debug_hpp_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hal.cpp Tue Mar 31 13:38:08 2015 +0000
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Zurich Research Lab - initial API, implementation and documentation
+ * Semtech Apps Team - Modified to support the MBED sx1276 driver
+ * library.
+ * Possibility to use original or Semtech's MBED
+ * radio driver. The selection is done by setting
+ * USE_SMTC_RADIO_DRIVER preprocessing directive
+ * in lmic.h
+ *******************************************************************************/
+#include "mbed.h"
+#include "lmic.h"
+#include "mbed_debug.h"
+
+#if !USE_SMTC_RADIO_DRIVER
+
+extern void radio_irq_handler( u1_t dio );
+
+static DigitalOut nss( D10 );
+static SPI spi( D11, D12, D13 ); // ( mosi, miso, sclk )
+
+static DigitalInOut rst( A0 );
+static DigitalOut rxtx( A4 );
+
+static InterruptIn dio0( D2 );
+static InterruptIn dio1( D3 );
+static InterruptIn dio2( D4 );
+
+static void dio0Irq( void ) {
+ radio_irq_handler( 0 );
+}
+
+static void dio1Irq( void ) {
+ radio_irq_handler( 1 );
+}
+
+static void dio2Irq( void ) {
+ radio_irq_handler( 2 );
+}
+
+#endif
+
+static u1_t irqlevel = 0;
+static u4_t ticks = 0;
+
+static Timer timer;
+static Ticker ticker;
+
+static void reset_timer( void ) {
+ ticks += timer.read_us( ) >> 6;
+ timer.reset( );
+}
+
+void hal_init( void ) {
+ __disable_irq( );
+ irqlevel = 0;
+
+#if !USE_SMTC_RADIO_DRIVER
+ // configure input lines
+ dio0.mode( PullDown );
+ dio0.rise( dio0Irq );
+ dio0.enable_irq( );
+ dio1.mode( PullDown );
+ dio1.rise( dio1Irq );
+ dio1.enable_irq( );
+ dio2.mode( PullDown );
+ dio2.rise( dio2Irq );
+ dio2.enable_irq( );
+ // configure reset line
+ rst.input( );
+ // configure spi
+ spi.frequency( 8000000 );
+ spi.format( 8, 0 );
+ nss = 1;
+#endif
+ // configure timer
+ timer.start( );
+ ticker.attach_us( reset_timer, 10000000 ); // reset timer every 10sec
+ __enable_irq( );
+}
+
+#if !USE_SMTC_RADIO_DRIVER
+
+void hal_pin_rxtx( u1_t val ) {
+ rxtx = !val;
+}
+
+void hal_pin_nss( u1_t val ) {
+ nss = val;
+}
+
+void hal_pin_rst( u1_t val ) {
+ if( val == 0 || val == 1 )
+ { // drive pin
+ rst.output( );
+ rst = val;
+ }
+ else
+ { // keep pin floating
+ rst.input( );
+ }
+}
+
+u1_t hal_spi( u1_t out ) {
+ return spi.write( out );
+}
+
+#endif
+
+void hal_disableIRQs( void ) {
+ __disable_irq( );
+ irqlevel++;
+}
+
+void hal_enableIRQs( void ) {
+ if( --irqlevel == 0 )
+ {
+ __enable_irq( );
+ }
+}
+
+void hal_sleep( void ) {
+ // NOP
+}
+
+u4_t hal_ticks( void ) {
+ hal_disableIRQs( );
+ int t = ticks + ( timer.read_us( ) >> 6 );
+ hal_enableIRQs( );
+ return t;
+}
+
+static u2_t deltaticks( u4_t time ) {
+ u4_t t = hal_ticks( );
+ s4_t d = time - t;
+ if( d <= 0 ) {
+ return 0; // in the past
+ }
+ if( ( d >> 16 ) != 0 ) {
+ return 0xFFFF; // far ahead
+ }
+ return ( u2_t )d;
+}
+
+void hal_waitUntil( u4_t time ) {
+ while( deltaticks( time ) != 0 ); // busy wait until timestamp is reached
+}
+
+u1_t hal_checkTimer( u4_t time ) {
+ return ( deltaticks( time ) < 2 );
+}
+
+void hal_failed( void ) {
+ while( 1 );
+}
--- a/main.cpp Thu Jan 22 13:02:55 2015 +0000
+++ b/main.cpp Tue Mar 31 13:38:08 2015 +0000
@@ -4,15 +4,18 @@
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
+ (C)2015 Semtech
-Description: MBED example application
+Description: MBED LoRaWAN example application
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
+#include "mbed.h"
+
#include "lmic.h"
+#include "debug.h"
/*!
* When set to 1 the application uses the Over-the-Air activation procedure
@@ -20,16 +23,60 @@
*/
#define OVER_THE_AIR_ACTIVATION 0
-#define APP_DATA_SIZE 1
+#if( OVER_THE_AIR_ACTIVATION == 0 )
+
+/*!
+ * Defines the network ID when using personalization activation procedure
+ */
+#define LORAWAN_NET_ID ( uint32_t )0x00000000
+
+/*!
+ * Defines the device address when using personalization activation procedure
+ */
+#define LORAWAN_DEV_ADDR ( uint32_t )0x12345678
+
+#endif
+
+/*!
+ * Defines the application data transmission duty cycle
+ */
+#define APP_TX_DUTYCYCLE 5000 // 5 [s] value in ms
+#define APP_TX_DUTYCYCLE_RND 1000 // 1 [s] value in ms
+
+/*!
+ * LoRaWAN Adaptative Data Rate
+ */
+#define LORAWAN_ADR_ON 1
+
+/*!
+ * LoRaWAN confirmed messages
+ */
+#define LORAWAN_CONFIRMED_MSG_ON 1
+
+/*!
+ * LoRaWAN application port
+ */
+#define LORAWAN_APP_PORT 15
+
+/*!
+ * User application data buffer size
+ */
+#if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
+#define LORAWAN_APP_DATA_SIZE 6
+
+#else
+#define LORAWAN_APP_DATA_SIZE 1
+
+#endif
//////////////////////////////////////////////////
// CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
//////////////////////////////////////////////////
// application router ID (LSBF)
-static const u1_t AppEui[8] =
+static const uint8_t AppEui[8] =
{
- 0xAA, 0xCC, 0x11, 0x00, 0xCC, 0xEE, 0x77, 0xEE
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// unique device ID (LSBF)
@@ -39,49 +86,70 @@
};
// device-specific AES key (derived from device EUI)
-static const u1_t DevKey[16] =
+static const uint8_t DevKey[16] =
{
- 0xAB, 0x89, 0xEF, 0xCD, 0x23, 0x01, 0x67, 0x45,
- 0x54, 0x76, 0x10, 0x32, 0xDC, 0xFE, 0x98, 0xBA
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
};
+#if( OVER_THE_AIR_ACTIVATION == 0 )
+// network session key
static uint8_t NwkSKey[] =
{
0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
};
+// application session key
static uint8_t ArtSKey[] =
{
0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
};
+#endif
+
// LEDs and Frame jobs
osjob_t rxLedJob;
osjob_t txLedJob;
osjob_t sendFrameJob;
+// LED state
static bool AppLedStateOn = false;
//////////////////////////////////////////////////
+// Utility functions
+//////////////////////////////////////////////////
+/*!
+ * \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 )
+{
+ return ( int32_t )rand( ) % ( max - min + 1 ) + min;
+}
+
+//////////////////////////////////////////////////
// APPLICATION CALLBACKS
//////////////////////////////////////////////////
// provide application router ID (8 bytes, LSBF)
-void os_getArtEui( u1_t* buf )
+void os_getArtEui( uint8_t *buf )
{
memcpy( buf, AppEui, 8 );
}
// provide device ID (8 bytes, LSBF)
-void os_getDevEui( u1_t* buf )
+void os_getDevEui( uint8_t *buf )
{
memcpy( buf, DevEui, 8 );
}
// provide device key (16 bytes)
-void os_getDevKey( u1_t* buf )
+void os_getDevKey( uint8_t *buf )
{
memcpy( buf, DevKey, 16 );
}
@@ -90,35 +158,26 @@
// MAIN - INITIALIZATION AND STARTUP
//////////////////////////////////////////////////
-// Initialization job
-static void onInit( osjob_t* j )
-{
- // reset MAC state
- LMIC_reset( );
- LMIC_setAdrMode( 1 );
- LMIC_setDrTxpow( DR_FSK, 14 );
- // start joining
-#if( OVER_THE_AIR_ACTIVATION != 0 )
- LMIC_startJoining( );
-#else
- LMIC_startABP( 0, 0x44332211, NwkSKey, ArtSKey );
-#endif
- // init done - onEvent() callback will be invoked...
-}
-
static void onRxLed( osjob_t* j )
{
- DEBUG_VAL("LED2 = ", 1 );
+ debug_val("LED2 = ", 0 );
}
static void onTxLed( osjob_t* j )
{
- DEBUG_VAL("LED1 = ", 1 );
+ debug_val("LED1 = ", 0 );
}
static void prepareTxFrame( void )
{
LMIC.frame[0] = AppLedStateOn;
+#if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
+ LMIC.frame[1] = LMIC.seqnoDn >> 8;
+ LMIC.frame[2] = LMIC.seqnoDn;
+ LMIC.frame[3] = LMIC.rssi >> 8;
+ LMIC.frame[4] = LMIC.rssi;
+ LMIC.frame[5] = LMIC.snr;
+#endif
}
void processRxFrame( void )
@@ -130,7 +189,7 @@
if( LMIC.dataLen == 1 )
{
AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
- DEBUG_VAL( "LED3 = ", AppLedStateOn ? 0 : 1 );
+ debug_val( "LED3 = ", AppLedStateOn );
}
break;
default:
@@ -141,10 +200,32 @@
static void onSendFrame( osjob_t* j )
{
prepareTxFrame( );
- LMIC_setTxData2( 1, LMIC.frame, APP_DATA_SIZE, 1 );
+ LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LORAWAN_APP_DATA_SIZE, LORAWAN_CONFIRMED_MSG_ON );
+
+ // Blink Tx LED
+ debug_val( "LED1 = ", 1 );
+ os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
}
-int main(void)
+// Initialization job
+static void onInit( osjob_t* j )
+{
+ // reset MAC state
+ LMIC_reset( );
+ LMIC_setAdrMode( LORAWAN_ADR_ON );
+ LMIC_setDrTxpow( DR_SF12, 14 );
+
+ // start joining
+#if( OVER_THE_AIR_ACTIVATION != 0 )
+ LMIC_startJoining( );
+#else
+ LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey );
+ onSendFrame( NULL );
+#endif
+ // init done - onEvent( ) callback will be invoked...
+}
+
+int main( void )
{
osjob_t initjob;
@@ -163,27 +244,27 @@
void onEvent( ev_t ev )
{
bool txOn = false;
-
- DEBUG_EVENT( ev );
+ debug_event( ev );
switch( ev )
{
// network joined, session established
case EV_JOINED:
- DEBUG_VAL( "Net ID = ", LMIC.netid );
+ debug_val( "Net ID = ", LMIC.netid );
txOn = true;
break;
// scheduled data sent (optionally data received)
case EV_TXCOMPLETE:
+ debug_val( "Datarate = ", LMIC.datarate );
// Check if we have a downlink on either Rx1 or Rx2 windows
- if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) )!= 0 )
+ if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 )
{
- DEBUG_VAL( "LED2 = ", 0 );
- os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 15 ), onRxLed );
+ debug_val( "LED2 = ", 1 );
+ os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed );
- if( LMIC.dataLen != 0 )
+ if( LMIC.dataLen != 0 )
{ // data received in rx slot after tx
- DEBUG_BUF( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
+ debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
processRxFrame( );
}
}
@@ -194,11 +275,12 @@
}
if( txOn == true )
{
- //os_setTimedCallback( &sendFrameJob, os_getTime( ) + sec2osticks( 5 ), onSendFrame );
- onSendFrame( NULL );
+ //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited)
+ os_setTimedCallback( &sendFrameJob,
+ os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ),
+ onSendFrame );
- // Blink Tx LED
- DEBUG_VAL( "LED1 = ", 0 );
- os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
+ ////Sends frame as soon as possible (duty cylce limitations)
+ //onSendFrame( NULL );
}
}
--- a/mbed.bld Thu Jan 22 13:02:55 2015 +0000 +++ b/mbed.bld Tue Mar 31 13:38:08 2015 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mbed_official/code/mbed/builds/4fc01daae5a5 \ No newline at end of file +http://mbed.org/users/mbed_official/code/mbed/builds/487b796308b0 \ No newline at end of file
