end node on synchronous star LoRa network.

Dependencies:   SX127x sx12xx_hal TSL2561

radio chip selection

Radio chip driver is not included, allowing choice of radio device.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
if you're using SX1280, then import sx1280 driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.

This project for use with LoRaWAN_singlechannel_gateway project.

Alternately gateway running on raspberry pi can be used as gateway.

LoRaWAN on single radio channel

Network description is at gateway project page. Synchronous star network.

Hardware Support

This project supports SX1276 and SX1272, sx126x kit, sx126x shield, and sx128x 2.4GHz. The ST board B-L072Z-LRWAN1 is also supported (TypeABZ module). When B-L072Z-LRWAN1 target is selected, TARGET_DISCO_L072CZ_LRWAN1 is defined by tools, allowing correct radio driver configuration for this platform. Alternately, any mbed board that can use LoRa radio shield board should work, but NUCLEO boards are tested.

End-node Unique ID

DevEUI is created from CPU serial number. AppEUI and AppKey are declared as software constants.

End-node Configuration

Data rate definition LORAMAC_DEFAULT_DATARATE configured in LoRaMac-definitions.h. See gateway project page for configuration of gateway.
LoRaWAN addressing is configured in Comissioning.h; only OTA mode is functional.
Header file board/lora_config.h, selects application layer options (i.e. sensors) to be compiled in.

Serial Interface

Serial port operates at 115200bps.
Application layer single_us915_main.cpp User button triggers uplink (i.e. blue button on nucleo board), or jumper enables continuously sends repeated uplink packets. The MAC layer holds each uplink request until the allocated timeslot.

commandargumentsdescription
?-print available commands
. (period)-print status (DevEUI, DevAddr, etc)
ullength integerset payload length of test uplink packets

sensor demo

Selected grove sensors may be plugged into SX1272 shield.
To enable, edit lora_config.h to define SENSORS.

Sensor connections on SX1272MB2xAS:

D8 D9: buttonRX TX: (unused)A3 A4: Rotary Angle Sensor
D6 D7: RGB LEDSCL SDA: digital light sensorA1 A2: Rotary Angle Sensor

Digital input pin, state reported via uplink: PC8
Digital output pin, controlled via downlink: PC6
PWM out: PB_10

Jumper enables auto-repeated transmit: PC10 and PC12 on NUCLEO board, located on end of morpho headers nearby JP4.

Committer:
Wayne Roberts
Date:
Sun Dec 16 10:22:21 2018 -0800
Revision:
31:6ed03f61af64
Parent:
29:ad409c68c0a6
Child:
34:9c8966cd66a2
rename header file due to header with same name in mbed-os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 0:8f0d0ae0a077 1 /*
dudmuck 0:8f0d0ae0a077 2 / _____) _ | |
dudmuck 0:8f0d0ae0a077 3 ( (____ _____ ____ _| |_ _____ ____| |__
dudmuck 0:8f0d0ae0a077 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
dudmuck 0:8f0d0ae0a077 5 _____) ) ____| | | || |_| ____( (___| | | |
dudmuck 0:8f0d0ae0a077 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
dudmuck 0:8f0d0ae0a077 7 (C)2015 Semtech
dudmuck 0:8f0d0ae0a077 8
dudmuck 0:8f0d0ae0a077 9 Description: LoRaMac classA device implementation
dudmuck 0:8f0d0ae0a077 10
dudmuck 0:8f0d0ae0a077 11 License: Revised BSD License, see LICENSE.TXT file include in the project
dudmuck 0:8f0d0ae0a077 12 */
dudmuck 0:8f0d0ae0a077 13 #include "mbed.h"
dudmuck 0:8f0d0ae0a077 14 #include "board.h"
dudmuck 0:8f0d0ae0a077 15
Wayne Roberts 31:6ed03f61af64 16 #include "LoRaMacSingle.h"
dudmuck 0:8f0d0ae0a077 17 #include "Commissioning.h"
dudmuck 11:4c337f5bbe4c 18 #include "commands.h"
dudmuck 0:8f0d0ae0a077 19
dudmuck 23:a862b5601663 20 #ifdef ENABLE_LUMINOSITY
dudmuck 12:ed33c53afcaf 21 #include "TSL2561.h"
dudmuck 12:ed33c53afcaf 22 //TSL2561 tsl2561(TSL2561_ADDR_FLOAT); // https://developer.mbed.org/components/Grove-Digital-Light-Sensor/
dudmuck 12:ed33c53afcaf 23 TSL2561 tsl2561(TSL2561_ADDR_LOW);
dudmuck 23:a862b5601663 24 #endif
dudmuck 23:a862b5601663 25
dudmuck 23:a862b5601663 26 #ifdef ENABLE_RGB
dudmuck 23:a862b5601663 27 #include "ChainableLED.h"
dudmuck 23:a862b5601663 28 ChainableLED rgb(D6, D7, 1); // https://developer.mbed.org/components/Grove-Chainable-RGB-LED/
dudmuck 10:00997daeb0c0 29 #endif
dudmuck 10:00997daeb0c0 30
dudmuck 25:fed9d5b77183 31 #ifdef TYPE_ABZ
dudmuck 25:fed9d5b77183 32 InterruptIn user_button(PB_2);
dudmuck 25:fed9d5b77183 33 #else
dudmuck 25:fed9d5b77183 34 InterruptIn user_button(USER_BUTTON);
dudmuck 25:fed9d5b77183 35 #endif
dudmuck 25:fed9d5b77183 36
dudmuck 23:a862b5601663 37 #ifdef SENSORS
dudmuck 23:a862b5601663 38 #ifdef TYPE_ABZ /* DISCO_L072CZ_LRWAN1 */
dudmuck 23:a862b5601663 39 PwmOut pwm(PB_5);
dudmuck 23:a862b5601663 40 DigitalIn pc8_in(PB_13);
dudmuck 23:a862b5601663 41 DigitalOut pc6_out(PB_14);
dudmuck 23:a862b5601663 42 AnalogIn a0(PA_0);
dudmuck 23:a862b5601663 43 AnalogIn a2(PA_4);
dudmuck 23:a862b5601663 44 #else
dudmuck 23:a862b5601663 45 PwmOut pwm(PB_11);
dudmuck 23:a862b5601663 46 DigitalIn pc8_in(PC_8);
dudmuck 23:a862b5601663 47 DigitalOut pc6_out(PC_6);
dudmuck 23:a862b5601663 48 AnalogIn a1(A1); // https://developer.mbed.org/teams/Seeed/wiki/Potentiometer
dudmuck 23:a862b5601663 49 AnalogIn a3(A3); // https://developer.mbed.org/teams/Seeed/wiki/Potentiometer
dudmuck 23:a862b5601663 50 #endif
dudmuck 26:8227a4edb216 51
dudmuck 26:8227a4edb216 52 #define N_SAMPLES 4
dudmuck 26:8227a4edb216 53 struct sens {
dudmuck 27:c8b432b2a4a8 54 uint16_t seq;
dudmuck 26:8227a4edb216 55 uint16_t ain_A, ain_B;
dudmuck 26:8227a4edb216 56 uint8_t pins;
dudmuck 26:8227a4edb216 57 } sensor[N_SAMPLES];
dudmuck 26:8227a4edb216 58 uint8_t sensor_in_idx, sensor_out_idx;
dudmuck 27:c8b432b2a4a8 59 uint16_t sample_seqnum;
dudmuck 28:36be305a5e5e 60 bool sensor_overflow;
dudmuck 28:36be305a5e5e 61 #define POLL_RATE 1.0
dudmuck 26:8227a4edb216 62
dudmuck 26:8227a4edb216 63 void sensor_poll()
dudmuck 26:8227a4edb216 64 {
dudmuck 27:c8b432b2a4a8 65 sensor[sensor_in_idx].seq = sample_seqnum++;
dudmuck 26:8227a4edb216 66 #ifdef TYPE_ABZ
dudmuck 26:8227a4edb216 67 sensor[sensor_in_idx].ain_A = a0.read_u16();
dudmuck 26:8227a4edb216 68 sensor[sensor_in_idx].ain_B = a2.read_u16();
dudmuck 26:8227a4edb216 69 #else
dudmuck 26:8227a4edb216 70 sensor[sensor_in_idx].ain_A = a1.read_u16();
dudmuck 26:8227a4edb216 71 sensor[sensor_in_idx].ain_B = a3.read_u16();
dudmuck 26:8227a4edb216 72 #endif
dudmuck 26:8227a4edb216 73 sensor[sensor_in_idx].pins = pc8_in.read();
dudmuck 26:8227a4edb216 74 sensor[sensor_in_idx].pins <<= 1;
dudmuck 26:8227a4edb216 75 sensor[sensor_in_idx].pins = pc6_out.read();
dudmuck 26:8227a4edb216 76 if (++sensor_in_idx == N_SAMPLES)
dudmuck 26:8227a4edb216 77 sensor_in_idx = 0;
dudmuck 28:36be305a5e5e 78
dudmuck 28:36be305a5e5e 79 if (sensor_in_idx == sensor_out_idx)
dudmuck 28:36be305a5e5e 80 sensor_overflow = true;
dudmuck 26:8227a4edb216 81 }
dudmuck 26:8227a4edb216 82 LowPowerTicker sensor_ticker;
dudmuck 23:a862b5601663 83 #endif /* SENSORS */
dudmuck 23:a862b5601663 84
Wayne Roberts 29:ad409c68c0a6 85 //DigitalOut pc2(PC_2);
dudmuck 12:ed33c53afcaf 86
dudmuck 23:a862b5601663 87 #if defined(TARGET_DISCO_L072CZ_LRWAN1) || ( defined(TARGET_NUCLEO_L073RZ) && defined(TYPE_ABZ) )
dudmuck 23:a862b5601663 88 DigitalOut jumper_out(PA_11);
dudmuck 23:a862b5601663 89 InterruptIn jumper_in(PA_12);
dudmuck 23:a862b5601663 90 #else
dudmuck 23:a862b5601663 91 DigitalOut jumper_out(PC_10);
dudmuck 23:a862b5601663 92 InterruptIn jumper_in(PC_12);
dudmuck 23:a862b5601663 93 #endif /* murata */
dudmuck 10:00997daeb0c0 94
dudmuck 0:8f0d0ae0a077 95 char pcbuf[128];
dudmuck 0:8f0d0ae0a077 96 int pcbuf_len;
dudmuck 0:8f0d0ae0a077 97
dudmuck 0:8f0d0ae0a077 98 /*!
dudmuck 0:8f0d0ae0a077 99 * Defines the application data transmission duty cycle. 5s, value in [ms].
dudmuck 0:8f0d0ae0a077 100 */
dudmuck 0:8f0d0ae0a077 101 #define APP_TX_DUTYCYCLE 5000
dudmuck 0:8f0d0ae0a077 102
dudmuck 0:8f0d0ae0a077 103 /*!
dudmuck 0:8f0d0ae0a077 104 * Defines a random delay for application data transmission duty cycle. 1s,
dudmuck 0:8f0d0ae0a077 105 * value in [ms].
dudmuck 0:8f0d0ae0a077 106 */
dudmuck 0:8f0d0ae0a077 107 #define APP_TX_DUTYCYCLE_RND 1000
dudmuck 0:8f0d0ae0a077 108
dudmuck 0:8f0d0ae0a077 109 /*!
dudmuck 0:8f0d0ae0a077 110 * LoRaWAN confirmed messages
dudmuck 0:8f0d0ae0a077 111 */
dudmuck 0:8f0d0ae0a077 112 #define LORAWAN_CONFIRMED_MSG_ON true
dudmuck 0:8f0d0ae0a077 113
dudmuck 0:8f0d0ae0a077 114 /*!
dudmuck 0:8f0d0ae0a077 115 * LoRaWAN application port
dudmuck 0:8f0d0ae0a077 116 */
dudmuck 0:8f0d0ae0a077 117 #define LORAWAN_APP_PORT 15
dudmuck 0:8f0d0ae0a077 118
dudmuck 0:8f0d0ae0a077 119 /*!
dudmuck 0:8f0d0ae0a077 120 * User application data buffer size
dudmuck 0:8f0d0ae0a077 121 */
dudmuck 0:8f0d0ae0a077 122 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
dudmuck 0:8f0d0ae0a077 123 #define LORAWAN_APP_DATA_SIZE 6
dudmuck 0:8f0d0ae0a077 124
dudmuck 0:8f0d0ae0a077 125 #else
dudmuck 0:8f0d0ae0a077 126 #define LORAWAN_APP_DATA_SIZE 1
dudmuck 0:8f0d0ae0a077 127
dudmuck 0:8f0d0ae0a077 128 #endif
dudmuck 0:8f0d0ae0a077 129
dudmuck 0:8f0d0ae0a077 130 static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
dudmuck 0:8f0d0ae0a077 131 static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
dudmuck 0:8f0d0ae0a077 132 static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
dudmuck 0:8f0d0ae0a077 133
dudmuck 0:8f0d0ae0a077 134 #if( OVER_THE_AIR_ACTIVATION == 0 )
dudmuck 0:8f0d0ae0a077 135
dudmuck 0:8f0d0ae0a077 136 static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
dudmuck 0:8f0d0ae0a077 137 static uint8_t AppSKey[] = LORAWAN_APPSKEY;
dudmuck 0:8f0d0ae0a077 138
dudmuck 0:8f0d0ae0a077 139 /*!
dudmuck 0:8f0d0ae0a077 140 * Device address
dudmuck 0:8f0d0ae0a077 141 */
dudmuck 0:8f0d0ae0a077 142 static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
dudmuck 0:8f0d0ae0a077 143
dudmuck 0:8f0d0ae0a077 144 #endif
dudmuck 0:8f0d0ae0a077 145
dudmuck 0:8f0d0ae0a077 146 /*!
dudmuck 0:8f0d0ae0a077 147 * Application port
dudmuck 0:8f0d0ae0a077 148 */
dudmuck 23:a862b5601663 149 #if defined(SENSORS)
dudmuck 10:00997daeb0c0 150 static uint8_t AppPort = SENSOR_PORT;
dudmuck 10:00997daeb0c0 151 #else
dudmuck 10:00997daeb0c0 152 static uint8_t AppPort = LORAWAN_APP_PORT;
dudmuck 10:00997daeb0c0 153 #endif
dudmuck 0:8f0d0ae0a077 154
dudmuck 0:8f0d0ae0a077 155 /*!
dudmuck 0:8f0d0ae0a077 156 * User application data size
dudmuck 0:8f0d0ae0a077 157 */
dudmuck 0:8f0d0ae0a077 158 static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE;
dudmuck 0:8f0d0ae0a077 159 static unsigned int uplink_length; // user assigned
dudmuck 0:8f0d0ae0a077 160
dudmuck 0:8f0d0ae0a077 161 /*!
dudmuck 0:8f0d0ae0a077 162 * User application data buffer size
dudmuck 0:8f0d0ae0a077 163 */
dudmuck 0:8f0d0ae0a077 164 #define LORAWAN_APP_DATA_MAX_SIZE 128
dudmuck 0:8f0d0ae0a077 165
dudmuck 0:8f0d0ae0a077 166 /*!
dudmuck 0:8f0d0ae0a077 167 * User application data
dudmuck 0:8f0d0ae0a077 168 */
dudmuck 0:8f0d0ae0a077 169 static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
dudmuck 0:8f0d0ae0a077 170
dudmuck 0:8f0d0ae0a077 171 /*!
dudmuck 0:8f0d0ae0a077 172 * Indicates if the node is sending confirmed or unconfirmed messages
dudmuck 0:8f0d0ae0a077 173 */
dudmuck 0:8f0d0ae0a077 174 static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
dudmuck 0:8f0d0ae0a077 175
dudmuck 0:8f0d0ae0a077 176 /*!
dudmuck 0:8f0d0ae0a077 177 * Defines the application data transmission duty cycle
dudmuck 0:8f0d0ae0a077 178 */
dudmuck 0:8f0d0ae0a077 179 static uint32_t TxDutyCycleTime;
dudmuck 0:8f0d0ae0a077 180
dudmuck 0:8f0d0ae0a077 181 /*!
dudmuck 0:8f0d0ae0a077 182 * Timer to handle the application data transmission duty cycle
dudmuck 0:8f0d0ae0a077 183 */
dudmuck 17:3215f12051f9 184 LowPowerTimeout TxNextPacketTimeout;
dudmuck 0:8f0d0ae0a077 185
dudmuck 0:8f0d0ae0a077 186 volatile bool send_at_beacon;
dudmuck 0:8f0d0ae0a077 187 volatile bool awaiting_mcps_indic;
dudmuck 21:500ff43d8424 188 bool join_retry;
dudmuck 0:8f0d0ae0a077 189 /*!
dudmuck 0:8f0d0ae0a077 190 * Specifies the state of the application LED
dudmuck 0:8f0d0ae0a077 191 */
dudmuck 0:8f0d0ae0a077 192 static bool AppLedStateOn = false;
dudmuck 0:8f0d0ae0a077 193
dudmuck 0:8f0d0ae0a077 194 /*!
dudmuck 0:8f0d0ae0a077 195 * Device states
dudmuck 0:8f0d0ae0a077 196 */
dudmuck 0:8f0d0ae0a077 197 static enum eDeviceState
dudmuck 0:8f0d0ae0a077 198 {
dudmuck 0:8f0d0ae0a077 199 DEVICE_STATE_INIT,
dudmuck 0:8f0d0ae0a077 200 DEVICE_STATE_JOIN,
dudmuck 0:8f0d0ae0a077 201 DEVICE_STATE_CYCLE,
dudmuck 16:915815632c1f 202 DEVICE_STATE_SLEEP,
dudmuck 18:9ac71c0eb70d 203 DEVICE_STATE_REJOIN,
dudmuck 18:9ac71c0eb70d 204 DEVICE_STATE_UPLINK
dudmuck 0:8f0d0ae0a077 205 }DeviceState;
dudmuck 0:8f0d0ae0a077 206
dudmuck 0:8f0d0ae0a077 207 /*!
dudmuck 0:8f0d0ae0a077 208 * Strucure containing the Uplink status
dudmuck 0:8f0d0ae0a077 209 */
dudmuck 0:8f0d0ae0a077 210 struct sLoRaMacUplinkStatus
dudmuck 0:8f0d0ae0a077 211 {
dudmuck 0:8f0d0ae0a077 212 uint8_t Acked;
dudmuck 0:8f0d0ae0a077 213 //int8_t Datarate;
dudmuck 0:8f0d0ae0a077 214 uint16_t UplinkCounter;
dudmuck 0:8f0d0ae0a077 215 uint8_t Port;
dudmuck 0:8f0d0ae0a077 216 uint8_t *Buffer;
dudmuck 0:8f0d0ae0a077 217 uint8_t BufferSize;
dudmuck 0:8f0d0ae0a077 218 }LoRaMacUplinkStatus;
dudmuck 0:8f0d0ae0a077 219 //volatile bool UplinkStatusUpdated = false;
dudmuck 0:8f0d0ae0a077 220
dudmuck 0:8f0d0ae0a077 221 /*!
dudmuck 0:8f0d0ae0a077 222 * Strucure containing the Downlink status
dudmuck 0:8f0d0ae0a077 223 */
dudmuck 0:8f0d0ae0a077 224 struct sLoRaMacDownlinkStatus
dudmuck 0:8f0d0ae0a077 225 {
dudmuck 0:8f0d0ae0a077 226 int16_t Rssi;
dudmuck 0:8f0d0ae0a077 227 int8_t Snr;
dudmuck 0:8f0d0ae0a077 228 uint16_t DownlinkCounter;
dudmuck 0:8f0d0ae0a077 229 bool RxData;
dudmuck 0:8f0d0ae0a077 230 uint8_t Port;
dudmuck 0:8f0d0ae0a077 231 uint8_t *Buffer;
dudmuck 0:8f0d0ae0a077 232 uint8_t BufferSize;
dudmuck 0:8f0d0ae0a077 233 }LoRaMacDownlinkStatus;
dudmuck 0:8f0d0ae0a077 234
dudmuck 2:f2d9aa163652 235 static uint8_t missed_count;
dudmuck 2:f2d9aa163652 236
dudmuck 0:8f0d0ae0a077 237
dudmuck 0:8f0d0ae0a077 238 /*!
dudmuck 0:8f0d0ae0a077 239 * \brief Prepares the payload of the frame
dudmuck 0:8f0d0ae0a077 240 */
dudmuck 0:8f0d0ae0a077 241 static void PrepareTxFrame( uint8_t port )
dudmuck 0:8f0d0ae0a077 242 {
dudmuck 0:8f0d0ae0a077 243 switch( port )
dudmuck 0:8f0d0ae0a077 244 {
dudmuck 0:8f0d0ae0a077 245 case 15:
dudmuck 0:8f0d0ae0a077 246 {
dudmuck 0:8f0d0ae0a077 247 AppData[0] = AppLedStateOn;
dudmuck 0:8f0d0ae0a077 248 if( IsTxConfirmed == true )
dudmuck 0:8f0d0ae0a077 249 {
dudmuck 0:8f0d0ae0a077 250 AppData[1] = LoRaMacDownlinkStatus.DownlinkCounter >> 8;
dudmuck 0:8f0d0ae0a077 251 AppData[2] = LoRaMacDownlinkStatus.DownlinkCounter;
dudmuck 0:8f0d0ae0a077 252 AppData[3] = LoRaMacDownlinkStatus.Rssi >> 8;
dudmuck 0:8f0d0ae0a077 253 AppData[4] = LoRaMacDownlinkStatus.Rssi;
dudmuck 0:8f0d0ae0a077 254 AppData[5] = LoRaMacDownlinkStatus.Snr;
dudmuck 0:8f0d0ae0a077 255 }
dudmuck 0:8f0d0ae0a077 256 }
dudmuck 0:8f0d0ae0a077 257 break;
dudmuck 23:a862b5601663 258 #if defined(SENSORS)
dudmuck 10:00997daeb0c0 259 case SENSOR_PORT:
dudmuck 12:ed33c53afcaf 260 {
dudmuck 26:8227a4edb216 261 uint16_t x = 0xffff;
dudmuck 23:a862b5601663 262 #ifdef ENABLE_LUMINOSITY
dudmuck 23:a862b5601663 263 x = tsl2561.getLuminosity(TSL2561_VISIBLE);
dudmuck 23:a862b5601663 264 #endif
dudmuck 28:36be305a5e5e 265 if (sensor_overflow) {
Wayne Roberts 29:ad409c68c0a6 266 app_printf("sensor_overflow\r\n");
dudmuck 28:36be305a5e5e 267 sensor_overflow = false;
dudmuck 28:36be305a5e5e 268 }
dudmuck 26:8227a4edb216 269 AppDataSize = 0;
dudmuck 26:8227a4edb216 270 AppData[AppDataSize++] = x >> 8;
dudmuck 26:8227a4edb216 271 AppData[AppDataSize++] = x & 0xff;
dudmuck 26:8227a4edb216 272 while (sensor_in_idx != sensor_out_idx) {
dudmuck 27:c8b432b2a4a8 273 AppData[AppDataSize++] = sensor[sensor_out_idx].seq >> 8;
dudmuck 27:c8b432b2a4a8 274 AppData[AppDataSize++] = sensor[sensor_out_idx].seq & 0xff;
dudmuck 26:8227a4edb216 275 AppData[AppDataSize++] = sensor[sensor_out_idx].ain_A >> 8;
dudmuck 26:8227a4edb216 276 AppData[AppDataSize++] = sensor[sensor_out_idx].ain_A & 0xff;
dudmuck 26:8227a4edb216 277 AppData[AppDataSize++] = sensor[sensor_out_idx].ain_B >> 8;
dudmuck 26:8227a4edb216 278 AppData[AppDataSize++] = sensor[sensor_out_idx].ain_B & 0xff;
dudmuck 26:8227a4edb216 279 AppData[AppDataSize++] = sensor[sensor_out_idx].pins;
dudmuck 26:8227a4edb216 280 if (++sensor_out_idx == N_SAMPLES)
dudmuck 26:8227a4edb216 281 sensor_out_idx = 0;
dudmuck 26:8227a4edb216 282 }
dudmuck 12:ed33c53afcaf 283 }
dudmuck 10:00997daeb0c0 284 break;
dudmuck 23:a862b5601663 285 #endif /* SENSORS */
dudmuck 0:8f0d0ae0a077 286 default:
dudmuck 0:8f0d0ae0a077 287 break;
dudmuck 0:8f0d0ae0a077 288 }
dudmuck 0:8f0d0ae0a077 289 }
dudmuck 0:8f0d0ae0a077 290
dudmuck 0:8f0d0ae0a077 291 void
dudmuck 0:8f0d0ae0a077 292 LoRaMacEventInfoStatus_to_string(LoRaMacEventInfoStatus_t status, char* dst)
dudmuck 0:8f0d0ae0a077 293 {
dudmuck 0:8f0d0ae0a077 294 const char* ptr = NULL;
dudmuck 0:8f0d0ae0a077 295
dudmuck 0:8f0d0ae0a077 296 switch (status) {
dudmuck 0:8f0d0ae0a077 297 case LORAMAC_EVENT_INFO_STATUS_RX_ERROR: ptr = "RX_ERROR"; break;
dudmuck 0:8f0d0ae0a077 298 case LORAMAC_EVENT_INFO_STATUS_OK: ptr = "OK"; break;
dudmuck 2:f2d9aa163652 299 case LORAMAC_EVENT_INFO_STATUS_ERROR_RX_MTYPE: ptr = "ERROR_RX_MTYPE"; break;
dudmuck 2:f2d9aa163652 300 case LORAMAC_EVENT_INFO_STATUS_ERROR_SEND: ptr = "ERROR_SEND"; break;
dudmuck 2:f2d9aa163652 301 case LORAMAC_EVENT_INFO_STATUS_ERROR_JOIN_ACCEPT: ptr = "ERROR_JOIN_ACCEPT"; break;
dudmuck 2:f2d9aa163652 302 case LORAMAC_EVENT_INFO_STATUS_ERROR_MLMEREQ: ptr = "ERROR_MLMEREQ"; break;
dudmuck 2:f2d9aa163652 303 case LORAMAC_EVENT_INFO_STATUS_ERROR_MCPSREQ: ptr = "ERROR_MCPSREQ"; break;
dudmuck 2:f2d9aa163652 304 //case LORAMAC_EVENT_INFO_STATUS_ERROR: ptr = "ERROR"; break;
dudmuck 2:f2d9aa163652 305
dudmuck 0:8f0d0ae0a077 306 case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT: ptr = "TX_TIMEOUT"; break;
dudmuck 0:8f0d0ae0a077 307 case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT: ptr = "RX_TIMEOUT"; break;
dudmuck 0:8f0d0ae0a077 308 case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL: ptr = "JOIN_FAIL"; break;
dudmuck 0:8f0d0ae0a077 309 case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED: ptr = "DOWNLINK_REPEATED"; break;
dudmuck 0:8f0d0ae0a077 310 case LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR: ptr = "TX_DR_PAYLOAD_SIZE_ERROR"; break;
dudmuck 0:8f0d0ae0a077 311 case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS: ptr = "DOWNLINK_TOO_MANY_FRAMES_LOSS"; break;
dudmuck 0:8f0d0ae0a077 312 case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL: ptr = "ADDRESS_FAIL"; break;
dudmuck 0:8f0d0ae0a077 313 case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL: ptr = "MIC_FAIL"; break;
dudmuck 0:8f0d0ae0a077 314 case LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED: ptr = "BEACON_LOCKED"; break;
dudmuck 0:8f0d0ae0a077 315 case LORAMAC_EVENT_INFO_STATUS_BEACON_LOST: ptr = "BEACON_LOST"; break;
dudmuck 0:8f0d0ae0a077 316 case LORAMAC_EVENT_INFO_STATUS_BEACON_NOT_FOUND: ptr = "BEACON_NOT_FOUND"; break;
dudmuck 16:915815632c1f 317 case LORAMAC_EVENT_INFO_STATUS_STOP: ptr = "STOP"; break;
dudmuck 0:8f0d0ae0a077 318 }
dudmuck 0:8f0d0ae0a077 319
dudmuck 0:8f0d0ae0a077 320 if (ptr != NULL)
dudmuck 0:8f0d0ae0a077 321 strcpy(dst, ptr);
dudmuck 0:8f0d0ae0a077 322 }
dudmuck 0:8f0d0ae0a077 323
dudmuck 0:8f0d0ae0a077 324 void
dudmuck 0:8f0d0ae0a077 325 LoRaMacStatus_to_string(LoRaMacStatus_t status, char* dst)
dudmuck 0:8f0d0ae0a077 326 {
dudmuck 0:8f0d0ae0a077 327 const char* ptr = NULL;
dudmuck 0:8f0d0ae0a077 328
dudmuck 0:8f0d0ae0a077 329 switch (status) {
dudmuck 0:8f0d0ae0a077 330 case LORAMAC_STATUS_OK: ptr = "OK"; break;
dudmuck 0:8f0d0ae0a077 331 case LORAMAC_STATUS_BUSY: ptr = "BUSY"; break;
dudmuck 0:8f0d0ae0a077 332 case LORAMAC_STATUS_SERVICE_UNKNOWN: ptr = "SERVICE_UNKNOWN"; break;
dudmuck 0:8f0d0ae0a077 333 case LORAMAC_STATUS_PARAMETER_INVALID: ptr = "PARAMETER_INVALID"; break;
dudmuck 0:8f0d0ae0a077 334 case LORAMAC_STATUS_FREQUENCY_INVALID: ptr = "FREQUENCY_INVALID"; break;
dudmuck 0:8f0d0ae0a077 335 case LORAMAC_STATUS_DATARATE_INVALID: ptr = "DATARATE_INVALID"; break;
dudmuck 0:8f0d0ae0a077 336 case LORAMAC_STATUS_FREQ_AND_DR_INVALID: ptr = "FREQ_AND_DR_INVALID"; break;
dudmuck 0:8f0d0ae0a077 337 case LORAMAC_STATUS_NO_NETWORK_JOINED: ptr = "NO_NETWORK_JOINED"; break;
dudmuck 0:8f0d0ae0a077 338 case LORAMAC_STATUS_LENGTH_ERROR: ptr = "LENGTH_ERROR"; break;
dudmuck 0:8f0d0ae0a077 339 case LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR: ptr = "MAC_CMD_LENGTH_ERROR"; break;
dudmuck 0:8f0d0ae0a077 340 case LORAMAC_STATUS_DEVICE_OFF: ptr = "DEVICE_OFF"; break;
dudmuck 0:8f0d0ae0a077 341 }
dudmuck 0:8f0d0ae0a077 342 if (ptr != NULL)
dudmuck 0:8f0d0ae0a077 343 strcpy(dst, ptr);
dudmuck 0:8f0d0ae0a077 344 }
dudmuck 0:8f0d0ae0a077 345
dudmuck 17:3215f12051f9 346 static void OnTxNextPacketTimerEvent( void );
dudmuck 5:c108560af4c3 347
dudmuck 5:c108560af4c3 348 /*!
dudmuck 0:8f0d0ae0a077 349 * \brief Prepares the payload of the frame
dudmuck 0:8f0d0ae0a077 350 *
dudmuck 0:8f0d0ae0a077 351 * \retval [0: frame could be send, 1: error]
dudmuck 0:8f0d0ae0a077 352 */
dudmuck 17:3215f12051f9 353 static bool SendFrame(uint8_t port)
dudmuck 0:8f0d0ae0a077 354 {
dudmuck 0:8f0d0ae0a077 355 McpsReq_t mcpsReq;
dudmuck 0:8f0d0ae0a077 356 LoRaMacTxInfo_t txInfo;
dudmuck 0:8f0d0ae0a077 357 LoRaMacStatus_t status;
dudmuck 0:8f0d0ae0a077 358 char str[64];
dudmuck 0:8f0d0ae0a077 359
dudmuck 0:8f0d0ae0a077 360 if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
dudmuck 0:8f0d0ae0a077 361 {
dudmuck 0:8f0d0ae0a077 362 // Send empty frame in order to flush MAC commands
dudmuck 0:8f0d0ae0a077 363 mcpsReq.Type = MCPS_UNCONFIRMED;
dudmuck 0:8f0d0ae0a077 364 mcpsReq.Req.Unconfirmed.fBuffer = NULL;
dudmuck 0:8f0d0ae0a077 365 mcpsReq.Req.Unconfirmed.fBufferSize = 0;
dudmuck 0:8f0d0ae0a077 366
dudmuck 0:8f0d0ae0a077 367 LoRaMacUplinkStatus.Acked = false;
dudmuck 0:8f0d0ae0a077 368 LoRaMacUplinkStatus.Port = 0;
dudmuck 0:8f0d0ae0a077 369 LoRaMacUplinkStatus.Buffer = NULL;
dudmuck 0:8f0d0ae0a077 370 LoRaMacUplinkStatus.BufferSize = 0;
dudmuck 0:8f0d0ae0a077 371 }
dudmuck 0:8f0d0ae0a077 372 else
dudmuck 0:8f0d0ae0a077 373 {
dudmuck 0:8f0d0ae0a077 374 LoRaMacUplinkStatus.Acked = false;
dudmuck 12:ed33c53afcaf 375 LoRaMacUplinkStatus.Port = port;
dudmuck 0:8f0d0ae0a077 376 LoRaMacUplinkStatus.Buffer = AppData;
dudmuck 0:8f0d0ae0a077 377 LoRaMacUplinkStatus.BufferSize = AppDataSize;
dudmuck 0:8f0d0ae0a077 378
dudmuck 0:8f0d0ae0a077 379 if( IsTxConfirmed == false )
dudmuck 0:8f0d0ae0a077 380 {
dudmuck 0:8f0d0ae0a077 381 mcpsReq.Type = MCPS_UNCONFIRMED;
dudmuck 12:ed33c53afcaf 382 mcpsReq.Req.Unconfirmed.fPort = port;
dudmuck 0:8f0d0ae0a077 383 mcpsReq.Req.Unconfirmed.fBuffer = AppData;
dudmuck 0:8f0d0ae0a077 384 mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize;
dudmuck 0:8f0d0ae0a077 385 }
dudmuck 0:8f0d0ae0a077 386 else
dudmuck 0:8f0d0ae0a077 387 {
dudmuck 0:8f0d0ae0a077 388 mcpsReq.Type = MCPS_CONFIRMED;
dudmuck 12:ed33c53afcaf 389 mcpsReq.Req.Confirmed.fPort = port;
dudmuck 0:8f0d0ae0a077 390 mcpsReq.Req.Confirmed.fBuffer = AppData;
dudmuck 0:8f0d0ae0a077 391 mcpsReq.Req.Confirmed.fBufferSize = AppDataSize;
dudmuck 0:8f0d0ae0a077 392 mcpsReq.Req.Confirmed.NbTrials = 8;
dudmuck 0:8f0d0ae0a077 393 }
dudmuck 0:8f0d0ae0a077 394 }
dudmuck 0:8f0d0ae0a077 395
dudmuck 0:8f0d0ae0a077 396 status = LoRaMacMcpsRequest( &mcpsReq );
dudmuck 0:8f0d0ae0a077 397 if( status == LORAMAC_STATUS_OK )
dudmuck 0:8f0d0ae0a077 398 {
dudmuck 0:8f0d0ae0a077 399 awaiting_mcps_indic = true;
Wayne Roberts 29:ad409c68c0a6 400 app_printf("send ok\r\n");
dudmuck 0:8f0d0ae0a077 401 return false;
dudmuck 0:8f0d0ae0a077 402 }
dudmuck 0:8f0d0ae0a077 403 LoRaMacStatus_to_string(status, str);
Wayne Roberts 29:ad409c68c0a6 404 app_printf("send failed:%s\r\n", str);
dudmuck 16:915815632c1f 405
dudmuck 21:500ff43d8424 406 if (status == LORAMAC_STATUS_NO_NETWORK_JOINED) {
dudmuck 21:500ff43d8424 407 join_retry = true;
dudmuck 26:8227a4edb216 408 #ifdef SENSORS
dudmuck 26:8227a4edb216 409 sensor_ticker.detach();
dudmuck 26:8227a4edb216 410 #endif
dudmuck 21:500ff43d8424 411 } else {
dudmuck 17:3215f12051f9 412 AppPort = port;
dudmuck 17:3215f12051f9 413 TxNextPacketTimeout.attach_us(&OnTxNextPacketTimerEvent, randr(1000000, 5000000) + 1000000);
dudmuck 22:999a7e7698a8 414 if (status == LORAMAC_STATUS_BUSY)
dudmuck 22:999a7e7698a8 415 send_at_beacon = true;
dudmuck 17:3215f12051f9 416 }
dudmuck 16:915815632c1f 417
dudmuck 0:8f0d0ae0a077 418 return true;
dudmuck 0:8f0d0ae0a077 419 }
dudmuck 0:8f0d0ae0a077 420
dudmuck 17:3215f12051f9 421 /*!
dudmuck 17:3215f12051f9 422 * \brief Function executed on TxNextPacket Timeout event
dudmuck 17:3215f12051f9 423 */
dudmuck 17:3215f12051f9 424 static void OnTxNextPacketTimerEvent( void )
dudmuck 17:3215f12051f9 425 {
dudmuck 17:3215f12051f9 426 MibRequestConfirm_t mibReq;
dudmuck 17:3215f12051f9 427 LoRaMacStatus_t status;
dudmuck 17:3215f12051f9 428
dudmuck 17:3215f12051f9 429 if (DeviceState == DEVICE_STATE_REJOIN) {
Wayne Roberts 29:ad409c68c0a6 430 app_printf("unjoin\r\n");
dudmuck 17:3215f12051f9 431 mibReq.Type = MIB_NETWORK_JOINED;
dudmuck 17:3215f12051f9 432 mibReq.Param.IsNetworkJoined = false;
dudmuck 26:8227a4edb216 433 #ifdef SENSORS
dudmuck 26:8227a4edb216 434 sensor_ticker.detach();
dudmuck 26:8227a4edb216 435 #endif
dudmuck 17:3215f12051f9 436 if (LoRaMacMibSetRequestConfirm( &mibReq ) != LORAMAC_STATUS_OK) {
dudmuck 17:3215f12051f9 437 TxNextPacketTimeout.attach_us(&OnTxNextPacketTimerEvent, 500000);
dudmuck 17:3215f12051f9 438 return;
dudmuck 17:3215f12051f9 439 }
dudmuck 17:3215f12051f9 440 }
dudmuck 17:3215f12051f9 441
dudmuck 17:3215f12051f9 442 mibReq.Type = MIB_NETWORK_JOINED;
dudmuck 17:3215f12051f9 443 status = LoRaMacMibGetRequestConfirm( &mibReq );
dudmuck 17:3215f12051f9 444
Wayne Roberts 29:ad409c68c0a6 445 app_printf("OnTxNextPacketTimerEvent() ");
dudmuck 17:3215f12051f9 446 if( status == LORAMAC_STATUS_OK )
dudmuck 17:3215f12051f9 447 {
dudmuck 17:3215f12051f9 448 if( mibReq.Param.IsNetworkJoined == true )
dudmuck 17:3215f12051f9 449 {
Wayne Roberts 29:ad409c68c0a6 450 app_printf("send");
dudmuck 18:9ac71c0eb70d 451 DeviceState = DEVICE_STATE_UPLINK;
dudmuck 17:3215f12051f9 452 }
dudmuck 17:3215f12051f9 453 else
dudmuck 17:3215f12051f9 454 {
Wayne Roberts 29:ad409c68c0a6 455 app_printf("join");
dudmuck 17:3215f12051f9 456 DeviceState = DEVICE_STATE_JOIN;
dudmuck 17:3215f12051f9 457 }
dudmuck 17:3215f12051f9 458 }
Wayne Roberts 29:ad409c68c0a6 459 app_printf("\r\n");
dudmuck 17:3215f12051f9 460 }
dudmuck 17:3215f12051f9 461
dudmuck 0:8f0d0ae0a077 462 void
dudmuck 0:8f0d0ae0a077 463 send_uplink()
dudmuck 0:8f0d0ae0a077 464 {
dudmuck 0:8f0d0ae0a077 465 AppDataSize = uplink_length;
dudmuck 18:9ac71c0eb70d 466 DeviceState = DEVICE_STATE_UPLINK;
dudmuck 0:8f0d0ae0a077 467 }
dudmuck 0:8f0d0ae0a077 468
dudmuck 0:8f0d0ae0a077 469 /*!
dudmuck 0:8f0d0ae0a077 470 * \brief MCPS-Confirm event function
dudmuck 0:8f0d0ae0a077 471 *
dudmuck 0:8f0d0ae0a077 472 * \param [IN] mcpsConfirm - Pointer to the confirm structure,
dudmuck 0:8f0d0ae0a077 473 * containing confirm attributes.
dudmuck 0:8f0d0ae0a077 474 */
dudmuck 0:8f0d0ae0a077 475 static void McpsConfirm( McpsConfirm_t *mcpsConfirm )
dudmuck 0:8f0d0ae0a077 476 {
dudmuck 2:f2d9aa163652 477 static uint8_t fail_count = 0;
dudmuck 0:8f0d0ae0a077 478 char str[64];
dudmuck 2:f2d9aa163652 479
Wayne Roberts 29:ad409c68c0a6 480 app_printf("McpsConfirm ");
dudmuck 0:8f0d0ae0a077 481 if( mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
dudmuck 0:8f0d0ae0a077 482 {
dudmuck 2:f2d9aa163652 483 fail_count = 0;
Wayne Roberts 29:ad409c68c0a6 484 app_printf("OK ");
dudmuck 0:8f0d0ae0a077 485 switch( mcpsConfirm->McpsRequest )
dudmuck 0:8f0d0ae0a077 486 {
dudmuck 0:8f0d0ae0a077 487 case MCPS_UNCONFIRMED:
dudmuck 0:8f0d0ae0a077 488 {
Wayne Roberts 29:ad409c68c0a6 489 app_printf("UNCONFIRMED");
dudmuck 0:8f0d0ae0a077 490 // Check Datarate
dudmuck 0:8f0d0ae0a077 491 // Check TxPower
dudmuck 0:8f0d0ae0a077 492 break;
dudmuck 0:8f0d0ae0a077 493 }
dudmuck 0:8f0d0ae0a077 494 case MCPS_CONFIRMED:
dudmuck 0:8f0d0ae0a077 495 {
Wayne Roberts 29:ad409c68c0a6 496 app_printf("CONFIRMED");
dudmuck 0:8f0d0ae0a077 497 // Check Datarate
dudmuck 0:8f0d0ae0a077 498 // Check TxPower
dudmuck 0:8f0d0ae0a077 499 // Check AckReceived
dudmuck 0:8f0d0ae0a077 500 // Check NbTrials
dudmuck 0:8f0d0ae0a077 501 LoRaMacUplinkStatus.Acked = mcpsConfirm->AckReceived;
dudmuck 0:8f0d0ae0a077 502 break;
dudmuck 0:8f0d0ae0a077 503 }
dudmuck 0:8f0d0ae0a077 504 case MCPS_PROPRIETARY:
dudmuck 0:8f0d0ae0a077 505 {
dudmuck 0:8f0d0ae0a077 506 break;
dudmuck 0:8f0d0ae0a077 507 }
dudmuck 0:8f0d0ae0a077 508 default:
dudmuck 0:8f0d0ae0a077 509 break;
dudmuck 0:8f0d0ae0a077 510 }
dudmuck 0:8f0d0ae0a077 511 //LoRaMacUplinkStatus.Datarate = mcpsConfirm->Datarate;
dudmuck 0:8f0d0ae0a077 512 LoRaMacUplinkStatus.UplinkCounter = mcpsConfirm->UpLinkCounter;
dudmuck 0:8f0d0ae0a077 513
dudmuck 0:8f0d0ae0a077 514 } else {
dudmuck 0:8f0d0ae0a077 515 LoRaMacEventInfoStatus_to_string(mcpsConfirm->Status, str);
Wayne Roberts 29:ad409c68c0a6 516 app_printf("%s ", str);
dudmuck 0:8f0d0ae0a077 517
dudmuck 0:8f0d0ae0a077 518 /* mcpsIndication may not come. last uplink done, send another uplink */
dudmuck 12:ed33c53afcaf 519 if (jumper_in.read()) { /* jumper installed: auto uplink */
dudmuck 17:3215f12051f9 520 TxNextPacketTimeout.attach_us(&send_uplink, 100000);
dudmuck 12:ed33c53afcaf 521 }
dudmuck 16:915815632c1f 522
dudmuck 2:f2d9aa163652 523 if (++fail_count > 10) {
dudmuck 2:f2d9aa163652 524 /* cause re-join */
dudmuck 2:f2d9aa163652 525 MibRequestConfirm_t mibReq;
dudmuck 2:f2d9aa163652 526 mibReq.Type = MIB_NETWORK_JOINED;
dudmuck 2:f2d9aa163652 527 mibReq.Param.IsNetworkJoined = false;
dudmuck 2:f2d9aa163652 528 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 16:915815632c1f 529 fail_count = 0;
dudmuck 26:8227a4edb216 530 #ifdef SENSORS
dudmuck 26:8227a4edb216 531 sensor_ticker.detach();
dudmuck 26:8227a4edb216 532 #endif
dudmuck 2:f2d9aa163652 533 }
dudmuck 0:8f0d0ae0a077 534 }
dudmuck 0:8f0d0ae0a077 535
Wayne Roberts 29:ad409c68c0a6 536 app_printf("\r\n");
dudmuck 0:8f0d0ae0a077 537 }
dudmuck 0:8f0d0ae0a077 538
dudmuck 0:8f0d0ae0a077 539 /*!
dudmuck 0:8f0d0ae0a077 540 * \brief MCPS-Indication event function
dudmuck 0:8f0d0ae0a077 541 *
dudmuck 0:8f0d0ae0a077 542 * \param [IN] mcpsIndication - Pointer to the indication structure,
dudmuck 0:8f0d0ae0a077 543 * containing indication attributes.
dudmuck 0:8f0d0ae0a077 544 */
dudmuck 0:8f0d0ae0a077 545 static void McpsIndication( McpsIndication_t *mcpsIndication )
dudmuck 0:8f0d0ae0a077 546 {
dudmuck 11:4c337f5bbe4c 547 char str[64];
dudmuck 22:999a7e7698a8 548 MibRequestConfirm_t mibReq;
dudmuck 22:999a7e7698a8 549
Wayne Roberts 29:ad409c68c0a6 550 app_printf("McpsIndication ");
dudmuck 0:8f0d0ae0a077 551
dudmuck 0:8f0d0ae0a077 552 /* last uplink done, send another uplink */
dudmuck 16:915815632c1f 553 if (jumper_in.read() && mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_STOP) {
dudmuck 16:915815632c1f 554 /* jumper installed: auto uplink */
dudmuck 17:3215f12051f9 555 TxNextPacketTimeout.attach_us(&send_uplink, 100000);
dudmuck 12:ed33c53afcaf 556 }
dudmuck 0:8f0d0ae0a077 557
dudmuck 0:8f0d0ae0a077 558 if( mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
dudmuck 0:8f0d0ae0a077 559 {
dudmuck 11:4c337f5bbe4c 560 LoRaMacEventInfoStatus_to_string(mcpsIndication->Status, str);
Wayne Roberts 29:ad409c68c0a6 561 app_printf("%s\r\n", str);
dudmuck 0:8f0d0ae0a077 562 return;
dudmuck 0:8f0d0ae0a077 563 }
dudmuck 0:8f0d0ae0a077 564
dudmuck 0:8f0d0ae0a077 565 awaiting_mcps_indic = false;
dudmuck 0:8f0d0ae0a077 566
dudmuck 0:8f0d0ae0a077 567 switch( mcpsIndication->McpsIndication )
dudmuck 0:8f0d0ae0a077 568 {
dudmuck 5:c108560af4c3 569 /* this refers to the downlink from gateway, not the uplink that was sent to it */
dudmuck 0:8f0d0ae0a077 570 case MCPS_UNCONFIRMED:
dudmuck 0:8f0d0ae0a077 571 {
Wayne Roberts 29:ad409c68c0a6 572 app_printf("UNCONFIRMED ");
dudmuck 0:8f0d0ae0a077 573 break;
dudmuck 0:8f0d0ae0a077 574 }
dudmuck 0:8f0d0ae0a077 575 case MCPS_CONFIRMED:
dudmuck 0:8f0d0ae0a077 576 {
dudmuck 5:c108560af4c3 577 /* downlink has requested Ack */
Wayne Roberts 29:ad409c68c0a6 578 app_printf("CONFIRMED ");
dudmuck 0:8f0d0ae0a077 579 break;
dudmuck 0:8f0d0ae0a077 580 }
dudmuck 0:8f0d0ae0a077 581 case MCPS_PROPRIETARY:
dudmuck 0:8f0d0ae0a077 582 {
dudmuck 0:8f0d0ae0a077 583 break;
dudmuck 0:8f0d0ae0a077 584 }
dudmuck 0:8f0d0ae0a077 585 case MCPS_MULTICAST:
dudmuck 0:8f0d0ae0a077 586 {
Wayne Roberts 29:ad409c68c0a6 587 app_printf("MCPS_MULTICAST ");
dudmuck 12:ed33c53afcaf 588 /*if (mcpsIndication->RxData) {
dudmuck 12:ed33c53afcaf 589 }*/
dudmuck 0:8f0d0ae0a077 590 break;
dudmuck 0:8f0d0ae0a077 591 }
dudmuck 0:8f0d0ae0a077 592 default:
dudmuck 0:8f0d0ae0a077 593 break;
dudmuck 0:8f0d0ae0a077 594 }
dudmuck 0:8f0d0ae0a077 595
dudmuck 0:8f0d0ae0a077 596 // Check Multicast
dudmuck 0:8f0d0ae0a077 597 // Check Port
dudmuck 0:8f0d0ae0a077 598 // Check Datarate
dudmuck 0:8f0d0ae0a077 599 // Check FramePending
dudmuck 0:8f0d0ae0a077 600 // Check Buffer
dudmuck 0:8f0d0ae0a077 601 // Check BufferSize
dudmuck 0:8f0d0ae0a077 602 // Check Rssi
dudmuck 0:8f0d0ae0a077 603 // Check Snr
dudmuck 0:8f0d0ae0a077 604 // Check RxSlot
dudmuck 0:8f0d0ae0a077 605 LoRaMacDownlinkStatus.Rssi = mcpsIndication->Rssi;
dudmuck 0:8f0d0ae0a077 606 if( mcpsIndication->Snr & 0x80 ) // The SNR sign bit is 1
dudmuck 0:8f0d0ae0a077 607 {
dudmuck 0:8f0d0ae0a077 608 // Invert and divide by 4
dudmuck 0:8f0d0ae0a077 609 LoRaMacDownlinkStatus.Snr = ( ( ~mcpsIndication->Snr + 1 ) & 0xFF ) >> 2;
dudmuck 0:8f0d0ae0a077 610 LoRaMacDownlinkStatus.Snr = -LoRaMacDownlinkStatus.Snr;
dudmuck 0:8f0d0ae0a077 611 }
dudmuck 0:8f0d0ae0a077 612 else
dudmuck 0:8f0d0ae0a077 613 {
dudmuck 0:8f0d0ae0a077 614 // Divide by 4
dudmuck 0:8f0d0ae0a077 615 LoRaMacDownlinkStatus.Snr = ( mcpsIndication->Snr & 0xFF ) >> 2;
dudmuck 0:8f0d0ae0a077 616 }
dudmuck 0:8f0d0ae0a077 617 LoRaMacDownlinkStatus.DownlinkCounter++;
dudmuck 0:8f0d0ae0a077 618 LoRaMacDownlinkStatus.RxData = mcpsIndication->RxData;
dudmuck 0:8f0d0ae0a077 619 LoRaMacDownlinkStatus.Port = mcpsIndication->Port;
dudmuck 0:8f0d0ae0a077 620 LoRaMacDownlinkStatus.Buffer = mcpsIndication->Buffer;
dudmuck 0:8f0d0ae0a077 621 LoRaMacDownlinkStatus.BufferSize = mcpsIndication->BufferSize;
dudmuck 0:8f0d0ae0a077 622
dudmuck 0:8f0d0ae0a077 623 if( mcpsIndication->RxData == true )
dudmuck 0:8f0d0ae0a077 624 {
dudmuck 0:8f0d0ae0a077 625 int i;
Wayne Roberts 29:ad409c68c0a6 626 app_printf("RxData %u ", mcpsIndication->BufferSize);
dudmuck 0:8f0d0ae0a077 627 for (i = 0; i < mcpsIndication->BufferSize; i++) {
Wayne Roberts 29:ad409c68c0a6 628 app_printf("%02x ", mcpsIndication->Buffer[i]);
dudmuck 0:8f0d0ae0a077 629 }
Wayne Roberts 29:ad409c68c0a6 630 app_printf("\r\n");
dudmuck 12:ed33c53afcaf 631
dudmuck 12:ed33c53afcaf 632 switch (mcpsIndication->Buffer[0]) {
dudmuck 12:ed33c53afcaf 633 default:
dudmuck 12:ed33c53afcaf 634 case CMD_NONE: break;
dudmuck 23:a862b5601663 635 #if defined (ENABLE_RGB)
dudmuck 12:ed33c53afcaf 636 case CMD_LED_RGB:
dudmuck 12:ed33c53afcaf 637 rgb.setColorRGB(0,
dudmuck 12:ed33c53afcaf 638 mcpsIndication->Buffer[1], // R
dudmuck 12:ed33c53afcaf 639 mcpsIndication->Buffer[2], // G
dudmuck 12:ed33c53afcaf 640 mcpsIndication->Buffer[3] // B
dudmuck 12:ed33c53afcaf 641 );
Wayne Roberts 29:ad409c68c0a6 642 app_printf("rgb %u %u %u\r\n",
dudmuck 16:915815632c1f 643 mcpsIndication->Buffer[1],
dudmuck 16:915815632c1f 644 mcpsIndication->Buffer[2],
dudmuck 16:915815632c1f 645 mcpsIndication->Buffer[3]
dudmuck 16:915815632c1f 646 );
dudmuck 12:ed33c53afcaf 647 break;
dudmuck 23:a862b5601663 648 #endif /* ENABLE_RGB */
dudmuck 23:a862b5601663 649 #if defined(SENSORS)
dudmuck 12:ed33c53afcaf 650 case CMD_GPIO_OUT:
dudmuck 12:ed33c53afcaf 651 pc6_out = mcpsIndication->Buffer[1];
Wayne Roberts 29:ad409c68c0a6 652 app_printf("gpo %d\r\n", mcpsIndication->Buffer[1]);
dudmuck 16:915815632c1f 653 break;
dudmuck 18:9ac71c0eb70d 654 case CMD_PWM:
dudmuck 18:9ac71c0eb70d 655 pwm.period(1.0 / mcpsIndication->Buffer[1]);
dudmuck 18:9ac71c0eb70d 656 pwm.write(mcpsIndication->Buffer[2] / 255.0);
Wayne Roberts 29:ad409c68c0a6 657 app_printf("pwm %u %u\r\n", mcpsIndication->Buffer[1], mcpsIndication->Buffer[2]);
dudmuck 22:999a7e7698a8 658 break;
dudmuck 23:a862b5601663 659 #endif /* SENSORS */
dudmuck 22:999a7e7698a8 660 case CMD_TX_POWER:
Wayne Roberts 29:ad409c68c0a6 661 app_printf("txp %u\r\n", mcpsIndication->Buffer[1]);
dudmuck 22:999a7e7698a8 662 mibReq.Type = MIB_CHANNELS_TX_POWER;
dudmuck 22:999a7e7698a8 663 mibReq.Param.ChannelsTxPower = mcpsIndication->Buffer[1];
dudmuck 22:999a7e7698a8 664 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 12:ed33c53afcaf 665 break;
dudmuck 12:ed33c53afcaf 666 } // ..switch (mcpsIndication->Buffer[3])
dudmuck 0:8f0d0ae0a077 667
dudmuck 0:8f0d0ae0a077 668 switch( mcpsIndication->Port )
dudmuck 0:8f0d0ae0a077 669 {
dudmuck 0:8f0d0ae0a077 670 case 1: // The application LED can be controlled on port 1 or 2
dudmuck 0:8f0d0ae0a077 671 case 2:
dudmuck 0:8f0d0ae0a077 672 if( mcpsIndication->BufferSize == 1 )
dudmuck 0:8f0d0ae0a077 673 {
dudmuck 0:8f0d0ae0a077 674 AppLedStateOn = mcpsIndication->Buffer[0] & 0x01;
dudmuck 0:8f0d0ae0a077 675 //Led3StateChanged = true;
dudmuck 0:8f0d0ae0a077 676 }
dudmuck 0:8f0d0ae0a077 677 break;
dudmuck 0:8f0d0ae0a077 678 default:
dudmuck 0:8f0d0ae0a077 679 break;
dudmuck 0:8f0d0ae0a077 680 }
dudmuck 0:8f0d0ae0a077 681 }
dudmuck 16:915815632c1f 682
dudmuck 16:915815632c1f 683 if (mcpsIndication->Status == LORAMAC_EVENT_INFO_STATUS_STOP) {
Wayne Roberts 29:ad409c68c0a6 684 app_printf(" STOP-SCC");
dudmuck 17:3215f12051f9 685 TxNextPacketTimeout.detach();
dudmuck 16:915815632c1f 686 DeviceState = DEVICE_STATE_SLEEP;
dudmuck 16:915815632c1f 687 }
dudmuck 17:3215f12051f9 688
Wayne Roberts 29:ad409c68c0a6 689 app_printf("\r\n");
dudmuck 0:8f0d0ae0a077 690 }
dudmuck 0:8f0d0ae0a077 691
dudmuck 0:8f0d0ae0a077 692 /*!
dudmuck 0:8f0d0ae0a077 693 * \brief MLME-Confirm event function
dudmuck 0:8f0d0ae0a077 694 *
dudmuck 0:8f0d0ae0a077 695 * \param [IN] mlmeConfirm - Pointer to the confirm structure,
dudmuck 0:8f0d0ae0a077 696 * containing confirm attributes.
dudmuck 0:8f0d0ae0a077 697 */
dudmuck 0:8f0d0ae0a077 698 static void MlmeConfirm( MlmeConfirm_t *mlmeConfirm )
dudmuck 0:8f0d0ae0a077 699 {
dudmuck 16:915815632c1f 700 char str[64];
dudmuck 16:915815632c1f 701 LoRaMacEventInfoStatus_to_string(mlmeConfirm->Status, str);
Wayne Roberts 29:ad409c68c0a6 702 app_printf("MlmeConfirm %s ", str);
dudmuck 16:915815632c1f 703
dudmuck 0:8f0d0ae0a077 704 switch( mlmeConfirm->MlmeRequest )
dudmuck 0:8f0d0ae0a077 705 {
dudmuck 0:8f0d0ae0a077 706 case MLME_JOIN:
dudmuck 0:8f0d0ae0a077 707 {
Wayne Roberts 29:ad409c68c0a6 708 app_printf("MLME_JOIN ");
dudmuck 0:8f0d0ae0a077 709 if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
dudmuck 0:8f0d0ae0a077 710 {
dudmuck 0:8f0d0ae0a077 711 // Status is OK, node has joined the network
dudmuck 0:8f0d0ae0a077 712 DeviceState = DEVICE_STATE_SLEEP;
dudmuck 26:8227a4edb216 713 #ifdef SENSORS
dudmuck 28:36be305a5e5e 714 sensor_ticker.attach(&sensor_poll, POLL_RATE);
dudmuck 26:8227a4edb216 715 sensor_in_idx = 0;
dudmuck 26:8227a4edb216 716 sensor_out_idx = 0;
dudmuck 27:c8b432b2a4a8 717 sample_seqnum = 0;
dudmuck 26:8227a4edb216 718 #endif
dudmuck 2:f2d9aa163652 719 missed_count = 0;
dudmuck 16:915815632c1f 720 if (jumper_in.read()) /* jumper installed: auto uplink */
dudmuck 17:3215f12051f9 721 TxNextPacketTimeout.attach_us(&send_uplink, 100000);
dudmuck 0:8f0d0ae0a077 722 }
dudmuck 0:8f0d0ae0a077 723 else
dudmuck 0:8f0d0ae0a077 724 {
dudmuck 0:8f0d0ae0a077 725 // Join was not successful. Try to join again
dudmuck 0:8f0d0ae0a077 726 DeviceState = DEVICE_STATE_JOIN;
dudmuck 0:8f0d0ae0a077 727 }
dudmuck 0:8f0d0ae0a077 728 break;
dudmuck 0:8f0d0ae0a077 729 }
dudmuck 0:8f0d0ae0a077 730 case MLME_LINK_CHECK:
dudmuck 0:8f0d0ae0a077 731 {
Wayne Roberts 29:ad409c68c0a6 732 app_printf("LINK_CHECK");
dudmuck 0:8f0d0ae0a077 733 if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
dudmuck 0:8f0d0ae0a077 734 {
dudmuck 0:8f0d0ae0a077 735 // Check DemodMargin
dudmuck 0:8f0d0ae0a077 736 //mlmeConfirm->DemodMargin;
dudmuck 0:8f0d0ae0a077 737 // Check NbGateways
dudmuck 0:8f0d0ae0a077 738 //mlmeConfirm->NbGateways;
dudmuck 0:8f0d0ae0a077 739 }
dudmuck 0:8f0d0ae0a077 740 break;
dudmuck 0:8f0d0ae0a077 741 }
dudmuck 0:8f0d0ae0a077 742 default:
dudmuck 0:8f0d0ae0a077 743 break;
dudmuck 0:8f0d0ae0a077 744 }
dudmuck 17:3215f12051f9 745
Wayne Roberts 29:ad409c68c0a6 746 app_printf("\r\n");
dudmuck 0:8f0d0ae0a077 747 }
dudmuck 0:8f0d0ae0a077 748
dudmuck 0:8f0d0ae0a077 749
dudmuck 0:8f0d0ae0a077 750 static void MlmeIndication( MlmeIndication_t *MlmeIndication )
dudmuck 0:8f0d0ae0a077 751 {
dudmuck 0:8f0d0ae0a077 752 char str[64];
dudmuck 0:8f0d0ae0a077 753
Wayne Roberts 29:ad409c68c0a6 754 app_printf("MlmeIndication ");
dudmuck 0:8f0d0ae0a077 755 switch( MlmeIndication->MlmeIndication )
dudmuck 0:8f0d0ae0a077 756 {
dudmuck 0:8f0d0ae0a077 757 case MLME_BEACON:
dudmuck 0:8f0d0ae0a077 758 {
Wayne Roberts 29:ad409c68c0a6 759 app_printf("BEACON ", missed_count);
Wayne Roberts 29:ad409c68c0a6 760 if (missed_count)
Wayne Roberts 29:ad409c68c0a6 761 app_printf("missed:%u ", missed_count);
Wayne Roberts 29:ad409c68c0a6 762
dudmuck 0:8f0d0ae0a077 763 LoRaMacEventInfoStatus_to_string(MlmeIndication->Status, str);
Wayne Roberts 29:ad409c68c0a6 764 app_printf("%s ", str);
dudmuck 16:915815632c1f 765
dudmuck 0:8f0d0ae0a077 766 if (send_at_beacon) {
dudmuck 17:3215f12051f9 767 TxNextPacketTimeout.attach_us(&send_uplink, 100000);
dudmuck 0:8f0d0ae0a077 768 send_at_beacon = false;
dudmuck 0:8f0d0ae0a077 769 }
dudmuck 16:915815632c1f 770
dudmuck 28:36be305a5e5e 771 if (LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED == MlmeIndication->Status) {
dudmuck 2:f2d9aa163652 772 missed_count = 0;
dudmuck 28:36be305a5e5e 773 #if defined(ENABLE_RGB)
dudmuck 28:36be305a5e5e 774 rgb.setColorRGB(0, 0, 0, 0); // off
dudmuck 28:36be305a5e5e 775 #endif /* ENABLE_RGB */
dudmuck 28:36be305a5e5e 776 } else {
dudmuck 28:36be305a5e5e 777 #if defined(ENABLE_RGB)
dudmuck 28:36be305a5e5e 778 rgb.setColorRGB(0, 255, 64, 0); // orange
dudmuck 28:36be305a5e5e 779 #endif /* ENABLE_RGB */
dudmuck 16:915815632c1f 780 if (++missed_count > 4) {
dudmuck 16:915815632c1f 781 /* cause re-join */
dudmuck 16:915815632c1f 782 LoRaMacStatus_t status;
dudmuck 16:915815632c1f 783 MibRequestConfirm_t mibReq;
dudmuck 26:8227a4edb216 784 #ifdef SENSORS
dudmuck 26:8227a4edb216 785 sensor_ticker.detach();
dudmuck 26:8227a4edb216 786 #endif
dudmuck 16:915815632c1f 787 mibReq.Type = MIB_NETWORK_JOINED;
dudmuck 16:915815632c1f 788 mibReq.Param.IsNetworkJoined = false;
dudmuck 16:915815632c1f 789 status = LoRaMacMibSetRequestConfirm(&mibReq);
dudmuck 16:915815632c1f 790 if (status != LORAMAC_STATUS_OK)
dudmuck 16:915815632c1f 791 DeviceState = DEVICE_STATE_REJOIN;
dudmuck 16:915815632c1f 792
dudmuck 16:915815632c1f 793 LoRaMacStatus_to_string(status, str);
Wayne Roberts 29:ad409c68c0a6 794 app_printf("app-rejoin %s\r\n", str);
dudmuck 17:3215f12051f9 795 TxNextPacketTimeout.attach_us(&OnTxNextPacketTimerEvent, randr(1000000, 5000000) + 1000000);
dudmuck 16:915815632c1f 796 }
dudmuck 2:f2d9aa163652 797 }
dudmuck 0:8f0d0ae0a077 798 break;
dudmuck 0:8f0d0ae0a077 799
dudmuck 0:8f0d0ae0a077 800 }
dudmuck 10:00997daeb0c0 801 case MLME_TXDONE:
Wayne Roberts 29:ad409c68c0a6 802 app_printf("MLME_TXDONE ");
dudmuck 10:00997daeb0c0 803 break;
dudmuck 0:8f0d0ae0a077 804 default:
Wayne Roberts 29:ad409c68c0a6 805 app_printf("<%d> ", MlmeIndication->MlmeIndication);
dudmuck 0:8f0d0ae0a077 806 break;
dudmuck 0:8f0d0ae0a077 807 }
dudmuck 0:8f0d0ae0a077 808
Wayne Roberts 29:ad409c68c0a6 809 app_printf("\r\n");
dudmuck 0:8f0d0ae0a077 810 }
dudmuck 0:8f0d0ae0a077 811
dudmuck 0:8f0d0ae0a077 812 void
dudmuck 0:8f0d0ae0a077 813 send_pcbuf_uplink()
dudmuck 0:8f0d0ae0a077 814 {
dudmuck 0:8f0d0ae0a077 815 bool ret;
dudmuck 0:8f0d0ae0a077 816 memcpy(AppData, pcbuf, pcbuf_len);
dudmuck 0:8f0d0ae0a077 817 AppDataSize = pcbuf_len;
dudmuck 0:8f0d0ae0a077 818
dudmuck 12:ed33c53afcaf 819 ret = SendFrame(TEXT_PORT);
Wayne Roberts 29:ad409c68c0a6 820 app_printf("%d = SendFrame()\r\n", ret);
dudmuck 0:8f0d0ae0a077 821 }
dudmuck 0:8f0d0ae0a077 822
dudmuck 10:00997daeb0c0 823
dudmuck 0:8f0d0ae0a077 824 void cmd_status(uint8_t idx)
dudmuck 0:8f0d0ae0a077 825 {
dudmuck 2:f2d9aa163652 826 MibRequestConfirm_t mibReq;
dudmuck 2:f2d9aa163652 827
Wayne Roberts 29:ad409c68c0a6 828 app_printf("DevEUI ");
dudmuck 2:f2d9aa163652 829 for (int i = 0; i < 8; i++)
Wayne Roberts 29:ad409c68c0a6 830 app_printf("%02x ", DevEui[i]);
dudmuck 2:f2d9aa163652 831 mibReq.Type = MIB_DEV_ADDR;
dudmuck 2:f2d9aa163652 832 LoRaMacMibGetRequestConfirm( &mibReq );
Wayne Roberts 29:ad409c68c0a6 833 app_printf(", DevAddr:%x\r\n", mibReq.Param.DevAddr);
dudmuck 2:f2d9aa163652 834
dudmuck 23:a862b5601663 835 #if defined(SENSORS)
dudmuck 23:a862b5601663 836 #ifdef TYPE_ABZ
Wayne Roberts 29:ad409c68c0a6 837 app_printf("a0:%u a2:%u\r\n", a0.read_u16(), a2.read_u16());
dudmuck 23:a862b5601663 838 #else
Wayne Roberts 29:ad409c68c0a6 839 app_printf("a1:%u a3:%u\r\n", a1.read_u16(), a3.read_u16());
dudmuck 23:a862b5601663 840 #endif
Wayne Roberts 29:ad409c68c0a6 841 app_printf("button:%d ", user_button.read());
dudmuck 10:00997daeb0c0 842 #endif
Wayne Roberts 29:ad409c68c0a6 843 app_printf("DEVICE_STATE_");
dudmuck 17:3215f12051f9 844 switch (DeviceState) {
dudmuck 17:3215f12051f9 845 case DEVICE_STATE_JOIN: printf("JOIN"); break;
dudmuck 17:3215f12051f9 846 case DEVICE_STATE_CYCLE: printf("CYCLE"); break;
dudmuck 17:3215f12051f9 847 case DEVICE_STATE_SLEEP: printf("SLEEP"); break;
dudmuck 17:3215f12051f9 848 case DEVICE_STATE_REJOIN: printf("REJOIN"); break;
dudmuck 18:9ac71c0eb70d 849 case DEVICE_STATE_INIT: printf("INIT"); break;
dudmuck 18:9ac71c0eb70d 850 case DEVICE_STATE_UPLINK: printf("UPLINK"); break;
dudmuck 17:3215f12051f9 851 }
Wayne Roberts 29:ad409c68c0a6 852 app_printf(" send_at_beacon:%d\r\n", send_at_beacon);
Wayne Roberts 29:ad409c68c0a6 853 app_printf("awaiting_mcps_indic:%d\r\n", awaiting_mcps_indic);
dudmuck 12:ed33c53afcaf 854
dudmuck 0:8f0d0ae0a077 855 loramac_print_status();
dudmuck 10:00997daeb0c0 856
dudmuck 0:8f0d0ae0a077 857 }
dudmuck 0:8f0d0ae0a077 858
dudmuck 0:8f0d0ae0a077 859 void cmd_uplink_length(uint8_t idx)
dudmuck 0:8f0d0ae0a077 860 {
dudmuck 0:8f0d0ae0a077 861 if (pcbuf[idx] >= '0' && pcbuf[idx] <= '9') {
dudmuck 0:8f0d0ae0a077 862 sscanf(pcbuf+idx, "%u", &uplink_length);
dudmuck 0:8f0d0ae0a077 863 }
Wayne Roberts 29:ad409c68c0a6 864 app_printf("uplink_length:%u\r\n", uplink_length);
dudmuck 0:8f0d0ae0a077 865 }
dudmuck 0:8f0d0ae0a077 866
dudmuck 23:a862b5601663 867 #if defined(ENABLE_RGB)
dudmuck 12:ed33c53afcaf 868 void cmd_rgb(uint8_t idx)
dudmuck 10:00997daeb0c0 869 {
dudmuck 12:ed33c53afcaf 870 int r, g, b;
dudmuck 12:ed33c53afcaf 871 sscanf(pcbuf+idx, "%d %d %d", &r, &g, &b);
dudmuck 12:ed33c53afcaf 872 rgb.setColorRGB(0, r, g, b);
Wayne Roberts 29:ad409c68c0a6 873 app_printf("\r\nrgb: %d %d %d\r\n", r, g, b);
dudmuck 16:915815632c1f 874 }
dudmuck 23:a862b5601663 875 #endif /* ENABLE_RGB */
dudmuck 16:915815632c1f 876
dudmuck 23:a862b5601663 877 #if defined(SENSORS)
dudmuck 18:9ac71c0eb70d 878 void cmd_pwm(uint8_t idx)
dudmuck 16:915815632c1f 879 {
dudmuck 18:9ac71c0eb70d 880 float period, duty;
dudmuck 18:9ac71c0eb70d 881 unsigned p, d;
dudmuck 18:9ac71c0eb70d 882
dudmuck 18:9ac71c0eb70d 883 if (sscanf(pcbuf+idx, "%u %u", &p, &d) == 2) {
dudmuck 18:9ac71c0eb70d 884 period = 1.0 / p;
dudmuck 18:9ac71c0eb70d 885 duty = d / 255.0;
dudmuck 18:9ac71c0eb70d 886 pwm.period(period);
dudmuck 18:9ac71c0eb70d 887 pwm.write(duty);
dudmuck 18:9ac71c0eb70d 888 printf("pwm period:%f, duty:%f\r\n", period, duty);
dudmuck 18:9ac71c0eb70d 889 } else
dudmuck 18:9ac71c0eb70d 890 printf("pwm parse fail\r\n");
dudmuck 16:915815632c1f 891 }
dudmuck 16:915815632c1f 892
dudmuck 10:00997daeb0c0 893 #endif /* SENSORS */
dudmuck 10:00997daeb0c0 894
dudmuck 15:9023bf4cf168 895 void cmd_ChannelsTxPower(uint8_t idx)
dudmuck 15:9023bf4cf168 896 {
dudmuck 15:9023bf4cf168 897 MibRequestConfirm_t mibReq;
dudmuck 15:9023bf4cf168 898 unsigned int i;
dudmuck 15:9023bf4cf168 899
dudmuck 15:9023bf4cf168 900 if (pcbuf[idx] >= '0' && pcbuf[idx] <= '9') {
dudmuck 15:9023bf4cf168 901 sscanf(pcbuf+idx, "%u", &i);
dudmuck 15:9023bf4cf168 902 mibReq.Type = MIB_CHANNELS_TX_POWER;
dudmuck 15:9023bf4cf168 903 mibReq.Param.ChannelsTxPower = i;
dudmuck 15:9023bf4cf168 904 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 15:9023bf4cf168 905 }
dudmuck 15:9023bf4cf168 906
dudmuck 15:9023bf4cf168 907 mibReq.Type = MIB_CHANNELS_TX_POWER;
dudmuck 15:9023bf4cf168 908 LoRaMacMibGetRequestConfirm( &mibReq );
Wayne Roberts 29:ad409c68c0a6 909 app_printf("ChannelsTxPower:%u\r\n", mibReq.Param.ChannelsTxPower);
dudmuck 15:9023bf4cf168 910 }
dudmuck 15:9023bf4cf168 911
dudmuck 0:8f0d0ae0a077 912 typedef struct {
dudmuck 0:8f0d0ae0a077 913 const char* const cmd;
dudmuck 0:8f0d0ae0a077 914 void (*handler)(uint8_t args_at);
dudmuck 0:8f0d0ae0a077 915 const char* const arg_descr;
dudmuck 0:8f0d0ae0a077 916 const char* const description;
dudmuck 0:8f0d0ae0a077 917 } menu_item_t;
dudmuck 0:8f0d0ae0a077 918
dudmuck 0:8f0d0ae0a077 919 void cmd_help(uint8_t args_at);
dudmuck 0:8f0d0ae0a077 920
dudmuck 0:8f0d0ae0a077 921 const menu_item_t menu_items[] =
dudmuck 0:8f0d0ae0a077 922 { /* after first character, command names must be [A-Za-z] */
dudmuck 0:8f0d0ae0a077 923 { "?", cmd_help, "","show available commands"},
dudmuck 0:8f0d0ae0a077 924 { ".", cmd_status, "","print status"},
dudmuck 10:00997daeb0c0 925 { "ul", cmd_uplink_length, "%u","set uplink payload length"},
dudmuck 15:9023bf4cf168 926 { "ctxp", cmd_ChannelsTxPower, "%u","get/set ChannelsTxPower"},
dudmuck 23:a862b5601663 927 #if defined(ENABLE_RGB)
dudmuck 18:9ac71c0eb70d 928 { "rgb", cmd_rgb, "%d %d %d", "set led R G B"},
dudmuck 23:a862b5601663 929 #endif
dudmuck 23:a862b5601663 930 #if defined(SENSORS)
dudmuck 18:9ac71c0eb70d 931 { "p", cmd_pwm, "%u %u", "set pwm period, duty"},
dudmuck 23:a862b5601663 932 #endif /* SENSORS */
dudmuck 0:8f0d0ae0a077 933 { NULL, NULL, NULL, NULL }
dudmuck 0:8f0d0ae0a077 934 };
dudmuck 0:8f0d0ae0a077 935
dudmuck 0:8f0d0ae0a077 936 void cmd_help(uint8_t args_at)
dudmuck 0:8f0d0ae0a077 937 {
dudmuck 0:8f0d0ae0a077 938 int i;
dudmuck 0:8f0d0ae0a077 939
dudmuck 0:8f0d0ae0a077 940 for (i = 0; menu_items[i].cmd != NULL ; i++) {
Wayne Roberts 29:ad409c68c0a6 941 app_printf("%s%s\t%s\r\n", menu_items[i].cmd, menu_items[i].arg_descr, menu_items[i].description);
dudmuck 0:8f0d0ae0a077 942 }
dudmuck 0:8f0d0ae0a077 943
dudmuck 0:8f0d0ae0a077 944 }
dudmuck 0:8f0d0ae0a077 945
dudmuck 0:8f0d0ae0a077 946 void
dudmuck 0:8f0d0ae0a077 947 console()
dudmuck 0:8f0d0ae0a077 948 {
dudmuck 0:8f0d0ae0a077 949 bool parsed;
dudmuck 0:8f0d0ae0a077 950 int i;
dudmuck 0:8f0d0ae0a077 951 uint8_t user_cmd_len;
dudmuck 0:8f0d0ae0a077 952
dudmuck 0:8f0d0ae0a077 953 if (pcbuf_len < 0) { // ctrl-C
dudmuck 0:8f0d0ae0a077 954 return;
dudmuck 0:8f0d0ae0a077 955 }
dudmuck 0:8f0d0ae0a077 956 if (pcbuf_len == 0)
dudmuck 0:8f0d0ae0a077 957 return;
dudmuck 0:8f0d0ae0a077 958
Wayne Roberts 29:ad409c68c0a6 959 app_printf("\r\n");
dudmuck 0:8f0d0ae0a077 960
dudmuck 0:8f0d0ae0a077 961 /* get end of user-entered command */
dudmuck 0:8f0d0ae0a077 962 user_cmd_len = 1; // first character can be any character
dudmuck 0:8f0d0ae0a077 963 for (i = 1; i <= pcbuf_len; i++) {
dudmuck 0:8f0d0ae0a077 964 if (pcbuf[i] < 'A' || (pcbuf[i] > 'Z' && pcbuf[i] < 'a') || pcbuf[i] > 'z') {
dudmuck 0:8f0d0ae0a077 965 user_cmd_len = i;
dudmuck 0:8f0d0ae0a077 966 break;
dudmuck 0:8f0d0ae0a077 967 }
dudmuck 0:8f0d0ae0a077 968 }
dudmuck 0:8f0d0ae0a077 969
dudmuck 0:8f0d0ae0a077 970 parsed = false;
dudmuck 0:8f0d0ae0a077 971 for (i = 0; menu_items[i].cmd != NULL ; i++) {
dudmuck 0:8f0d0ae0a077 972 int mi_len = strlen(menu_items[i].cmd);
dudmuck 0:8f0d0ae0a077 973
dudmuck 0:8f0d0ae0a077 974 if (menu_items[i].handler && user_cmd_len == mi_len && (strncmp(pcbuf, menu_items[i].cmd, mi_len) == 0)) {
dudmuck 0:8f0d0ae0a077 975 while (pcbuf[mi_len] == ' ') // skip past spaces
dudmuck 0:8f0d0ae0a077 976 mi_len++;
dudmuck 0:8f0d0ae0a077 977 menu_items[i].handler(mi_len);
dudmuck 0:8f0d0ae0a077 978 parsed = true;
dudmuck 0:8f0d0ae0a077 979 break;
dudmuck 0:8f0d0ae0a077 980 }
dudmuck 0:8f0d0ae0a077 981 }
dudmuck 0:8f0d0ae0a077 982
dudmuck 0:8f0d0ae0a077 983 if (!parsed)
dudmuck 0:8f0d0ae0a077 984 send_pcbuf_uplink();
dudmuck 0:8f0d0ae0a077 985
dudmuck 0:8f0d0ae0a077 986 pcbuf_len = 0;
Wayne Roberts 29:ad409c68c0a6 987 app_printf("> ");
dudmuck 0:8f0d0ae0a077 988 fflush(stdout);
dudmuck 0:8f0d0ae0a077 989 }
dudmuck 0:8f0d0ae0a077 990
dudmuck 0:8f0d0ae0a077 991 void rx_callback()
dudmuck 0:8f0d0ae0a077 992 {
dudmuck 0:8f0d0ae0a077 993 static uint8_t pcbuf_idx = 0;
dudmuck 0:8f0d0ae0a077 994 static uint8_t prev_len = 0;;
dudmuck 0:8f0d0ae0a077 995 char c = pc.getc();
dudmuck 0:8f0d0ae0a077 996
dudmuck 0:8f0d0ae0a077 997 if (c == 8) {
dudmuck 0:8f0d0ae0a077 998 if (pcbuf_idx > 0) {
dudmuck 0:8f0d0ae0a077 999 pc.putc(8);
dudmuck 0:8f0d0ae0a077 1000 pc.putc(' ');
dudmuck 0:8f0d0ae0a077 1001 pc.putc(8);
dudmuck 0:8f0d0ae0a077 1002 pcbuf_idx--;
dudmuck 0:8f0d0ae0a077 1003 }
dudmuck 0:8f0d0ae0a077 1004 } else if (c == 3) { // ctrl-C
dudmuck 0:8f0d0ae0a077 1005 pcbuf_len = -1;
dudmuck 0:8f0d0ae0a077 1006 } else if (c == '\r') {
dudmuck 0:8f0d0ae0a077 1007 if (pcbuf_idx == 0) {
dudmuck 0:8f0d0ae0a077 1008 pcbuf_len = prev_len;
dudmuck 0:8f0d0ae0a077 1009 } else {
dudmuck 0:8f0d0ae0a077 1010 pcbuf[pcbuf_idx] = 0; // null terminate
dudmuck 0:8f0d0ae0a077 1011 prev_len = pcbuf_idx;
dudmuck 0:8f0d0ae0a077 1012 pcbuf_idx = 0;
dudmuck 0:8f0d0ae0a077 1013 pcbuf_len = prev_len;
dudmuck 0:8f0d0ae0a077 1014 }
dudmuck 0:8f0d0ae0a077 1015 } else if (pcbuf_idx < sizeof(pcbuf)) {
dudmuck 0:8f0d0ae0a077 1016 pcbuf[pcbuf_idx++] = c;
dudmuck 0:8f0d0ae0a077 1017 pc.putc(c);
dudmuck 0:8f0d0ae0a077 1018 }
dudmuck 0:8f0d0ae0a077 1019 }
dudmuck 0:8f0d0ae0a077 1020
dudmuck 10:00997daeb0c0 1021 void button_isr()
dudmuck 10:00997daeb0c0 1022 {
Wayne Roberts 29:ad409c68c0a6 1023 app_printf("button_isr\r\n");
dudmuck 19:c3af34457b6d 1024
dudmuck 19:c3af34457b6d 1025 AppPort = SENSOR_PORT;
dudmuck 19:c3af34457b6d 1026 send_uplink();
dudmuck 10:00997daeb0c0 1027 }
dudmuck 10:00997daeb0c0 1028
dudmuck 0:8f0d0ae0a077 1029 /**
dudmuck 0:8f0d0ae0a077 1030 * Main application entry point.
dudmuck 0:8f0d0ae0a077 1031 */
dudmuck 0:8f0d0ae0a077 1032 int main( void )
dudmuck 0:8f0d0ae0a077 1033 {
dudmuck 0:8f0d0ae0a077 1034 LoRaMacPrimitives_t LoRaMacPrimitives;
dudmuck 0:8f0d0ae0a077 1035 LoRaMacCallback_t LoRaMacCallbacks;
dudmuck 0:8f0d0ae0a077 1036 MibRequestConfirm_t mibReq;
dudmuck 0:8f0d0ae0a077 1037
Wayne Roberts 29:ad409c68c0a6 1038 pc.baud(115200);
dudmuck 7:e238827f0e47 1039 pc.attach(&rx_callback);
Wayne Roberts 29:ad409c68c0a6 1040 app_printf("\r\nreset %s\r\n", FW_VERS);
dudmuck 10:00997daeb0c0 1041
dudmuck 10:00997daeb0c0 1042 BoardInit( );
dudmuck 10:00997daeb0c0 1043
dudmuck 0:8f0d0ae0a077 1044 DeviceState = DEVICE_STATE_INIT;
dudmuck 10:00997daeb0c0 1045
dudmuck 20:42839629a5dc 1046 while (!user_button) {
dudmuck 20:42839629a5dc 1047 printf("button-lo\r\n");
dudmuck 20:42839629a5dc 1048 wait(0.01);
dudmuck 10:00997daeb0c0 1049 }
dudmuck 20:42839629a5dc 1050 user_button.fall(&button_isr);
dudmuck 12:ed33c53afcaf 1051
dudmuck 23:a862b5601663 1052 #ifdef ENABLE_LUMINOSITY
Wayne Roberts 29:ad409c68c0a6 1053 app_printf("TSL2561 Sensor ");
dudmuck 12:ed33c53afcaf 1054 if (tsl2561.begin()) {
Wayne Roberts 29:ad409c68c0a6 1055 app_printf("Found\r\n");
dudmuck 12:ed33c53afcaf 1056 } else {
Wayne Roberts 29:ad409c68c0a6 1057 app_printf("not-found\r\n");
dudmuck 12:ed33c53afcaf 1058 }
dudmuck 12:ed33c53afcaf 1059
dudmuck 12:ed33c53afcaf 1060 // You can change the gain on the fly, to adapt to brighter/dimmer tsl2561 situations
dudmuck 12:ed33c53afcaf 1061 tsl2561.setGain(TSL2561_GAIN_0X); // set no gain (for bright situtations)
dudmuck 12:ed33c53afcaf 1062 //tsl2561.setGain(TSL2561_GAIN_16X); // set 16x gain (for dim situations)
dudmuck 12:ed33c53afcaf 1063
dudmuck 12:ed33c53afcaf 1064 // Changing the integration time gives you a longer time over which to sense tsl2561
dudmuck 12:ed33c53afcaf 1065 // longer timelines are slower, but are good in very low tsl2561 situtations!
dudmuck 12:ed33c53afcaf 1066 //tsl2561.setTiming(TSL2561_INTEGRATIONTIME_13MS); // shortest integration time (bright tsl2561)
dudmuck 12:ed33c53afcaf 1067 //tsl2561.setTiming(TSL2561_INTEGRATIONTIME_101MS); // medium integration time (medium tsl2561)
dudmuck 12:ed33c53afcaf 1068 tsl2561.setTiming(TSL2561_INTEGRATIONTIME_402MS); // longest integration time (dim tsl2561)
dudmuck 23:a862b5601663 1069 #endif /* ENABLE_LUMINOSITY */
dudmuck 10:00997daeb0c0 1070
dudmuck 10:00997daeb0c0 1071 jumper_out = 1;
dudmuck 10:00997daeb0c0 1072 jumper_in.mode(PullDown);
Wayne Roberts 29:ad409c68c0a6 1073 //pc2 = 0;
dudmuck 0:8f0d0ae0a077 1074
dudmuck 0:8f0d0ae0a077 1075 while( 1 )
dudmuck 0:8f0d0ae0a077 1076 {
dudmuck 0:8f0d0ae0a077 1077 console();
dudmuck 12:ed33c53afcaf 1078
dudmuck 0:8f0d0ae0a077 1079 switch( DeviceState )
dudmuck 0:8f0d0ae0a077 1080 {
dudmuck 0:8f0d0ae0a077 1081 case DEVICE_STATE_INIT:
dudmuck 0:8f0d0ae0a077 1082 {
Wayne Roberts 29:ad409c68c0a6 1083 app_printf("DEVICE_STATE_INIT\r\n");
dudmuck 23:a862b5601663 1084 #if defined(SENSORS)
dudmuck 14:7ac0add1123e 1085 uplink_length = 7;
dudmuck 14:7ac0add1123e 1086 #else
dudmuck 0:8f0d0ae0a077 1087 uplink_length = 2;
dudmuck 14:7ac0add1123e 1088 #endif
dudmuck 0:8f0d0ae0a077 1089 LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
dudmuck 0:8f0d0ae0a077 1090 LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
dudmuck 0:8f0d0ae0a077 1091 LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
dudmuck 0:8f0d0ae0a077 1092 LoRaMacPrimitives.MacMlmeIndication = MlmeIndication;
dudmuck 0:8f0d0ae0a077 1093 LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
dudmuck 0:8f0d0ae0a077 1094 if (LORAMAC_STATUS_OK != LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks )) {
Wayne Roberts 29:ad409c68c0a6 1095 app_printf("LoRaMacInitialization() failed\r\n");
dudmuck 0:8f0d0ae0a077 1096 for (;;) ;
dudmuck 0:8f0d0ae0a077 1097 }
Wayne Roberts 29:ad409c68c0a6 1098 app_printf("INIT-ok\r\n");
dudmuck 0:8f0d0ae0a077 1099
dudmuck 0:8f0d0ae0a077 1100 mibReq.Type = MIB_PUBLIC_NETWORK;
dudmuck 0:8f0d0ae0a077 1101 mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK;
dudmuck 0:8f0d0ae0a077 1102 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1103
dudmuck 0:8f0d0ae0a077 1104 LoRaMacDownlinkStatus.DownlinkCounter = 0;
dudmuck 0:8f0d0ae0a077 1105
dudmuck 0:8f0d0ae0a077 1106 DeviceState = DEVICE_STATE_JOIN;
dudmuck 0:8f0d0ae0a077 1107 break;
dudmuck 0:8f0d0ae0a077 1108 }
dudmuck 0:8f0d0ae0a077 1109 case DEVICE_STATE_JOIN:
dudmuck 0:8f0d0ae0a077 1110 {
dudmuck 10:00997daeb0c0 1111 if (jumper_in.read()) /* if jumper installed: auto uplink */
dudmuck 10:00997daeb0c0 1112 send_at_beacon = true;
dudmuck 0:8f0d0ae0a077 1113 #if( OVER_THE_AIR_ACTIVATION != 0 )
dudmuck 0:8f0d0ae0a077 1114 MlmeReq_t mlmeReq;
dudmuck 0:8f0d0ae0a077 1115 // override software definition with hardware value
dudmuck 0:8f0d0ae0a077 1116 BoardGetUniqueId(DevEui);
Wayne Roberts 29:ad409c68c0a6 1117 app_printf("DevEUI ");
dudmuck 0:8f0d0ae0a077 1118 for (int i = 0; i < 8; i++)
Wayne Roberts 29:ad409c68c0a6 1119 app_printf("%02x ", DevEui[i]);
Wayne Roberts 29:ad409c68c0a6 1120 app_printf("\r\n");
dudmuck 0:8f0d0ae0a077 1121
dudmuck 0:8f0d0ae0a077 1122 mlmeReq.Type = MLME_JOIN;
dudmuck 0:8f0d0ae0a077 1123
dudmuck 0:8f0d0ae0a077 1124 mlmeReq.Req.Join.DevEui = DevEui;
dudmuck 0:8f0d0ae0a077 1125 mlmeReq.Req.Join.AppEui = AppEui;
dudmuck 0:8f0d0ae0a077 1126 mlmeReq.Req.Join.AppKey = AppKey;
dudmuck 0:8f0d0ae0a077 1127 mlmeReq.Req.Join.NbTrials = 255;
dudmuck 0:8f0d0ae0a077 1128
dudmuck 16:915815632c1f 1129 LoRaMacStatus_t status = LoRaMacMlmeRequest( &mlmeReq );
dudmuck 16:915815632c1f 1130 if (status != LORAMAC_STATUS_OK) {
dudmuck 16:915815632c1f 1131 char str[48];
dudmuck 16:915815632c1f 1132 LoRaMacStatus_to_string(status, str);
Wayne Roberts 29:ad409c68c0a6 1133 app_printf("join-req-failed:%s\r\n", str);
dudmuck 0:8f0d0ae0a077 1134 }
dudmuck 0:8f0d0ae0a077 1135 DeviceState = DEVICE_STATE_SLEEP;
dudmuck 0:8f0d0ae0a077 1136 #else
dudmuck 0:8f0d0ae0a077 1137 mibReq.Type = MIB_NET_ID;
dudmuck 0:8f0d0ae0a077 1138 mibReq.Param.NetID = LORAWAN_NETWORK_ID;
dudmuck 0:8f0d0ae0a077 1139 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1140
dudmuck 0:8f0d0ae0a077 1141 mibReq.Type = MIB_DEV_ADDR;
dudmuck 0:8f0d0ae0a077 1142 mibReq.Param.DevAddr = DevAddr;
dudmuck 0:8f0d0ae0a077 1143 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1144
dudmuck 0:8f0d0ae0a077 1145 mibReq.Type = MIB_NWK_SKEY;
dudmuck 0:8f0d0ae0a077 1146 mibReq.Param.NwkSKey = NwkSKey;
dudmuck 0:8f0d0ae0a077 1147 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1148
dudmuck 0:8f0d0ae0a077 1149 mibReq.Type = MIB_APP_SKEY;
dudmuck 0:8f0d0ae0a077 1150 mibReq.Param.AppSKey = AppSKey;
dudmuck 0:8f0d0ae0a077 1151 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1152
dudmuck 0:8f0d0ae0a077 1153 mibReq.Type = MIB_NETWORK_JOINED;
dudmuck 0:8f0d0ae0a077 1154 mibReq.Param.IsNetworkJoined = true;
dudmuck 0:8f0d0ae0a077 1155 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1156 #endif
dudmuck 21:500ff43d8424 1157 join_retry = false;
dudmuck 0:8f0d0ae0a077 1158 break;
dudmuck 0:8f0d0ae0a077 1159 }
dudmuck 0:8f0d0ae0a077 1160 case DEVICE_STATE_CYCLE:
dudmuck 0:8f0d0ae0a077 1161 {
dudmuck 0:8f0d0ae0a077 1162 DeviceState = DEVICE_STATE_SLEEP;
dudmuck 0:8f0d0ae0a077 1163
dudmuck 0:8f0d0ae0a077 1164 // Schedule next packet transmission
dudmuck 17:3215f12051f9 1165 TxNextPacketTimeout.attach_us(&OnTxNextPacketTimerEvent, TxDutyCycleTime * 1000);
dudmuck 0:8f0d0ae0a077 1166 break;
dudmuck 0:8f0d0ae0a077 1167 }
dudmuck 0:8f0d0ae0a077 1168 case DEVICE_STATE_SLEEP:
dudmuck 0:8f0d0ae0a077 1169 {
Wayne Roberts 29:ad409c68c0a6 1170 //bottom_half();
dudmuck 20:42839629a5dc 1171 LoRaMacBottomHalf();
dudmuck 0:8f0d0ae0a077 1172 // Wake up through events
Wayne Roberts 29:ad409c68c0a6 1173 //pc2 = 1;
dudmuck 20:42839629a5dc 1174 sleep();
Wayne Roberts 29:ad409c68c0a6 1175 //pc2 = 0;
dudmuck 0:8f0d0ae0a077 1176 break;
dudmuck 0:8f0d0ae0a077 1177 }
dudmuck 18:9ac71c0eb70d 1178 case DEVICE_STATE_UPLINK:
Wayne Roberts 29:ad409c68c0a6 1179 app_printf("DEVICE_STATE_UPLINK\r\n");
dudmuck 18:9ac71c0eb70d 1180 PrepareTxFrame(AppPort);
dudmuck 18:9ac71c0eb70d 1181 SendFrame(AppPort);
dudmuck 18:9ac71c0eb70d 1182 DeviceState = DEVICE_STATE_SLEEP;
dudmuck 18:9ac71c0eb70d 1183 break;
dudmuck 0:8f0d0ae0a077 1184 default:
dudmuck 0:8f0d0ae0a077 1185 {
dudmuck 0:8f0d0ae0a077 1186 DeviceState = DEVICE_STATE_INIT;
dudmuck 0:8f0d0ae0a077 1187 break;
dudmuck 0:8f0d0ae0a077 1188 }
dudmuck 0:8f0d0ae0a077 1189 }
dudmuck 1:53c30224eda8 1190
Wayne Roberts 29:ad409c68c0a6 1191 //bottom_half();
dudmuck 20:42839629a5dc 1192 LoRaMacBottomHalf();
dudmuck 1:53c30224eda8 1193
dudmuck 21:500ff43d8424 1194 if (join_retry) {
Wayne Roberts 29:ad409c68c0a6 1195 app_printf("join_retry\r\n");
dudmuck 21:500ff43d8424 1196 DeviceState = DEVICE_STATE_JOIN;
dudmuck 21:500ff43d8424 1197 join_retry = false;
dudmuck 21:500ff43d8424 1198 }
dudmuck 21:500ff43d8424 1199
dudmuck 1:53c30224eda8 1200 } // ..while( 1 )
dudmuck 0:8f0d0ae0a077 1201 }