Demonstration of Class-A LoRaWAN device using NAMote-72

Dependencies:   LoRaWAN-lib mbed lib_mpl3115a2 lib_mma8451q lib_gps SX1272Lib

Dependents:   LoRaWAN-NAMote72-BVS-confirmed-tester-0-7v1_copy

LoRaWAN-NAMote72 Application Demo is a Class-A device example project using LoRaWAN-lib and SX1272Lib libraries.

This project is compliant with LoRaWAN V1.0.1 specification.

Comissioning.h (LoRaWAN Network Configuration)

The end-device can be activated in one of the two ways:

Over the Air (OTA) activation can be enabled as shown in the figure below. /media/uploads/ubhat/ota_enable.png

The end-device must be configured with the following parameters:

  • LORAWAN_DEVICE_EUI (8 Bytes) : Fist 3 Bytes is the Organizationally Unique Identifier (OUI) followed by 5 bytes of unique ID. If not defined by user, then the firmware automatically assigns one to the end-device
  • LORAWAN_APPLICATION_EUI (8 Bytes)
  • LORAWAN_APPLICATION_KEY (or DEVKEY) (16 Bytes)

/media/uploads/ubhat/ota_eui.png

Activation by Personalization (ABP) can be enabled as shown in the figure below. /media/uploads/ubhat/abp_enable.png

The end-device must be configured with the following parameters:

  • LORAWAN_DEVICE_ADDRESS (4 Bytes) : If not defined by user, then the firmware automatically assigns one to the end-device
  • LORAWAN_NWKSKEY (16 Bytes)
  • LORAWAN_APPSKEY (16 Bytes)

/media/uploads/ubhat/abp_key.png

Config.h (LoRaWAN Communication Parameters)

  • Mode of Operation : Hybrid If the end-device needs to be configured to operate over 8-channels, then Hybrid Mode needs to be enabled /media/uploads/ubhat/hybridenable.png
  • Mode of Operation : Frequency Hop If the end-device needs to be configured to operate over 64-channels, then Hybrid Mode needs to be disabled
  • Delay between successive JOIN REQUESTs : The delay between successive Join Requests (until the end-device joins the network) can be configured using the parameter OVER_THE_AIR_ACTIVATION_DUTYCYCLE
  • Inter-Frame Delay : One can change the delay between each frame transmission using APP_TX_DUTYCYCLE It is advisable that APP_TX_DUTYCYCLE is greater than or equal to 3sec.
  • Data Rate : The data rate can be configured as per LoRaWAN specification using the paramter LORAWAN_DEFAULT_DATARATE. The range of values are DR_0, DR_1, DR_2, DR_3 and DR_4
  • Confirmed/Unconfirmed Messages : The uplink message or payload can be chosen to be confirmed or unconfirmed using the parameter LORAWAN_CONFIRMED_MSG_ON. When set to 1, the transmitted messages need to be confirmed with an ACK by the network server in the subsequent RX window. When set to 0, no ACK is requested.
  • ADR ON/OFF : The ADR can be enabled or disabled using the parameter LORAWAN_ADR_ON. When set to 1, ADR is enabled and disabled when set to 0.
  • Application Port : The application port can be set using parameter LORAWAN_APP_PORT.
  • Payload Length : The lenght of the payload (in bytes) to be transmitted can be configured using LORAWAN_APP_DATA_SIZE
  • Transmit Power : The transmit power can be configured using LORAWAN_TX_POWER (LoRaMAC verifies if the set power is compliant with the LoRaWAN spec and FCC guidelines)

/media/uploads/ubhat/loraconfig.png

Main.cpp (Device State Machine)

The end-device state machine is defined.

  • Initial State : Device is initialized.
  • Join State : For OTA, Join Request is transmitted to the network until Join Accept is received by the end-device. Join event function is called that sets Red LED ON.
  • Send State : Transmit payload frame is prepared. Tx event is called that blinks the Red LED indicating uplink transmission.
  • Cycle State : Next packet transmission is scheduled

LoRaEventProc.cpp (Events and On-board Application)

Define events during Join, Tx & Rx. Prepare TX packet by appending with appropriate application data.

/media/uploads/ubhat/lora_events.png

  • PrepareLoRaFrame(uint8_t port ) : Prepare LoRa payload frame with on-board application data such as GPS, Temperature, Battery, etc. LoRa.ApplicationCall(AppType ) calls application AppType defined in LoRaApp.cpp. AppType is defined in LoRaApp.h

/media/uploads/ubhat/lora_app.png

LoRaApp.cpp

User-defined applications such as GPS, Temp, Accelerometer, LED indications etc. Event based actions such as LED blink on Tx, LED toggle on downlink etc /media/uploads/ubhat/apptype.png

LoRaDeviceStateProc.cpp

Process function calls corresponding to different Device states /media/uploads/ubhat/device_state.png

LoRaMacLayerService.cpp

Define MAC Layer Services: MLME & MCPS

Serial Terminal Display

By using a serial port connection using applications such as teraterm or putty, one can view the status of the End-Device. Once the End-Device Joins the network, transmission parameters such as payload data, application port, message type etc. are displayed on the terminal.

/media/uploads/ubhat/serial.png

Default Application Payload

This application defaults to sending uplink data to logical port 5. The application payload consists of: /media/uploads/jknapp_smtc/payload.png

Sample Application Payload Calculation for Longitude/Latitude

Payload => 00 19 F6 352BBA A94C20 FFFF

Temperature Calculation

19H => 2510

Temp = 25/2 = 12.5 oC

Battery Level

FFH => 100 %

F6H => 96.5 %

Longitude Calculation

longitude = A94C20H => 1109507210

longitudinal coordinate = -360 + (longitude10 x 180/(223))

longitudinal coordinate = -121.93

Latitude Calculation

latitude = 352BBAH = 348460210

latitude coordinate = (latitude10 x 90/(223-1))

latitude coordinate = 37.39

Committer:
ubhat
Date:
Wed Aug 31 21:01:03 2016 +0000
Revision:
15:39a23f5affd1
Parent:
14:f687ec277e1b
Child:
18:18408c3c2d0c
Port13 application updates

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ubhat 0:69f2e28d12c1 1 /*
ubhat 0:69f2e28d12c1 2 / _____) _ | |
ubhat 0:69f2e28d12c1 3 ( (____ _____ ____ _| |_ _____ ____| |__
ubhat 0:69f2e28d12c1 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
ubhat 0:69f2e28d12c1 5 _____) ) ____| | | || |_| ____( (___| | | |
ubhat 0:69f2e28d12c1 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
ubhat 0:69f2e28d12c1 7 (C)2015 Semtech
ubhat 0:69f2e28d12c1 8
ubhat 0:69f2e28d12c1 9 Description: User-defined applications such as GPS, Temp, Accelerometer, LED indications etc.
ubhat 0:69f2e28d12c1 10 Event based actions such as LED blink on Tx, LED toggle on downlink etc
ubhat 0:69f2e28d12c1 11
ubhat 0:69f2e28d12c1 12 License: Revised BSD License, see LICENSE.TXT file include in the project
ubhat 0:69f2e28d12c1 13
ubhat 0:69f2e28d12c1 14 Maintainer: Uttam Bhat
ubhat 0:69f2e28d12c1 15 */
ubhat 0:69f2e28d12c1 16
ubhat 0:69f2e28d12c1 17 #include "LoRaApp.h"
ubhat 0:69f2e28d12c1 18
ubhat 7:92f4f419f91f 19 bool VerticalStatus = false;
ubhat 7:92f4f419f91f 20
ubhat 0:69f2e28d12c1 21 /*!
ubhat 0:69f2e28d12c1 22 * Red LED timer event
ubhat 0:69f2e28d12c1 23 */
ubhat 0:69f2e28d12c1 24 TimerLed RedLedTimer( Red );
ubhat 0:69f2e28d12c1 25
ubhat 0:69f2e28d12c1 26 /*!
ubhat 0:69f2e28d12c1 27 * Yellow LED timer event
ubhat 0:69f2e28d12c1 28 */
ubhat 0:69f2e28d12c1 29 TimerLed YellowLedTimer( Yellow );
ubhat 0:69f2e28d12c1 30
ubhat 0:69f2e28d12c1 31 /*!
ubhat 0:69f2e28d12c1 32 * Green LED timer event
ubhat 0:69f2e28d12c1 33 */
ubhat 0:69f2e28d12c1 34 TimerLed GreenLedTimer( Green );
ubhat 0:69f2e28d12c1 35
ubhat 0:69f2e28d12c1 36 Application::Application( uint8_t * memptr )
ubhat 0:69f2e28d12c1 37 {
ubhat 0:69f2e28d12c1 38 BuffAddr = memptr;
ubhat 0:69f2e28d12c1 39 memset( BuffAddr, 0, LORAWAN_APP_DATA_MAX_SIZE );
ubhat 6:f8194e691dd4 40 BuffPtr = 0;
ubhat 0:69f2e28d12c1 41 }
ubhat 0:69f2e28d12c1 42
ubhat 0:69f2e28d12c1 43 Application::~Application( )
ubhat 0:69f2e28d12c1 44 {
ubhat 0:69f2e28d12c1 45 }
ubhat 0:69f2e28d12c1 46
ubhat 0:69f2e28d12c1 47 void Application::ApplicationAppendData( uint8_t *pData, uint8_t len )
ubhat 0:69f2e28d12c1 48 {
ubhat 15:39a23f5affd1 49 if( ( BuffPtr + len ) <= LORAWAN_APP_DATA_SIZE )
ubhat 15:39a23f5affd1 50 {
ubhat 15:39a23f5affd1 51 memcpy( BuffAddr + BuffPtr, pData, len );
ubhat 15:39a23f5affd1 52 BuffPtr += len;
ubhat 15:39a23f5affd1 53 }
ubhat 0:69f2e28d12c1 54 }
ubhat 0:69f2e28d12c1 55
ubhat 0:69f2e28d12c1 56 void Application::ApplicationPtrPos( uint8_t ptrPos )
ubhat 0:69f2e28d12c1 57 {
ubhat 0:69f2e28d12c1 58 BuffPtr = ptrPos;
ubhat 0:69f2e28d12c1 59 }
ubhat 0:69f2e28d12c1 60
ubhat 0:69f2e28d12c1 61 void Application::ApplicationCall( eAppType App )
ubhat 0:69f2e28d12c1 62 {
ubhat 0:69f2e28d12c1 63 switch( App )
ubhat 0:69f2e28d12c1 64 {
ubhat 0:69f2e28d12c1 65 // Appends 8 Bytes (3 bytes longitude, 3 bytes latitude, 2 bytes altitude) to TX buffer
ubhat 0:69f2e28d12c1 66 case AppGps:
ubhat 0:69f2e28d12c1 67 {
ubhat 0:69f2e28d12c1 68 Gps.service( );
ubhat 0:69f2e28d12c1 69
ubhat 0:69f2e28d12c1 70 uint16_t altitudeGps = atoi( Gps.NmeaGpsData.NmeaAltitude );
ubhat 0:69f2e28d12c1 71
ubhat 0:69f2e28d12c1 72 if( ( BuffPtr + 8 ) <= LORAWAN_APP_DATA_SIZE )
ubhat 0:69f2e28d12c1 73 {
ubhat 0:69f2e28d12c1 74 BuffAddr[BuffPtr++] = ( Gps.LatitudeBinary >> 16 ) & 0xFF;
ubhat 0:69f2e28d12c1 75 BuffAddr[BuffPtr++] = ( Gps.LatitudeBinary >> 8 ) & 0xFF;
ubhat 0:69f2e28d12c1 76 BuffAddr[BuffPtr++] = Gps.LatitudeBinary & 0xFF;
ubhat 0:69f2e28d12c1 77 BuffAddr[BuffPtr++] = ( Gps.LongitudeBinary >> 16 ) & 0xFF;
ubhat 0:69f2e28d12c1 78 BuffAddr[BuffPtr++] = ( Gps.LongitudeBinary >> 8 ) & 0xFF;
ubhat 0:69f2e28d12c1 79 BuffAddr[BuffPtr++] = Gps.LongitudeBinary & 0xFF;
ubhat 0:69f2e28d12c1 80 BuffAddr[BuffPtr++] = ( altitudeGps >> 8 ) & 0xFF;
ubhat 0:69f2e28d12c1 81 BuffAddr[BuffPtr++] = altitudeGps & 0xFF;
ubhat 0:69f2e28d12c1 82 }
ubhat 0:69f2e28d12c1 83 break;
ubhat 0:69f2e28d12c1 84 }
ubhat 0:69f2e28d12c1 85
ubhat 0:69f2e28d12c1 86 // Appends 1 Byte to TX buffer
ubhat 13:6b6f4be13633 87 case AppPrsr:
ubhat 13:6b6f4be13633 88 {
ubhat 13:6b6f4be13633 89 if( ( BuffPtr + 2 ) <= LORAWAN_APP_DATA_SIZE )
ubhat 13:6b6f4be13633 90 {
ubhat 13:6b6f4be13633 91 volatile uint8_t stat;
ubhat 13:6b6f4be13633 92 float val;
ubhat 13:6b6f4be13633 93
ubhat 13:6b6f4be13633 94 Mpl3115a2.SetModeBarometer();
ubhat 13:6b6f4be13633 95 Mpl3115a2.ToggleOneShot( );
ubhat 13:6b6f4be13633 96
ubhat 13:6b6f4be13633 97 stat = Mpl3115a2.read(STATUS_REG);
ubhat 13:6b6f4be13633 98 while( (stat & 0x04) != 0x04 ) {
ubhat 13:6b6f4be13633 99 wait(0.01);
ubhat 13:6b6f4be13633 100 stat = Mpl3115a2.read(STATUS_REG);
ubhat 13:6b6f4be13633 101 }
ubhat 13:6b6f4be13633 102
ubhat 13:6b6f4be13633 103 val = Mpl3115a2.ReadBarometer()/100.0;
ubhat 13:6b6f4be13633 104
ubhat 13:6b6f4be13633 105 BuffAddr[BuffPtr++] = ( ( uint16_t ) val >> 8 ) & 0xFF;
ubhat 13:6b6f4be13633 106 BuffAddr[BuffPtr++] = ( ( uint16_t ) val ) & 0xFF;
ubhat 13:6b6f4be13633 107
ubhat 13:6b6f4be13633 108 }
ubhat 13:6b6f4be13633 109 break;
ubhat 13:6b6f4be13633 110 }
ubhat 13:6b6f4be13633 111
ubhat 13:6b6f4be13633 112 // Appends 1 Byte to TX buffer
ubhat 0:69f2e28d12c1 113 case AppTemp:
ubhat 0:69f2e28d12c1 114 {
ubhat 0:69f2e28d12c1 115 Mpl3115a2.ReadTemperature( );
ubhat 0:69f2e28d12c1 116 if( ( BuffPtr + 1 ) <= LORAWAN_APP_DATA_SIZE )
ubhat 0:69f2e28d12c1 117 {
ubhat 13:6b6f4be13633 118 BuffAddr[BuffPtr++] = ( int32_t )Mpl3115a2.Temperature; // Signed degrees Celcius in half degree units. So, +/-63 °C
ubhat 0:69f2e28d12c1 119 }
ubhat 0:69f2e28d12c1 120 break;
ubhat 13:6b6f4be13633 121 }
ubhat 0:69f2e28d12c1 122
ubhat 0:69f2e28d12c1 123 // Appends 1 Byte to TX buffer
ubhat 0:69f2e28d12c1 124 case AppBat:
ubhat 0:69f2e28d12c1 125 {
ubhat 0:69f2e28d12c1 126 if( ( BuffPtr + 1 ) <= LORAWAN_APP_DATA_SIZE )
ubhat 0:69f2e28d12c1 127 {
ubhat 13:6b6f4be13633 128 #ifdef BAT_VAL_PERCENT
ubhat 13:6b6f4be13633 129 uint16_t value;
ubhat 13:6b6f4be13633 130 value = BoardGetBatteryLevel();
ubhat 13:6b6f4be13633 131 BuffAddr[BuffPtr++] = ( value * 100 ) >> 8; // Bat level in %
ubhat 13:6b6f4be13633 132 #else
ubhat 0:69f2e28d12c1 133 BuffAddr[BuffPtr++] = BoardGetBatteryLevel( ); // Per LoRaWAN spec; 0 = Charging; 1...254 = level, 255 = N/A
ubhat 13:6b6f4be13633 134 #endif
ubhat 0:69f2e28d12c1 135 }
ubhat 0:69f2e28d12c1 136 break;
ubhat 0:69f2e28d12c1 137 }
ubhat 0:69f2e28d12c1 138
ubhat 0:69f2e28d12c1 139 // Appends incremental values of 1 Byte each to TX buffer until Full
ubhat 0:69f2e28d12c1 140 case AppRamp:
ubhat 0:69f2e28d12c1 141 {
ubhat 0:69f2e28d12c1 142 int32_t i, j;
ubhat 0:69f2e28d12c1 143
ubhat 0:69f2e28d12c1 144 // Populate Tx Buffer with increasing byte values starting from 0x00, 0x01, 0x02 ...
ubhat 0:69f2e28d12c1 145 for( i = BuffPtr, j = 0; i < LORAWAN_APP_DATA_SIZE; i++ )
ubhat 0:69f2e28d12c1 146 {
ubhat 0:69f2e28d12c1 147 BuffAddr[i] = j++;
ubhat 0:69f2e28d12c1 148 }
ubhat 0:69f2e28d12c1 149 BuffPtr = LORAWAN_APP_DATA_SIZE;
ubhat 0:69f2e28d12c1 150 break;
ubhat 0:69f2e28d12c1 151 }
ubhat 0:69f2e28d12c1 152
ubhat 0:69f2e28d12c1 153 // Appends 2 Bytes to TX buffer
ubhat 0:69f2e28d12c1 154 case AppAccl:
ubhat 0:69f2e28d12c1 155 {
ubhat 0:69f2e28d12c1 156 uint8_t statusReg;
ubhat 0:69f2e28d12c1 157
ubhat 0:69f2e28d12c1 158 // Read the PS_STATUS register
ubhat 0:69f2e28d12c1 159 statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );
ubhat 0:69f2e28d12c1 160
ubhat 0:69f2e28d12c1 161 /* Display Orientation of NAMote on Serial Port */
ubhat 0:69f2e28d12c1 162 SerialAcclMetrDisplay( statusReg );
ubhat 0:69f2e28d12c1 163
ubhat 0:69f2e28d12c1 164 // If Orientation of the Mote changed then let Green LED ON
ubhat 0:69f2e28d12c1 165 if( ( statusReg & 0x80 ) != 0 )
ubhat 0:69f2e28d12c1 166 {
ubhat 0:69f2e28d12c1 167 AppLed = 1;
ubhat 0:69f2e28d12c1 168 CtrlLED( Green, LED_ON );
ubhat 0:69f2e28d12c1 169 }
ubhat 0:69f2e28d12c1 170
ubhat 0:69f2e28d12c1 171 // Read and populate device orientation in Tx Buffer
ubhat 0:69f2e28d12c1 172 if( ( BuffPtr + 2 ) <= LORAWAN_APP_DATA_SIZE )
ubhat 0:69f2e28d12c1 173 {
ubhat 0:69f2e28d12c1 174 if( statusReg & 0x40 )
ubhat 0:69f2e28d12c1 175 {
ubhat 0:69f2e28d12c1 176 if( statusReg & 0x01 )
ubhat 0:69f2e28d12c1 177 {
ubhat 0:69f2e28d12c1 178 BuffAddr[BuffPtr++] = 0x66; // horizontal + faceup
ubhat 0:69f2e28d12c1 179 }
ubhat 0:69f2e28d12c1 180 else
ubhat 0:69f2e28d12c1 181 {
ubhat 0:69f2e28d12c1 182 BuffAddr[BuffPtr++] = 0x99; // horizontal + facedown
ubhat 0:69f2e28d12c1 183 }
ubhat 0:69f2e28d12c1 184
ubhat 0:69f2e28d12c1 185 BuffAddr[BuffPtr++] = 0; // vertical = false
ubhat 0:69f2e28d12c1 186 }
ubhat 0:69f2e28d12c1 187 else
ubhat 0:69f2e28d12c1 188 {
ubhat 0:69f2e28d12c1 189 BuffAddr[BuffPtr++] = 0; // horizontal = false
ubhat 0:69f2e28d12c1 190 BuffAddr[BuffPtr++] = 0x11; // vertical = true
ubhat 0:69f2e28d12c1 191 }
ubhat 0:69f2e28d12c1 192 }
ubhat 0:69f2e28d12c1 193
ubhat 0:69f2e28d12c1 194 break;
ubhat 6:f8194e691dd4 195 }
ubhat 0:69f2e28d12c1 196
ubhat 0:69f2e28d12c1 197 case AppAcclSenet:
ubhat 0:69f2e28d12c1 198 {
ubhat 0:69f2e28d12c1 199 uint8_t statusReg;
ubhat 0:69f2e28d12c1 200
ubhat 0:69f2e28d12c1 201 // Read the PS_STATUS register
ubhat 0:69f2e28d12c1 202 statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );
ubhat 0:69f2e28d12c1 203
ubhat 0:69f2e28d12c1 204 /* Display Orientation of NAMote on Serial Port */
ubhat 0:69f2e28d12c1 205 SerialAcclMetrDisplay( statusReg );
ubhat 0:69f2e28d12c1 206
ubhat 0:69f2e28d12c1 207 // If Orientation of the Mote changed then populate Upper Nibble of 0th Byte of Tx Buffer
ubhat 0:69f2e28d12c1 208 if( ( statusReg & 0x40 ) != 0 )
ubhat 0:69f2e28d12c1 209 {
ubhat 0:69f2e28d12c1 210 AppLed = 0;
ubhat 0:69f2e28d12c1 211 CtrlLED( Green, LED_OFF );
ubhat 0:69f2e28d12c1 212 BuffAddr[BuffPtr++] = 0; // horizontal
ubhat 0:69f2e28d12c1 213 }
ubhat 0:69f2e28d12c1 214 else
ubhat 0:69f2e28d12c1 215 {
ubhat 0:69f2e28d12c1 216 AppLed = 1;
ubhat 0:69f2e28d12c1 217 CtrlLED( Green, LED_ON );
ubhat 0:69f2e28d12c1 218 BuffAddr[BuffPtr++] = 10; // vertical
ubhat 0:69f2e28d12c1 219 }
ubhat 0:69f2e28d12c1 220
ubhat 0:69f2e28d12c1 221 break;
ubhat 0:69f2e28d12c1 222 }
ubhat 0:69f2e28d12c1 223
ubhat 13:6b6f4be13633 224 case AppAcclSensor:
ubhat 13:6b6f4be13633 225 {
ubhat 13:6b6f4be13633 226 uint8_t statusReg;
ubhat 14:f687ec277e1b 227 int8_t regVal;
ubhat 14:f687ec277e1b 228 int16_t axesData;
ubhat 13:6b6f4be13633 229
ubhat 13:6b6f4be13633 230 // Read the PS_STATUS register
ubhat 13:6b6f4be13633 231 statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );
ubhat 13:6b6f4be13633 232
ubhat 13:6b6f4be13633 233 /* Display Orientation of NAMote on Serial Port */
ubhat 13:6b6f4be13633 234 SerialAcclMetrDisplay( statusReg );
ubhat 13:6b6f4be13633 235
ubhat 13:6b6f4be13633 236 // If Orientation of the Mote changed then populate Upper Nibble of 0th Byte of Tx Buffer
ubhat 13:6b6f4be13633 237 if( ( statusReg & 0x80 ) != 0 )
ubhat 13:6b6f4be13633 238 {
ubhat 13:6b6f4be13633 239 CtrlLED( Green, LED_ON );
ubhat 13:6b6f4be13633 240 }
ubhat 13:6b6f4be13633 241 else
ubhat 13:6b6f4be13633 242 {
ubhat 13:6b6f4be13633 243 CtrlLED( Green, LED_OFF );
ubhat 13:6b6f4be13633 244 }
ubhat 13:6b6f4be13633 245
ubhat 13:6b6f4be13633 246 // Read and populate device orientation in Tx Buffer
ubhat 13:6b6f4be13633 247 if( ( BuffPtr + 6 ) <= LORAWAN_APP_DATA_SIZE )
ubhat 13:6b6f4be13633 248 {
ubhat 13:6b6f4be13633 249 uint8_t addr;
ubhat 13:6b6f4be13633 250 addr = MMA8451_OUT_X_MSB;
ubhat 13:6b6f4be13633 251
ubhat 13:6b6f4be13633 252 // Read X-axis Data
ubhat 13:6b6f4be13633 253 regVal = Mma8451q.read_single( addr++ );
ubhat 13:6b6f4be13633 254 axesData = regVal << 8;
ubhat 13:6b6f4be13633 255 regVal = Mma8451q.read_single( addr++ );
ubhat 13:6b6f4be13633 256 axesData |= regVal;
ubhat 13:6b6f4be13633 257 BuffAddr[BuffPtr++] = ( axesData >> 10 ) & 0xFF;
ubhat 13:6b6f4be13633 258 BuffAddr[BuffPtr++] = ( axesData >> 2 ) & 0xFF;
ubhat 13:6b6f4be13633 259
ubhat 13:6b6f4be13633 260 // Read Y-axis Data
ubhat 13:6b6f4be13633 261 regVal = Mma8451q.read_single( addr++ );
ubhat 13:6b6f4be13633 262 axesData = regVal << 8;
ubhat 13:6b6f4be13633 263 regVal = Mma8451q.read_single( addr++ );
ubhat 13:6b6f4be13633 264 axesData |= regVal;
ubhat 13:6b6f4be13633 265 BuffAddr[BuffPtr++] = ( axesData >> 10 ) & 0xFF;
ubhat 13:6b6f4be13633 266 BuffAddr[BuffPtr++] = ( axesData >> 2 ) & 0xFF;
ubhat 13:6b6f4be13633 267
ubhat 13:6b6f4be13633 268 // Read Z-axis Data
ubhat 13:6b6f4be13633 269 regVal = Mma8451q.read_single( addr++ );
ubhat 13:6b6f4be13633 270 axesData = regVal << 8;
ubhat 13:6b6f4be13633 271 regVal = Mma8451q.read_single( addr++ );
ubhat 13:6b6f4be13633 272 axesData |= regVal;
ubhat 13:6b6f4be13633 273 BuffAddr[BuffPtr++] = ( axesData >> 10 ) & 0xFF;
ubhat 13:6b6f4be13633 274 BuffAddr[BuffPtr++] = ( axesData >> 2 ) & 0xFF;
ubhat 13:6b6f4be13633 275 }
ubhat 13:6b6f4be13633 276
ubhat 13:6b6f4be13633 277 break;
ubhat 13:6b6f4be13633 278 }
ubhat 13:6b6f4be13633 279
ubhat 6:f8194e691dd4 280 case AppPushButton:
ubhat 6:f8194e691dd4 281 {
ubhat 6:f8194e691dd4 282 uint16_t PushButtonCnt;
ubhat 6:f8194e691dd4 283 uint8_t *p = (uint8_t *) &PushButtonCnt;
ubhat 6:f8194e691dd4 284
ubhat 6:f8194e691dd4 285 PushButtonCnt = LoRaMacUplinkStatus.UplinkCounter;
ubhat 6:f8194e691dd4 286
ubhat 6:f8194e691dd4 287 memcpy( &BuffAddr[BuffPtr], p, sizeof(uint16_t) );
ubhat 6:f8194e691dd4 288
ubhat 6:f8194e691dd4 289 break;
ubhat 6:f8194e691dd4 290 }
ubhat 6:f8194e691dd4 291
ubhat 0:69f2e28d12c1 292 default:
ubhat 0:69f2e28d12c1 293 {
ubhat 0:69f2e28d12c1 294 break;
ubhat 0:69f2e28d12c1 295 }
ubhat 0:69f2e28d12c1 296 }
ubhat 0:69f2e28d12c1 297 }
ubhat 0:69f2e28d12c1 298
ubhat 0:69f2e28d12c1 299 static void OnRedLedTimerEvent( void )
ubhat 0:69f2e28d12c1 300 {
ubhat 0:69f2e28d12c1 301 TimerStop( &RedLedTimer.LedTimer );
ubhat 0:69f2e28d12c1 302
ubhat 0:69f2e28d12c1 303 if( RedLed == LED_OFF )
ubhat 0:69f2e28d12c1 304 {
ubhat 0:69f2e28d12c1 305 RedLed = LED_ON;
ubhat 0:69f2e28d12c1 306 }
ubhat 0:69f2e28d12c1 307 else
ubhat 0:69f2e28d12c1 308 {
ubhat 0:69f2e28d12c1 309 RedLed = LED_OFF;
ubhat 0:69f2e28d12c1 310 }
ubhat 0:69f2e28d12c1 311 }
ubhat 0:69f2e28d12c1 312
ubhat 0:69f2e28d12c1 313 static void OnYellowLedTimerEvent( void )
ubhat 0:69f2e28d12c1 314 {
ubhat 0:69f2e28d12c1 315 TimerStop( &YellowLedTimer.LedTimer );
ubhat 0:69f2e28d12c1 316
ubhat 0:69f2e28d12c1 317 if( YellowLed == LED_OFF )
ubhat 0:69f2e28d12c1 318 {
ubhat 0:69f2e28d12c1 319 YellowLed = LED_ON;
ubhat 0:69f2e28d12c1 320 }
ubhat 0:69f2e28d12c1 321 else
ubhat 0:69f2e28d12c1 322 {
ubhat 0:69f2e28d12c1 323 YellowLed = LED_OFF;
ubhat 0:69f2e28d12c1 324 }
ubhat 0:69f2e28d12c1 325 }
ubhat 0:69f2e28d12c1 326
ubhat 0:69f2e28d12c1 327 static void OnGreenLedTimerEvent( void )
ubhat 0:69f2e28d12c1 328 {
ubhat 0:69f2e28d12c1 329 TimerStop( &GreenLedTimer.LedTimer );
ubhat 0:69f2e28d12c1 330
ubhat 0:69f2e28d12c1 331 if( GreenLed == LED_OFF )
ubhat 0:69f2e28d12c1 332 {
ubhat 0:69f2e28d12c1 333 GreenLed = LED_ON;
ubhat 0:69f2e28d12c1 334 }
ubhat 0:69f2e28d12c1 335 else
ubhat 0:69f2e28d12c1 336 {
ubhat 0:69f2e28d12c1 337 GreenLed = LED_OFF;
ubhat 0:69f2e28d12c1 338 }
ubhat 0:69f2e28d12c1 339 }
ubhat 0:69f2e28d12c1 340
ubhat 0:69f2e28d12c1 341 TimerLed::TimerLed( eLedType led )
ubhat 0:69f2e28d12c1 342 {
ubhat 0:69f2e28d12c1 343 switch( led )
ubhat 0:69f2e28d12c1 344 {
ubhat 0:69f2e28d12c1 345 case Red:
ubhat 0:69f2e28d12c1 346 {
ubhat 0:69f2e28d12c1 347 TimerInit( &LedTimer, OnRedLedTimerEvent );
ubhat 0:69f2e28d12c1 348 break;
ubhat 0:69f2e28d12c1 349 }
ubhat 0:69f2e28d12c1 350
ubhat 0:69f2e28d12c1 351 case Yellow:
ubhat 0:69f2e28d12c1 352 {
ubhat 0:69f2e28d12c1 353 TimerInit( &LedTimer, OnYellowLedTimerEvent );
ubhat 0:69f2e28d12c1 354 break;
ubhat 0:69f2e28d12c1 355 }
ubhat 0:69f2e28d12c1 356
ubhat 0:69f2e28d12c1 357 case Green:
ubhat 0:69f2e28d12c1 358 {
ubhat 0:69f2e28d12c1 359 TimerInit( &LedTimer, OnGreenLedTimerEvent );
ubhat 0:69f2e28d12c1 360 break;
ubhat 0:69f2e28d12c1 361 }
ubhat 0:69f2e28d12c1 362 }
ubhat 0:69f2e28d12c1 363
ubhat 0:69f2e28d12c1 364 }
ubhat 0:69f2e28d12c1 365
ubhat 0:69f2e28d12c1 366 TimerLed::~TimerLed( )
ubhat 0:69f2e28d12c1 367 {
ubhat 0:69f2e28d12c1 368 }
ubhat 0:69f2e28d12c1 369
ubhat 0:69f2e28d12c1 370 void BlinkLED( eLedType led, uint32_t time )
ubhat 0:69f2e28d12c1 371 {
ubhat 0:69f2e28d12c1 372 switch( led )
ubhat 0:69f2e28d12c1 373 {
ubhat 0:69f2e28d12c1 374 case Red:
ubhat 0:69f2e28d12c1 375 {
ubhat 0:69f2e28d12c1 376 TimerSetValue( &RedLedTimer.LedTimer, time );
ubhat 0:69f2e28d12c1 377 TimerStart( &RedLedTimer.LedTimer );
ubhat 0:69f2e28d12c1 378 RedLed = LED_ON;
ubhat 0:69f2e28d12c1 379 break;
ubhat 0:69f2e28d12c1 380 }
ubhat 0:69f2e28d12c1 381
ubhat 0:69f2e28d12c1 382 case Yellow:
ubhat 0:69f2e28d12c1 383 {
ubhat 0:69f2e28d12c1 384 TimerSetValue( &YellowLedTimer.LedTimer, time );
ubhat 0:69f2e28d12c1 385 TimerStart( &YellowLedTimer.LedTimer );
ubhat 0:69f2e28d12c1 386 YellowLed = LED_ON;
ubhat 0:69f2e28d12c1 387 break;
ubhat 0:69f2e28d12c1 388 }
ubhat 0:69f2e28d12c1 389
ubhat 0:69f2e28d12c1 390 case Green:
ubhat 0:69f2e28d12c1 391 {
ubhat 0:69f2e28d12c1 392 TimerSetValue( &GreenLedTimer.LedTimer, time );
ubhat 0:69f2e28d12c1 393 TimerStart( &GreenLedTimer.LedTimer );
ubhat 0:69f2e28d12c1 394 GreenLed = LED_ON;
ubhat 0:69f2e28d12c1 395 break;
ubhat 0:69f2e28d12c1 396 }
ubhat 0:69f2e28d12c1 397 }
ubhat 0:69f2e28d12c1 398 }
ubhat 0:69f2e28d12c1 399
ubhat 0:69f2e28d12c1 400 void ToggleLED( eLedType led )
ubhat 0:69f2e28d12c1 401 {
ubhat 0:69f2e28d12c1 402 switch( led )
ubhat 0:69f2e28d12c1 403 {
ubhat 0:69f2e28d12c1 404 case Red:
ubhat 0:69f2e28d12c1 405 {
ubhat 0:69f2e28d12c1 406 if( RedLed == LED_OFF )
ubhat 0:69f2e28d12c1 407 {
ubhat 0:69f2e28d12c1 408 RedLed = LED_ON;
ubhat 0:69f2e28d12c1 409 }
ubhat 0:69f2e28d12c1 410 else
ubhat 0:69f2e28d12c1 411 {
ubhat 0:69f2e28d12c1 412 RedLed = LED_OFF;
ubhat 0:69f2e28d12c1 413 }
ubhat 0:69f2e28d12c1 414 break;
ubhat 0:69f2e28d12c1 415 }
ubhat 0:69f2e28d12c1 416
ubhat 0:69f2e28d12c1 417 case Yellow:
ubhat 0:69f2e28d12c1 418 {
ubhat 0:69f2e28d12c1 419 if( YellowLed == LED_OFF )
ubhat 0:69f2e28d12c1 420 {
ubhat 0:69f2e28d12c1 421 YellowLed = LED_ON;
ubhat 0:69f2e28d12c1 422 }
ubhat 0:69f2e28d12c1 423 else
ubhat 0:69f2e28d12c1 424 {
ubhat 0:69f2e28d12c1 425 YellowLed = LED_OFF;
ubhat 0:69f2e28d12c1 426 }
ubhat 0:69f2e28d12c1 427 break;
ubhat 0:69f2e28d12c1 428 }
ubhat 0:69f2e28d12c1 429
ubhat 0:69f2e28d12c1 430 case Green:
ubhat 0:69f2e28d12c1 431 {
ubhat 0:69f2e28d12c1 432 if( GreenLed == LED_OFF )
ubhat 0:69f2e28d12c1 433 {
ubhat 0:69f2e28d12c1 434 GreenLed = LED_ON;
ubhat 0:69f2e28d12c1 435 }
ubhat 0:69f2e28d12c1 436 else
ubhat 0:69f2e28d12c1 437 {
ubhat 0:69f2e28d12c1 438 GreenLed = LED_OFF;
ubhat 0:69f2e28d12c1 439 }
ubhat 0:69f2e28d12c1 440 break;
ubhat 0:69f2e28d12c1 441 }
ubhat 0:69f2e28d12c1 442 }
ubhat 0:69f2e28d12c1 443 }
ubhat 0:69f2e28d12c1 444
ubhat 0:69f2e28d12c1 445 void CtrlLED( eLedType led, uint8_t state )
ubhat 0:69f2e28d12c1 446 {
ubhat 0:69f2e28d12c1 447 switch( led )
ubhat 0:69f2e28d12c1 448 {
ubhat 0:69f2e28d12c1 449 case Red:
ubhat 0:69f2e28d12c1 450 {
ubhat 0:69f2e28d12c1 451 RedLed = state;
ubhat 0:69f2e28d12c1 452 break;
ubhat 0:69f2e28d12c1 453 }
ubhat 0:69f2e28d12c1 454
ubhat 0:69f2e28d12c1 455 case Yellow:
ubhat 0:69f2e28d12c1 456 {
ubhat 0:69f2e28d12c1 457 YellowLed = state;
ubhat 0:69f2e28d12c1 458 break;
ubhat 0:69f2e28d12c1 459 }
ubhat 0:69f2e28d12c1 460
ubhat 0:69f2e28d12c1 461 case Green:
ubhat 0:69f2e28d12c1 462 {
ubhat 0:69f2e28d12c1 463 GreenLed = state;
ubhat 0:69f2e28d12c1 464 break;
ubhat 0:69f2e28d12c1 465 }
ubhat 0:69f2e28d12c1 466
ubhat 0:69f2e28d12c1 467 case Usr:
ubhat 0:69f2e28d12c1 468 {
ubhat 0:69f2e28d12c1 469 if( state )
ubhat 0:69f2e28d12c1 470 {
ubhat 0:69f2e28d12c1 471 UsrLed = LED_ON;
ubhat 0:69f2e28d12c1 472 }
ubhat 0:69f2e28d12c1 473 else
ubhat 0:69f2e28d12c1 474 {
ubhat 0:69f2e28d12c1 475 UsrLed = LED_OFF;
ubhat 0:69f2e28d12c1 476 }
ubhat 0:69f2e28d12c1 477 break;
ubhat 0:69f2e28d12c1 478 }
ubhat 0:69f2e28d12c1 479 }
ubhat 0:69f2e28d12c1 480 }
ubhat 7:92f4f419f91f 481
ubhat 7:92f4f419f91f 482 void CheckOrientation( void )
ubhat 7:92f4f419f91f 483 {
ubhat 7:92f4f419f91f 484 uint8_t statusReg;
ubhat 7:92f4f419f91f 485
ubhat 7:92f4f419f91f 486 // Read the PS_STATUS register
ubhat 7:92f4f419f91f 487 statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );
ubhat 7:92f4f419f91f 488
ubhat 7:92f4f419f91f 489 // If Orientation of the Mote changed then populate Upper Nibble of 0th Byte of Tx Buffer
ubhat 7:92f4f419f91f 490 if( ( statusReg & 0x40 ) != 0 )
ubhat 7:92f4f419f91f 491 {
ubhat 7:92f4f419f91f 492 CtrlLED( Green, LED_OFF );
ubhat 7:92f4f419f91f 493 VerticalStatus = false; // horizontal
ubhat 7:92f4f419f91f 494 }
ubhat 7:92f4f419f91f 495 else
ubhat 7:92f4f419f91f 496 {
ubhat 7:92f4f419f91f 497 CtrlLED( Green, LED_ON );
ubhat 7:92f4f419f91f 498 VerticalStatus = true; // vertical
ubhat 7:92f4f419f91f 499 }
ubhat 7:92f4f419f91f 500 }