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:
Mon Jul 13 09:15:59 2020 -0700
Revision:
35:be452a242876
Parent:
34:9c8966cd66a2
remove old crypto

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