Sille Van Landschoot / LMiC

Dependents:   Simple-LoRaWAN

Fork of LMiC by Semtech

Committer:
mluis
Date:
Thu Jan 22 12:50:49 2015 +0000
Revision:
0:62d1edcc13d1
Porting of IBM LoRa MAC in C (LMiC) to the mbed platform.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mluis 0:62d1edcc13d1 1 /*******************************************************************************
mluis 0:62d1edcc13d1 2 * Copyright (c) 2014 IBM Corporation.
mluis 0:62d1edcc13d1 3 * All rights reserved. This program and the accompanying materials
mluis 0:62d1edcc13d1 4 * are made available under the terms of the Eclipse Public License v1.0
mluis 0:62d1edcc13d1 5 * which accompanies this distribution, and is available at
mluis 0:62d1edcc13d1 6 * http://www.eclipse.org/legal/epl-v10.html
mluis 0:62d1edcc13d1 7 *
mluis 0:62d1edcc13d1 8 * Contributors:
mluis 0:62d1edcc13d1 9 * IBM Zurich Research Lab - initial API, implementation and documentation
mluis 0:62d1edcc13d1 10 * Semtech Apps Team - Modified to support the MBED sx1276 driver
mluis 0:62d1edcc13d1 11 * library.
mluis 0:62d1edcc13d1 12 * Possibility to use original or Semtech's MBED
mluis 0:62d1edcc13d1 13 * radio driver. The selection is done by setting
mluis 0:62d1edcc13d1 14 * USE_SMTC_RADIO_DRIVER preprocessing directive
mluis 0:62d1edcc13d1 15 * in lmic.h
mluis 0:62d1edcc13d1 16 *******************************************************************************/
mluis 0:62d1edcc13d1 17 #include "mbed.h"
mluis 0:62d1edcc13d1 18 #include "lmic.h"
mluis 0:62d1edcc13d1 19 #include "mbed_debug.h"
mluis 0:62d1edcc13d1 20
mluis 0:62d1edcc13d1 21 #if USE_SMTC_RADIO_DRIVER
mluis 0:62d1edcc13d1 22
mluis 0:62d1edcc13d1 23 #else
mluis 0:62d1edcc13d1 24
mluis 0:62d1edcc13d1 25 extern void radio_irq_handler( u1_t dio );
mluis 0:62d1edcc13d1 26
mluis 0:62d1edcc13d1 27 static DigitalOut nss( D10 );
mluis 0:62d1edcc13d1 28 static SPI spi( D11, D12, D13 ); // ( mosi, miso, sclk )
mluis 0:62d1edcc13d1 29
mluis 0:62d1edcc13d1 30 static DigitalInOut rst( A0 );
mluis 0:62d1edcc13d1 31 static DigitalOut rxtx( A4 );
mluis 0:62d1edcc13d1 32
mluis 0:62d1edcc13d1 33 static InterruptIn dio0( D2 );
mluis 0:62d1edcc13d1 34 static InterruptIn dio1( D3 );
mluis 0:62d1edcc13d1 35 static InterruptIn dio2( D4 );
mluis 0:62d1edcc13d1 36
mluis 0:62d1edcc13d1 37 static void dio0Irq( void )
mluis 0:62d1edcc13d1 38 {
mluis 0:62d1edcc13d1 39 radio_irq_handler( 0 );
mluis 0:62d1edcc13d1 40 }
mluis 0:62d1edcc13d1 41
mluis 0:62d1edcc13d1 42 static void dio1Irq( void )
mluis 0:62d1edcc13d1 43 {
mluis 0:62d1edcc13d1 44 radio_irq_handler( 1 );
mluis 0:62d1edcc13d1 45 }
mluis 0:62d1edcc13d1 46 static void dio2Irq( void )
mluis 0:62d1edcc13d1 47 {
mluis 0:62d1edcc13d1 48 radio_irq_handler( 2 );
mluis 0:62d1edcc13d1 49 }
mluis 0:62d1edcc13d1 50
mluis 0:62d1edcc13d1 51 #endif
mluis 0:62d1edcc13d1 52
mluis 0:62d1edcc13d1 53 static u1_t irqlevel = 0;
mluis 0:62d1edcc13d1 54 static u4_t ticks = 0;
mluis 0:62d1edcc13d1 55
mluis 0:62d1edcc13d1 56 static Timer timer;
mluis 0:62d1edcc13d1 57 static Ticker ticker;
mluis 0:62d1edcc13d1 58
mluis 0:62d1edcc13d1 59 static void reset_timer( void )
mluis 0:62d1edcc13d1 60 {
mluis 0:62d1edcc13d1 61 ticks += timer.read_us( ) >> 6;
mluis 0:62d1edcc13d1 62 timer.reset( );
mluis 0:62d1edcc13d1 63 }
mluis 0:62d1edcc13d1 64
mluis 0:62d1edcc13d1 65 void hal_init( void )
mluis 0:62d1edcc13d1 66 {
mluis 0:62d1edcc13d1 67 __disable_irq( );
mluis 0:62d1edcc13d1 68 irqlevel = 0;
mluis 0:62d1edcc13d1 69
mluis 0:62d1edcc13d1 70 #if USE_SMTC_RADIO_DRIVER
mluis 0:62d1edcc13d1 71
mluis 0:62d1edcc13d1 72 #else
mluis 0:62d1edcc13d1 73 // configure input lines
mluis 0:62d1edcc13d1 74 dio0.mode( PullDown );
mluis 0:62d1edcc13d1 75 dio0.rise( dio0Irq );
mluis 0:62d1edcc13d1 76 dio0.enable_irq( );
mluis 0:62d1edcc13d1 77 dio1.mode( PullDown );
mluis 0:62d1edcc13d1 78 dio1.rise( dio1Irq );
mluis 0:62d1edcc13d1 79 dio1.enable_irq( );
mluis 0:62d1edcc13d1 80 dio2.mode( PullDown );
mluis 0:62d1edcc13d1 81 dio2.rise( dio2Irq );
mluis 0:62d1edcc13d1 82 dio2.enable_irq( );
mluis 0:62d1edcc13d1 83 // configure reset line
mluis 0:62d1edcc13d1 84 rst.input( );
mluis 0:62d1edcc13d1 85 // configure spi
mluis 0:62d1edcc13d1 86 spi.frequency( 8000000 );
mluis 0:62d1edcc13d1 87 spi.format( 8, 0 );
mluis 0:62d1edcc13d1 88 nss = 1;
mluis 0:62d1edcc13d1 89 #endif
mluis 0:62d1edcc13d1 90 // configure timer
mluis 0:62d1edcc13d1 91 timer.start( );
mluis 0:62d1edcc13d1 92 ticker.attach_us( reset_timer, 10000000 ); // reset timer every 10sec
mluis 0:62d1edcc13d1 93 __enable_irq( );
mluis 0:62d1edcc13d1 94 }
mluis 0:62d1edcc13d1 95
mluis 0:62d1edcc13d1 96 #if USE_SMTC_RADIO_DRIVER
mluis 0:62d1edcc13d1 97
mluis 0:62d1edcc13d1 98 #else
mluis 0:62d1edcc13d1 99
mluis 0:62d1edcc13d1 100 void hal_pin_rxtx( u1_t val )
mluis 0:62d1edcc13d1 101 {
mluis 0:62d1edcc13d1 102 rxtx = !val;
mluis 0:62d1edcc13d1 103 }
mluis 0:62d1edcc13d1 104
mluis 0:62d1edcc13d1 105 void hal_pin_nss( u1_t val )
mluis 0:62d1edcc13d1 106 {
mluis 0:62d1edcc13d1 107 nss = val;
mluis 0:62d1edcc13d1 108 }
mluis 0:62d1edcc13d1 109
mluis 0:62d1edcc13d1 110 void hal_pin_rst( u1_t val )
mluis 0:62d1edcc13d1 111 {
mluis 0:62d1edcc13d1 112 if( val == 0 || val == 1 )
mluis 0:62d1edcc13d1 113 { // drive pin
mluis 0:62d1edcc13d1 114 rst.output( );
mluis 0:62d1edcc13d1 115 rst = val;
mluis 0:62d1edcc13d1 116 }
mluis 0:62d1edcc13d1 117 else
mluis 0:62d1edcc13d1 118 { // keep pin floating
mluis 0:62d1edcc13d1 119 rst.input( );
mluis 0:62d1edcc13d1 120 }
mluis 0:62d1edcc13d1 121 }
mluis 0:62d1edcc13d1 122
mluis 0:62d1edcc13d1 123 u1_t hal_spi( u1_t out )
mluis 0:62d1edcc13d1 124 {
mluis 0:62d1edcc13d1 125 return spi.write( out );
mluis 0:62d1edcc13d1 126 }
mluis 0:62d1edcc13d1 127
mluis 0:62d1edcc13d1 128 #endif
mluis 0:62d1edcc13d1 129
mluis 0:62d1edcc13d1 130 void hal_disableIRQs( void )
mluis 0:62d1edcc13d1 131 {
mluis 0:62d1edcc13d1 132 __disable_irq( );
mluis 0:62d1edcc13d1 133 irqlevel++;
mluis 0:62d1edcc13d1 134 }
mluis 0:62d1edcc13d1 135
mluis 0:62d1edcc13d1 136 void hal_enableIRQs( void )
mluis 0:62d1edcc13d1 137 {
mluis 0:62d1edcc13d1 138 if( --irqlevel == 0 )
mluis 0:62d1edcc13d1 139 {
mluis 0:62d1edcc13d1 140 __enable_irq( );
mluis 0:62d1edcc13d1 141 }
mluis 0:62d1edcc13d1 142 }
mluis 0:62d1edcc13d1 143
mluis 0:62d1edcc13d1 144 void hal_sleep( void )
mluis 0:62d1edcc13d1 145 {
mluis 0:62d1edcc13d1 146 // NOP
mluis 0:62d1edcc13d1 147 }
mluis 0:62d1edcc13d1 148
mluis 0:62d1edcc13d1 149 u4_t hal_ticks( void )
mluis 0:62d1edcc13d1 150 {
mluis 0:62d1edcc13d1 151 hal_disableIRQs( );
mluis 0:62d1edcc13d1 152 int t = ticks + ( timer.read_us( ) >> 6 );
mluis 0:62d1edcc13d1 153 hal_enableIRQs( );
mluis 0:62d1edcc13d1 154 return t;
mluis 0:62d1edcc13d1 155 }
mluis 0:62d1edcc13d1 156
mluis 0:62d1edcc13d1 157 static u2_t deltaticks( u4_t time )
mluis 0:62d1edcc13d1 158 {
mluis 0:62d1edcc13d1 159 u4_t t = hal_ticks( );
mluis 0:62d1edcc13d1 160 s4_t d = time - t;
mluis 0:62d1edcc13d1 161 if( d <= 0 )
mluis 0:62d1edcc13d1 162 {
mluis 0:62d1edcc13d1 163 return 0; // in the past
mluis 0:62d1edcc13d1 164 }
mluis 0:62d1edcc13d1 165 if( ( d >> 16 ) != 0 )
mluis 0:62d1edcc13d1 166 {
mluis 0:62d1edcc13d1 167 return 0xFFFF; // far ahead
mluis 0:62d1edcc13d1 168 }
mluis 0:62d1edcc13d1 169 return ( u2_t )d;
mluis 0:62d1edcc13d1 170 }
mluis 0:62d1edcc13d1 171
mluis 0:62d1edcc13d1 172 void hal_waitUntil( u4_t time )
mluis 0:62d1edcc13d1 173 {
mluis 0:62d1edcc13d1 174 while( deltaticks( time ) != 0 ); // busy wait until timestamp is reached
mluis 0:62d1edcc13d1 175 }
mluis 0:62d1edcc13d1 176
mluis 0:62d1edcc13d1 177 u1_t hal_checkTimer( u4_t time )
mluis 0:62d1edcc13d1 178 {
mluis 0:62d1edcc13d1 179 return ( deltaticks( time ) < 2 );
mluis 0:62d1edcc13d1 180 }
mluis 0:62d1edcc13d1 181
mluis 0:62d1edcc13d1 182 void hal_failed( void )
mluis 0:62d1edcc13d1 183 {
mluis 0:62d1edcc13d1 184 while( 1 );
mluis 0:62d1edcc13d1 185 }
mluis 0:62d1edcc13d1 186
mluis 0:62d1edcc13d1 187 //////////////////////////////////////////////////////////////////////
mluis 0:62d1edcc13d1 188 // DEBUG CODE BELOW (use CFG_DEBUG)
mluis 0:62d1edcc13d1 189 //////////////////////////////////////////////////////////////////////
mluis 0:62d1edcc13d1 190 #ifdef CFG_DEBUG
mluis 0:62d1edcc13d1 191
mluis 0:62d1edcc13d1 192 void debug_init( void )
mluis 0:62d1edcc13d1 193 {
mluis 0:62d1edcc13d1 194 // print banner
mluis 0:62d1edcc13d1 195 debug( "\r\n============== DEBUG STARTED ==============\r\n" );
mluis 0:62d1edcc13d1 196 }
mluis 0:62d1edcc13d1 197
mluis 0:62d1edcc13d1 198 void debug_char( u1_t c )
mluis 0:62d1edcc13d1 199 {
mluis 0:62d1edcc13d1 200 debug( "%c", c );
mluis 0:62d1edcc13d1 201 }
mluis 0:62d1edcc13d1 202
mluis 0:62d1edcc13d1 203 void debug_hex( u1_t b )
mluis 0:62d1edcc13d1 204 {
mluis 0:62d1edcc13d1 205 debug( "%02X", b );
mluis 0:62d1edcc13d1 206 }
mluis 0:62d1edcc13d1 207
mluis 0:62d1edcc13d1 208 void debug_buf( const u1_t* buf, u2_t len )
mluis 0:62d1edcc13d1 209 {
mluis 0:62d1edcc13d1 210 while( len-- )
mluis 0:62d1edcc13d1 211 {
mluis 0:62d1edcc13d1 212 debug_hex( *buf++ );
mluis 0:62d1edcc13d1 213 debug_char( ' ' );
mluis 0:62d1edcc13d1 214 }
mluis 0:62d1edcc13d1 215 debug_char( '\r' );
mluis 0:62d1edcc13d1 216 debug_char( '\n' );
mluis 0:62d1edcc13d1 217 }
mluis 0:62d1edcc13d1 218
mluis 0:62d1edcc13d1 219 void debug_uint( u4_t v )
mluis 0:62d1edcc13d1 220 {
mluis 0:62d1edcc13d1 221 for( s1_t n = 24; n >= 0; n -= 8 )
mluis 0:62d1edcc13d1 222 {
mluis 0:62d1edcc13d1 223 debug_hex( v >> n );
mluis 0:62d1edcc13d1 224 }
mluis 0:62d1edcc13d1 225 }
mluis 0:62d1edcc13d1 226
mluis 0:62d1edcc13d1 227 void debug_str( const u1_t* str )
mluis 0:62d1edcc13d1 228 {
mluis 0:62d1edcc13d1 229 while( *str )
mluis 0:62d1edcc13d1 230 {
mluis 0:62d1edcc13d1 231 debug_char( *str++ );
mluis 0:62d1edcc13d1 232 }
mluis 0:62d1edcc13d1 233 }
mluis 0:62d1edcc13d1 234
mluis 0:62d1edcc13d1 235 void debug_val( const u1_t* label, u4_t val )
mluis 0:62d1edcc13d1 236 {
mluis 0:62d1edcc13d1 237 debug_str( label );
mluis 0:62d1edcc13d1 238 debug_uint( val );
mluis 0:62d1edcc13d1 239 debug_char( '\r' );
mluis 0:62d1edcc13d1 240 debug_char( '\n' );
mluis 0:62d1edcc13d1 241 }
mluis 0:62d1edcc13d1 242
mluis 0:62d1edcc13d1 243 void debug_led( u1_t val )
mluis 0:62d1edcc13d1 244 {
mluis 0:62d1edcc13d1 245 debug_val( "LED = ", val );
mluis 0:62d1edcc13d1 246 }
mluis 0:62d1edcc13d1 247
mluis 0:62d1edcc13d1 248 void debug_event( int ev )
mluis 0:62d1edcc13d1 249 {
mluis 0:62d1edcc13d1 250 static const u1_t* evnames[] =
mluis 0:62d1edcc13d1 251 {
mluis 0:62d1edcc13d1 252 [EV_SCAN_TIMEOUT] = "SCAN_TIMEOUT",
mluis 0:62d1edcc13d1 253 [EV_BEACON_FOUND] = "BEACON_FOUND",
mluis 0:62d1edcc13d1 254 [EV_BEACON_MISSED] = "BEACON_MISSED",
mluis 0:62d1edcc13d1 255 [EV_BEACON_TRACKED] = "BEACON_TRACKED",
mluis 0:62d1edcc13d1 256 [EV_JOINING] = "JOINING",
mluis 0:62d1edcc13d1 257 [EV_JOINED] = "JOINED",
mluis 0:62d1edcc13d1 258 [EV_RFU1] = "RFU1",
mluis 0:62d1edcc13d1 259 [EV_JOIN_FAILED] = "JOIN_FAILED",
mluis 0:62d1edcc13d1 260 [EV_REJOIN_FAILED] = "REJOIN_FAILED",
mluis 0:62d1edcc13d1 261 [EV_TXCOMPLETE] = "TXCOMPLETE",
mluis 0:62d1edcc13d1 262 [EV_LOST_TSYNC] = "LOST_TSYNC",
mluis 0:62d1edcc13d1 263 [EV_RESET] = "RESET",
mluis 0:62d1edcc13d1 264 [EV_RXCOMPLETE] = "RXCOMPLETE",
mluis 0:62d1edcc13d1 265 [EV_LINK_DEAD] = "LINK_DEAD",
mluis 0:62d1edcc13d1 266 [EV_LINK_ALIVE] = "LINK_ALIVE",
mluis 0:62d1edcc13d1 267 };
mluis 0:62d1edcc13d1 268 debug( "%s\r\n", evnames[ev] );
mluis 0:62d1edcc13d1 269 }
mluis 0:62d1edcc13d1 270 #endif // CFG_DEBUG