Example implementation of LoraWan specification based on IBM LoraWan in C (ver. 1.5) for Elmo board. Tested only with OTA activation (requires setting AppEui/ DevKey in main.cpp).

Dependencies:   SX1272lib mbed

Committer:
WGorniak
Date:
Fri Oct 02 16:43:13 2015 +0200
Revision:
0:bb3b0e756578
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WGorniak 0:bb3b0e756578 1 /*******************************************************************************
WGorniak 0:bb3b0e756578 2 * Copyright (c) 2014 IBM Corporation.
WGorniak 0:bb3b0e756578 3 * All rights reserved. This program and the accompanying materials
WGorniak 0:bb3b0e756578 4 * are made available under the terms of the Eclipse Public License v1.0
WGorniak 0:bb3b0e756578 5 * which accompanies this distribution, and is available at
WGorniak 0:bb3b0e756578 6 * http://www.eclipse.org/legal/epl-v10.html
WGorniak 0:bb3b0e756578 7 *
WGorniak 0:bb3b0e756578 8 * Contributors:
WGorniak 0:bb3b0e756578 9 * IBM Zurich Research Lab - initial API, implementation and documentation
WGorniak 0:bb3b0e756578 10 * Semtech Apps Team - Modified to support the MBED sx1276 driver
WGorniak 0:bb3b0e756578 11 * library.
WGorniak 0:bb3b0e756578 12 * Possibility to use original or Semtech's MBED
WGorniak 0:bb3b0e756578 13 * radio driver. The selection is done by setting
WGorniak 0:bb3b0e756578 14 * USE_SMTC_RADIO_DRIVER preprocessing directive
WGorniak 0:bb3b0e756578 15 * in lmic.h
WGorniak 0:bb3b0e756578 16 *******************************************************************************/
WGorniak 0:bb3b0e756578 17 #include "mbed.h"
WGorniak 0:bb3b0e756578 18 #include "lmic.h"
WGorniak 0:bb3b0e756578 19 #include "mbed_debug.h"
WGorniak 0:bb3b0e756578 20
WGorniak 0:bb3b0e756578 21 #if !USE_SMTC_RADIO_DRIVER
WGorniak 0:bb3b0e756578 22
WGorniak 0:bb3b0e756578 23 extern void radio_irq_handler( u1_t dio );
WGorniak 0:bb3b0e756578 24
WGorniak 0:bb3b0e756578 25 static DigitalOut nss( D10 );
WGorniak 0:bb3b0e756578 26 static SPI spi( D11, D12, D13 ); // ( mosi, miso, sclk )
WGorniak 0:bb3b0e756578 27
WGorniak 0:bb3b0e756578 28 static DigitalInOut rst( A0 );
WGorniak 0:bb3b0e756578 29 static DigitalOut rxtx( A4 );
WGorniak 0:bb3b0e756578 30
WGorniak 0:bb3b0e756578 31 static InterruptIn dio0( D2 );
WGorniak 0:bb3b0e756578 32 static InterruptIn dio1( D3 );
WGorniak 0:bb3b0e756578 33 static InterruptIn dio2( D4 );
WGorniak 0:bb3b0e756578 34
WGorniak 0:bb3b0e756578 35 static void dio0Irq( void ) {
WGorniak 0:bb3b0e756578 36 radio_irq_handler( 0 );
WGorniak 0:bb3b0e756578 37 }
WGorniak 0:bb3b0e756578 38
WGorniak 0:bb3b0e756578 39 static void dio1Irq( void ) {
WGorniak 0:bb3b0e756578 40 radio_irq_handler( 1 );
WGorniak 0:bb3b0e756578 41 }
WGorniak 0:bb3b0e756578 42
WGorniak 0:bb3b0e756578 43 static void dio2Irq( void ) {
WGorniak 0:bb3b0e756578 44 radio_irq_handler( 2 );
WGorniak 0:bb3b0e756578 45 }
WGorniak 0:bb3b0e756578 46
WGorniak 0:bb3b0e756578 47 #endif
WGorniak 0:bb3b0e756578 48
WGorniak 0:bb3b0e756578 49 static u1_t irqlevel = 0;
WGorniak 0:bb3b0e756578 50 static u4_t ticks = 0;
WGorniak 0:bb3b0e756578 51
WGorniak 0:bb3b0e756578 52 static Timer timer;
WGorniak 0:bb3b0e756578 53 static Ticker ticker;
WGorniak 0:bb3b0e756578 54
WGorniak 0:bb3b0e756578 55 static void reset_timer( void ) {
WGorniak 0:bb3b0e756578 56 ticks += timer.read_us( ) >> 6;
WGorniak 0:bb3b0e756578 57 timer.reset( );
WGorniak 0:bb3b0e756578 58 }
WGorniak 0:bb3b0e756578 59
WGorniak 0:bb3b0e756578 60 void hal_init( void ) {
WGorniak 0:bb3b0e756578 61 __disable_irq( );
WGorniak 0:bb3b0e756578 62 irqlevel = 0;
WGorniak 0:bb3b0e756578 63
WGorniak 0:bb3b0e756578 64 #if !USE_SMTC_RADIO_DRIVER
WGorniak 0:bb3b0e756578 65 // configure input lines
WGorniak 0:bb3b0e756578 66 dio0.mode( PullDown );
WGorniak 0:bb3b0e756578 67 dio0.rise( dio0Irq );
WGorniak 0:bb3b0e756578 68 dio0.enable_irq( );
WGorniak 0:bb3b0e756578 69 dio1.mode( PullDown );
WGorniak 0:bb3b0e756578 70 dio1.rise( dio1Irq );
WGorniak 0:bb3b0e756578 71 dio1.enable_irq( );
WGorniak 0:bb3b0e756578 72 dio2.mode( PullDown );
WGorniak 0:bb3b0e756578 73 dio2.rise( dio2Irq );
WGorniak 0:bb3b0e756578 74 dio2.enable_irq( );
WGorniak 0:bb3b0e756578 75 // configure reset line
WGorniak 0:bb3b0e756578 76 rst.input( );
WGorniak 0:bb3b0e756578 77 // configure spi
WGorniak 0:bb3b0e756578 78 spi.frequency( 8000000 );
WGorniak 0:bb3b0e756578 79 spi.format( 8, 0 );
WGorniak 0:bb3b0e756578 80 nss = 1;
WGorniak 0:bb3b0e756578 81 #endif
WGorniak 0:bb3b0e756578 82 // configure timer
WGorniak 0:bb3b0e756578 83 timer.start( );
WGorniak 0:bb3b0e756578 84 ticker.attach_us( reset_timer, 10000000 ); // reset timer every 10sec
WGorniak 0:bb3b0e756578 85 __enable_irq( );
WGorniak 0:bb3b0e756578 86 }
WGorniak 0:bb3b0e756578 87
WGorniak 0:bb3b0e756578 88 #if !USE_SMTC_RADIO_DRIVER
WGorniak 0:bb3b0e756578 89
WGorniak 0:bb3b0e756578 90 void hal_pin_rxtx( u1_t val ) {
WGorniak 0:bb3b0e756578 91 rxtx = !val;
WGorniak 0:bb3b0e756578 92 }
WGorniak 0:bb3b0e756578 93
WGorniak 0:bb3b0e756578 94 void hal_pin_nss( u1_t val ) {
WGorniak 0:bb3b0e756578 95 nss = val;
WGorniak 0:bb3b0e756578 96 }
WGorniak 0:bb3b0e756578 97
WGorniak 0:bb3b0e756578 98 void hal_pin_rst( u1_t val ) {
WGorniak 0:bb3b0e756578 99 if( val == 0 || val == 1 )
WGorniak 0:bb3b0e756578 100 { // drive pin
WGorniak 0:bb3b0e756578 101 rst.output( );
WGorniak 0:bb3b0e756578 102 rst = val;
WGorniak 0:bb3b0e756578 103 }
WGorniak 0:bb3b0e756578 104 else
WGorniak 0:bb3b0e756578 105 { // keep pin floating
WGorniak 0:bb3b0e756578 106 rst.input( );
WGorniak 0:bb3b0e756578 107 }
WGorniak 0:bb3b0e756578 108 }
WGorniak 0:bb3b0e756578 109
WGorniak 0:bb3b0e756578 110 u1_t hal_spi( u1_t out ) {
WGorniak 0:bb3b0e756578 111 return spi.write( out );
WGorniak 0:bb3b0e756578 112 }
WGorniak 0:bb3b0e756578 113
WGorniak 0:bb3b0e756578 114 #endif
WGorniak 0:bb3b0e756578 115
WGorniak 0:bb3b0e756578 116 void hal_disableIRQs( void ) {
WGorniak 0:bb3b0e756578 117 __disable_irq( );
WGorniak 0:bb3b0e756578 118 irqlevel++;
WGorniak 0:bb3b0e756578 119 }
WGorniak 0:bb3b0e756578 120
WGorniak 0:bb3b0e756578 121 void hal_enableIRQs( void ) {
WGorniak 0:bb3b0e756578 122 if( --irqlevel == 0 )
WGorniak 0:bb3b0e756578 123 {
WGorniak 0:bb3b0e756578 124 __enable_irq( );
WGorniak 0:bb3b0e756578 125 }
WGorniak 0:bb3b0e756578 126 }
WGorniak 0:bb3b0e756578 127
WGorniak 0:bb3b0e756578 128 void hal_sleep( void ) {
WGorniak 0:bb3b0e756578 129 // NOP
WGorniak 0:bb3b0e756578 130 }
WGorniak 0:bb3b0e756578 131
WGorniak 0:bb3b0e756578 132 u4_t hal_ticks( void ) {
WGorniak 0:bb3b0e756578 133 hal_disableIRQs( );
WGorniak 0:bb3b0e756578 134 int t = ticks + ( timer.read_us( ) >> 6 );
WGorniak 0:bb3b0e756578 135 hal_enableIRQs( );
WGorniak 0:bb3b0e756578 136 return t;
WGorniak 0:bb3b0e756578 137 }
WGorniak 0:bb3b0e756578 138
WGorniak 0:bb3b0e756578 139 static u2_t deltaticks( u4_t time ) {
WGorniak 0:bb3b0e756578 140 u4_t t = hal_ticks( );
WGorniak 0:bb3b0e756578 141 s4_t d = time - t;
WGorniak 0:bb3b0e756578 142 if( d <= 0 ) {
WGorniak 0:bb3b0e756578 143 return 0; // in the past
WGorniak 0:bb3b0e756578 144 }
WGorniak 0:bb3b0e756578 145 if( ( d >> 16 ) != 0 ) {
WGorniak 0:bb3b0e756578 146 return 0xFFFF; // far ahead
WGorniak 0:bb3b0e756578 147 }
WGorniak 0:bb3b0e756578 148 return ( u2_t )d;
WGorniak 0:bb3b0e756578 149 }
WGorniak 0:bb3b0e756578 150
WGorniak 0:bb3b0e756578 151 void hal_waitUntil( u4_t time ) {
WGorniak 0:bb3b0e756578 152 while( deltaticks( time ) != 0 ); // busy wait until timestamp is reached
WGorniak 0:bb3b0e756578 153 }
WGorniak 0:bb3b0e756578 154
WGorniak 0:bb3b0e756578 155 u1_t hal_checkTimer( u4_t time ) {
WGorniak 0:bb3b0e756578 156 return ( deltaticks( time ) < 2 );
WGorniak 0:bb3b0e756578 157 }
WGorniak 0:bb3b0e756578 158
WGorniak 0:bb3b0e756578 159 void hal_failed( void ) {
WGorniak 0:bb3b0e756578 160 while( 1 );
WGorniak 0:bb3b0e756578 161 }