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:
dudmuck
Date:
Mon Aug 28 13:13:56 2017 -0700
Revision:
28:36be305a5e5e
Parent:
27:c8b432b2a4a8
Child:
29:ad409c68c0a6
when RGB enabled, indicate beacon lost

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