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:
Tue Aug 30 06:35:16 2016 +0000
Revision:
13:6b6f4be13633
Parent:
7:92f4f419f91f
Child:
14:f687ec277e1b
NA Mote Sensor Application (Pressure, Battery, Temperature + Accelerometer)

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