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 Jun 19 23:49:42 2017 +0000
Revision:
11:4c337f5bbe4c
Parent:
10:00997daeb0c0
Child:
12:ed33c53afcaf
sensor support in application layer

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 11:4c337f5bbe4c 23 DigitalOut grove_led(D6);
dudmuck 11:4c337f5bbe4c 24 uint32_t grove_cnt;
dudmuck 10:00997daeb0c0 25 #if defined(ENABLE_SX1272) && defined(SENSORS)
dudmuck 10:00997daeb0c0 26 #include "Air_Quality.h"
dudmuck 10:00997daeb0c0 27 AirQuality airqualitysensor;
dudmuck 10:00997daeb0c0 28 PinName analogPin = A1;
dudmuck 10:00997daeb0c0 29 #define SENSOR_PORT 10
dudmuck 10:00997daeb0c0 30 InterruptIn button(D8);
dudmuck 10:00997daeb0c0 31 #define RED_LED_RATE_US 333333 /* third of second */
dudmuck 10:00997daeb0c0 32 uint32_t button_cnt;
dudmuck 10:00997daeb0c0 33 //AnalogIn water(A3);
dudmuck 10:00997daeb0c0 34 DigitalIn water(A3);
dudmuck 10:00997daeb0c0 35 #endif
dudmuck 10:00997daeb0c0 36
dudmuck 10:00997daeb0c0 37 DigitalOut jumper_out(PC_10);
dudmuck 10:00997daeb0c0 38 InterruptIn jumper_in(PC_12);
dudmuck 10:00997daeb0c0 39
dudmuck 0:8f0d0ae0a077 40 char pcbuf[128];
dudmuck 0:8f0d0ae0a077 41 int pcbuf_len;
dudmuck 0:8f0d0ae0a077 42
dudmuck 0:8f0d0ae0a077 43 /*!
dudmuck 0:8f0d0ae0a077 44 * Defines the application data transmission duty cycle. 5s, value in [ms].
dudmuck 0:8f0d0ae0a077 45 */
dudmuck 0:8f0d0ae0a077 46 #define APP_TX_DUTYCYCLE 5000
dudmuck 0:8f0d0ae0a077 47
dudmuck 0:8f0d0ae0a077 48 /*!
dudmuck 0:8f0d0ae0a077 49 * Defines a random delay for application data transmission duty cycle. 1s,
dudmuck 0:8f0d0ae0a077 50 * value in [ms].
dudmuck 0:8f0d0ae0a077 51 */
dudmuck 0:8f0d0ae0a077 52 #define APP_TX_DUTYCYCLE_RND 1000
dudmuck 0:8f0d0ae0a077 53
dudmuck 0:8f0d0ae0a077 54 /*!
dudmuck 0:8f0d0ae0a077 55 * Default datarate
dudmuck 0:8f0d0ae0a077 56 */
dudmuck 0:8f0d0ae0a077 57 #define LORAWAN_DEFAULT_DATARATE DR_10
dudmuck 0:8f0d0ae0a077 58
dudmuck 0:8f0d0ae0a077 59 /*!
dudmuck 0:8f0d0ae0a077 60 * LoRaWAN confirmed messages
dudmuck 0:8f0d0ae0a077 61 */
dudmuck 0:8f0d0ae0a077 62 #define LORAWAN_CONFIRMED_MSG_ON true
dudmuck 0:8f0d0ae0a077 63
dudmuck 0:8f0d0ae0a077 64 /*!
dudmuck 0:8f0d0ae0a077 65 * LoRaWAN application port
dudmuck 0:8f0d0ae0a077 66 */
dudmuck 0:8f0d0ae0a077 67 #define LORAWAN_APP_PORT 15
dudmuck 0:8f0d0ae0a077 68
dudmuck 0:8f0d0ae0a077 69 /*!
dudmuck 0:8f0d0ae0a077 70 * User application data buffer size
dudmuck 0:8f0d0ae0a077 71 */
dudmuck 0:8f0d0ae0a077 72 #if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
dudmuck 0:8f0d0ae0a077 73 #define LORAWAN_APP_DATA_SIZE 6
dudmuck 0:8f0d0ae0a077 74
dudmuck 0:8f0d0ae0a077 75 #else
dudmuck 0:8f0d0ae0a077 76 #define LORAWAN_APP_DATA_SIZE 1
dudmuck 0:8f0d0ae0a077 77
dudmuck 0:8f0d0ae0a077 78 #endif
dudmuck 0:8f0d0ae0a077 79
dudmuck 0:8f0d0ae0a077 80 static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
dudmuck 0:8f0d0ae0a077 81 static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
dudmuck 0:8f0d0ae0a077 82 static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
dudmuck 0:8f0d0ae0a077 83
dudmuck 0:8f0d0ae0a077 84 #if( OVER_THE_AIR_ACTIVATION == 0 )
dudmuck 0:8f0d0ae0a077 85
dudmuck 0:8f0d0ae0a077 86 static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
dudmuck 0:8f0d0ae0a077 87 static uint8_t AppSKey[] = LORAWAN_APPSKEY;
dudmuck 0:8f0d0ae0a077 88
dudmuck 0:8f0d0ae0a077 89 /*!
dudmuck 0:8f0d0ae0a077 90 * Device address
dudmuck 0:8f0d0ae0a077 91 */
dudmuck 0:8f0d0ae0a077 92 static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
dudmuck 0:8f0d0ae0a077 93
dudmuck 0:8f0d0ae0a077 94 #endif
dudmuck 0:8f0d0ae0a077 95
dudmuck 0:8f0d0ae0a077 96 /*!
dudmuck 0:8f0d0ae0a077 97 * Application port
dudmuck 0:8f0d0ae0a077 98 */
dudmuck 11:4c337f5bbe4c 99 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 10:00997daeb0c0 100 static uint8_t AppPort = SENSOR_PORT;
dudmuck 10:00997daeb0c0 101 #else
dudmuck 10:00997daeb0c0 102 static uint8_t AppPort = LORAWAN_APP_PORT;
dudmuck 10:00997daeb0c0 103 #endif
dudmuck 0:8f0d0ae0a077 104
dudmuck 0:8f0d0ae0a077 105 /*!
dudmuck 0:8f0d0ae0a077 106 * User application data size
dudmuck 0:8f0d0ae0a077 107 */
dudmuck 0:8f0d0ae0a077 108 static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE;
dudmuck 0:8f0d0ae0a077 109 static unsigned int uplink_length; // user assigned
dudmuck 0:8f0d0ae0a077 110
dudmuck 0:8f0d0ae0a077 111 /*!
dudmuck 0:8f0d0ae0a077 112 * User application data buffer size
dudmuck 0:8f0d0ae0a077 113 */
dudmuck 0:8f0d0ae0a077 114 #define LORAWAN_APP_DATA_MAX_SIZE 128
dudmuck 0:8f0d0ae0a077 115
dudmuck 0:8f0d0ae0a077 116 /*!
dudmuck 0:8f0d0ae0a077 117 * User application data
dudmuck 0:8f0d0ae0a077 118 */
dudmuck 0:8f0d0ae0a077 119 static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
dudmuck 0:8f0d0ae0a077 120
dudmuck 0:8f0d0ae0a077 121 /*!
dudmuck 0:8f0d0ae0a077 122 * Indicates if the node is sending confirmed or unconfirmed messages
dudmuck 0:8f0d0ae0a077 123 */
dudmuck 0:8f0d0ae0a077 124 static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
dudmuck 0:8f0d0ae0a077 125
dudmuck 0:8f0d0ae0a077 126 /*!
dudmuck 0:8f0d0ae0a077 127 * Defines the application data transmission duty cycle
dudmuck 0:8f0d0ae0a077 128 */
dudmuck 0:8f0d0ae0a077 129 static uint32_t TxDutyCycleTime;
dudmuck 0:8f0d0ae0a077 130
dudmuck 0:8f0d0ae0a077 131 /*!
dudmuck 0:8f0d0ae0a077 132 * Timer to handle the application data transmission duty cycle
dudmuck 0:8f0d0ae0a077 133 */
dudmuck 0:8f0d0ae0a077 134 LowPowerTimeout TxNextPacketTimer;
dudmuck 0:8f0d0ae0a077 135
dudmuck 0:8f0d0ae0a077 136 volatile bool send_at_beacon;
dudmuck 0:8f0d0ae0a077 137 volatile bool awaiting_mcps_indic;
dudmuck 0:8f0d0ae0a077 138 /*!
dudmuck 0:8f0d0ae0a077 139 * Specifies the state of the application LED
dudmuck 0:8f0d0ae0a077 140 */
dudmuck 0:8f0d0ae0a077 141 static bool AppLedStateOn = false;
dudmuck 0:8f0d0ae0a077 142
dudmuck 0:8f0d0ae0a077 143 /*!
dudmuck 0:8f0d0ae0a077 144 * Indicates if a new packet can be sent
dudmuck 0:8f0d0ae0a077 145 */
dudmuck 0:8f0d0ae0a077 146 static bool NextTx = true;
dudmuck 0:8f0d0ae0a077 147
dudmuck 0:8f0d0ae0a077 148 /*!
dudmuck 0:8f0d0ae0a077 149 * Device states
dudmuck 0:8f0d0ae0a077 150 */
dudmuck 0:8f0d0ae0a077 151 static enum eDeviceState
dudmuck 0:8f0d0ae0a077 152 {
dudmuck 0:8f0d0ae0a077 153 DEVICE_STATE_INIT,
dudmuck 0:8f0d0ae0a077 154 DEVICE_STATE_JOIN,
dudmuck 0:8f0d0ae0a077 155 DEVICE_STATE_SEND,
dudmuck 0:8f0d0ae0a077 156 DEVICE_STATE_CYCLE,
dudmuck 0:8f0d0ae0a077 157 DEVICE_STATE_SLEEP
dudmuck 0:8f0d0ae0a077 158 }DeviceState;
dudmuck 0:8f0d0ae0a077 159
dudmuck 0:8f0d0ae0a077 160 /*!
dudmuck 0:8f0d0ae0a077 161 * Strucure containing the Uplink status
dudmuck 0:8f0d0ae0a077 162 */
dudmuck 0:8f0d0ae0a077 163 struct sLoRaMacUplinkStatus
dudmuck 0:8f0d0ae0a077 164 {
dudmuck 0:8f0d0ae0a077 165 uint8_t Acked;
dudmuck 0:8f0d0ae0a077 166 //int8_t Datarate;
dudmuck 0:8f0d0ae0a077 167 uint16_t UplinkCounter;
dudmuck 0:8f0d0ae0a077 168 uint8_t Port;
dudmuck 0:8f0d0ae0a077 169 uint8_t *Buffer;
dudmuck 0:8f0d0ae0a077 170 uint8_t BufferSize;
dudmuck 0:8f0d0ae0a077 171 }LoRaMacUplinkStatus;
dudmuck 0:8f0d0ae0a077 172 //volatile bool UplinkStatusUpdated = false;
dudmuck 0:8f0d0ae0a077 173
dudmuck 0:8f0d0ae0a077 174 /*!
dudmuck 0:8f0d0ae0a077 175 * Strucure containing the Downlink status
dudmuck 0:8f0d0ae0a077 176 */
dudmuck 0:8f0d0ae0a077 177 struct sLoRaMacDownlinkStatus
dudmuck 0:8f0d0ae0a077 178 {
dudmuck 0:8f0d0ae0a077 179 int16_t Rssi;
dudmuck 0:8f0d0ae0a077 180 int8_t Snr;
dudmuck 0:8f0d0ae0a077 181 uint16_t DownlinkCounter;
dudmuck 0:8f0d0ae0a077 182 bool RxData;
dudmuck 0:8f0d0ae0a077 183 uint8_t Port;
dudmuck 0:8f0d0ae0a077 184 uint8_t *Buffer;
dudmuck 0:8f0d0ae0a077 185 uint8_t BufferSize;
dudmuck 0:8f0d0ae0a077 186 }LoRaMacDownlinkStatus;
dudmuck 0:8f0d0ae0a077 187
dudmuck 2:f2d9aa163652 188 static uint8_t missed_count;
dudmuck 2:f2d9aa163652 189
dudmuck 0:8f0d0ae0a077 190
dudmuck 0:8f0d0ae0a077 191 /*!
dudmuck 0:8f0d0ae0a077 192 * \brief Prepares the payload of the frame
dudmuck 0:8f0d0ae0a077 193 */
dudmuck 0:8f0d0ae0a077 194 static void PrepareTxFrame( uint8_t port )
dudmuck 0:8f0d0ae0a077 195 {
dudmuck 0:8f0d0ae0a077 196 switch( port )
dudmuck 0:8f0d0ae0a077 197 {
dudmuck 0:8f0d0ae0a077 198 case 15:
dudmuck 0:8f0d0ae0a077 199 {
dudmuck 0:8f0d0ae0a077 200 AppData[0] = AppLedStateOn;
dudmuck 0:8f0d0ae0a077 201 if( IsTxConfirmed == true )
dudmuck 0:8f0d0ae0a077 202 {
dudmuck 0:8f0d0ae0a077 203 AppData[1] = LoRaMacDownlinkStatus.DownlinkCounter >> 8;
dudmuck 0:8f0d0ae0a077 204 AppData[2] = LoRaMacDownlinkStatus.DownlinkCounter;
dudmuck 0:8f0d0ae0a077 205 AppData[3] = LoRaMacDownlinkStatus.Rssi >> 8;
dudmuck 0:8f0d0ae0a077 206 AppData[4] = LoRaMacDownlinkStatus.Rssi;
dudmuck 0:8f0d0ae0a077 207 AppData[5] = LoRaMacDownlinkStatus.Snr;
dudmuck 0:8f0d0ae0a077 208 }
dudmuck 0:8f0d0ae0a077 209 }
dudmuck 0:8f0d0ae0a077 210 break;
dudmuck 11:4c337f5bbe4c 211 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 10:00997daeb0c0 212 case SENSOR_PORT:
dudmuck 10:00997daeb0c0 213 airqualitysensor.slope();
dudmuck 10:00997daeb0c0 214 AppData[0] = airqualitysensor.first_vol >> 8;
dudmuck 10:00997daeb0c0 215 AppData[1] = airqualitysensor.first_vol & 0xff;
dudmuck 10:00997daeb0c0 216 AppDataSize = 2;
dudmuck 10:00997daeb0c0 217 isr_printf("first_vol:%d last_vol:%d\r\n", airqualitysensor.first_vol, airqualitysensor.last_vol);
dudmuck 10:00997daeb0c0 218 break;
dudmuck 10:00997daeb0c0 219 #endif /* SENSORS */
dudmuck 0:8f0d0ae0a077 220 default:
dudmuck 0:8f0d0ae0a077 221 break;
dudmuck 0:8f0d0ae0a077 222 }
dudmuck 0:8f0d0ae0a077 223 }
dudmuck 0:8f0d0ae0a077 224
dudmuck 0:8f0d0ae0a077 225 void
dudmuck 0:8f0d0ae0a077 226 LoRaMacEventInfoStatus_to_string(LoRaMacEventInfoStatus_t status, char* dst)
dudmuck 0:8f0d0ae0a077 227 {
dudmuck 0:8f0d0ae0a077 228 const char* ptr = NULL;
dudmuck 0:8f0d0ae0a077 229
dudmuck 0:8f0d0ae0a077 230 switch (status) {
dudmuck 0:8f0d0ae0a077 231 case LORAMAC_EVENT_INFO_STATUS_RX_ERROR: ptr = "RX_ERROR"; break;
dudmuck 0:8f0d0ae0a077 232 case LORAMAC_EVENT_INFO_STATUS_OK: ptr = "OK"; break;
dudmuck 2:f2d9aa163652 233 case LORAMAC_EVENT_INFO_STATUS_ERROR_RX_MTYPE: ptr = "ERROR_RX_MTYPE"; break;
dudmuck 2:f2d9aa163652 234 case LORAMAC_EVENT_INFO_STATUS_ERROR_SEND: ptr = "ERROR_SEND"; break;
dudmuck 2:f2d9aa163652 235 case LORAMAC_EVENT_INFO_STATUS_ERROR_JOIN_ACCEPT: ptr = "ERROR_JOIN_ACCEPT"; break;
dudmuck 2:f2d9aa163652 236 case LORAMAC_EVENT_INFO_STATUS_ERROR_MLMEREQ: ptr = "ERROR_MLMEREQ"; break;
dudmuck 2:f2d9aa163652 237 case LORAMAC_EVENT_INFO_STATUS_ERROR_MCPSREQ: ptr = "ERROR_MCPSREQ"; break;
dudmuck 2:f2d9aa163652 238 //case LORAMAC_EVENT_INFO_STATUS_ERROR: ptr = "ERROR"; break;
dudmuck 2:f2d9aa163652 239
dudmuck 0:8f0d0ae0a077 240 case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT: ptr = "TX_TIMEOUT"; break;
dudmuck 0:8f0d0ae0a077 241 case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT: ptr = "RX_TIMEOUT"; break;
dudmuck 0:8f0d0ae0a077 242 case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL: ptr = "JOIN_FAIL"; break;
dudmuck 0:8f0d0ae0a077 243 case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED: ptr = "DOWNLINK_REPEATED"; break;
dudmuck 0:8f0d0ae0a077 244 case LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR: ptr = "TX_DR_PAYLOAD_SIZE_ERROR"; break;
dudmuck 0:8f0d0ae0a077 245 case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS: ptr = "DOWNLINK_TOO_MANY_FRAMES_LOSS"; break;
dudmuck 0:8f0d0ae0a077 246 case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL: ptr = "ADDRESS_FAIL"; break;
dudmuck 0:8f0d0ae0a077 247 case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL: ptr = "MIC_FAIL"; break;
dudmuck 0:8f0d0ae0a077 248 case LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED: ptr = "BEACON_LOCKED"; break;
dudmuck 0:8f0d0ae0a077 249 case LORAMAC_EVENT_INFO_STATUS_BEACON_LOST: ptr = "BEACON_LOST"; break;
dudmuck 0:8f0d0ae0a077 250 case LORAMAC_EVENT_INFO_STATUS_BEACON_NOT_FOUND: ptr = "BEACON_NOT_FOUND"; break;
dudmuck 0:8f0d0ae0a077 251 }
dudmuck 0:8f0d0ae0a077 252
dudmuck 0:8f0d0ae0a077 253 if (ptr != NULL)
dudmuck 0:8f0d0ae0a077 254 strcpy(dst, ptr);
dudmuck 0:8f0d0ae0a077 255 }
dudmuck 0:8f0d0ae0a077 256
dudmuck 0:8f0d0ae0a077 257 void
dudmuck 0:8f0d0ae0a077 258 LoRaMacStatus_to_string(LoRaMacStatus_t status, char* dst)
dudmuck 0:8f0d0ae0a077 259 {
dudmuck 0:8f0d0ae0a077 260 const char* ptr = NULL;
dudmuck 0:8f0d0ae0a077 261
dudmuck 0:8f0d0ae0a077 262 switch (status) {
dudmuck 0:8f0d0ae0a077 263 case LORAMAC_STATUS_OK: ptr = "OK"; break;
dudmuck 0:8f0d0ae0a077 264 case LORAMAC_STATUS_BUSY: ptr = "BUSY"; break;
dudmuck 0:8f0d0ae0a077 265 case LORAMAC_STATUS_SERVICE_UNKNOWN: ptr = "SERVICE_UNKNOWN"; break;
dudmuck 0:8f0d0ae0a077 266 case LORAMAC_STATUS_PARAMETER_INVALID: ptr = "PARAMETER_INVALID"; break;
dudmuck 0:8f0d0ae0a077 267 case LORAMAC_STATUS_FREQUENCY_INVALID: ptr = "FREQUENCY_INVALID"; break;
dudmuck 0:8f0d0ae0a077 268 case LORAMAC_STATUS_DATARATE_INVALID: ptr = "DATARATE_INVALID"; break;
dudmuck 0:8f0d0ae0a077 269 case LORAMAC_STATUS_FREQ_AND_DR_INVALID: ptr = "FREQ_AND_DR_INVALID"; break;
dudmuck 0:8f0d0ae0a077 270 case LORAMAC_STATUS_NO_NETWORK_JOINED: ptr = "NO_NETWORK_JOINED"; break;
dudmuck 0:8f0d0ae0a077 271 case LORAMAC_STATUS_LENGTH_ERROR: ptr = "LENGTH_ERROR"; break;
dudmuck 0:8f0d0ae0a077 272 case LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR: ptr = "MAC_CMD_LENGTH_ERROR"; break;
dudmuck 0:8f0d0ae0a077 273 case LORAMAC_STATUS_DEVICE_OFF: ptr = "DEVICE_OFF"; break;
dudmuck 0:8f0d0ae0a077 274 }
dudmuck 0:8f0d0ae0a077 275 if (ptr != NULL)
dudmuck 0:8f0d0ae0a077 276 strcpy(dst, ptr);
dudmuck 0:8f0d0ae0a077 277 }
dudmuck 0:8f0d0ae0a077 278
dudmuck 0:8f0d0ae0a077 279 /*!
dudmuck 5:c108560af4c3 280 * \brief Function executed on TxNextPacket Timeout event
dudmuck 5:c108560af4c3 281 */
dudmuck 5:c108560af4c3 282 static void OnTxNextPacketTimerEvent( void )
dudmuck 5:c108560af4c3 283 {
dudmuck 5:c108560af4c3 284 MibRequestConfirm_t mibReq;
dudmuck 5:c108560af4c3 285 LoRaMacStatus_t status;
dudmuck 5:c108560af4c3 286
dudmuck 5:c108560af4c3 287 mibReq.Type = MIB_NETWORK_JOINED;
dudmuck 5:c108560af4c3 288 status = LoRaMacMibGetRequestConfirm( &mibReq );
dudmuck 5:c108560af4c3 289
dudmuck 5:c108560af4c3 290 if( status == LORAMAC_STATUS_OK )
dudmuck 5:c108560af4c3 291 {
dudmuck 5:c108560af4c3 292 if( mibReq.Param.IsNetworkJoined == true )
dudmuck 5:c108560af4c3 293 {
dudmuck 5:c108560af4c3 294 DeviceState = DEVICE_STATE_SEND;
dudmuck 5:c108560af4c3 295 NextTx = true;
dudmuck 5:c108560af4c3 296 }
dudmuck 5:c108560af4c3 297 else
dudmuck 5:c108560af4c3 298 {
dudmuck 5:c108560af4c3 299 DeviceState = DEVICE_STATE_JOIN;
dudmuck 5:c108560af4c3 300 }
dudmuck 5:c108560af4c3 301 }
dudmuck 5:c108560af4c3 302 }
dudmuck 5:c108560af4c3 303
dudmuck 5:c108560af4c3 304 /*!
dudmuck 0:8f0d0ae0a077 305 * \brief Prepares the payload of the frame
dudmuck 0:8f0d0ae0a077 306 *
dudmuck 0:8f0d0ae0a077 307 * \retval [0: frame could be send, 1: error]
dudmuck 0:8f0d0ae0a077 308 */
dudmuck 0:8f0d0ae0a077 309 static bool SendFrame( void )
dudmuck 0:8f0d0ae0a077 310 {
dudmuck 0:8f0d0ae0a077 311 McpsReq_t mcpsReq;
dudmuck 0:8f0d0ae0a077 312 LoRaMacTxInfo_t txInfo;
dudmuck 0:8f0d0ae0a077 313 LoRaMacStatus_t status;
dudmuck 0:8f0d0ae0a077 314 char str[64];
dudmuck 0:8f0d0ae0a077 315
dudmuck 0:8f0d0ae0a077 316 if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
dudmuck 0:8f0d0ae0a077 317 {
dudmuck 0:8f0d0ae0a077 318 // Send empty frame in order to flush MAC commands
dudmuck 0:8f0d0ae0a077 319 mcpsReq.Type = MCPS_UNCONFIRMED;
dudmuck 0:8f0d0ae0a077 320 mcpsReq.Req.Unconfirmed.fBuffer = NULL;
dudmuck 0:8f0d0ae0a077 321 mcpsReq.Req.Unconfirmed.fBufferSize = 0;
dudmuck 0:8f0d0ae0a077 322 //mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
dudmuck 0:8f0d0ae0a077 323
dudmuck 0:8f0d0ae0a077 324 LoRaMacUplinkStatus.Acked = false;
dudmuck 0:8f0d0ae0a077 325 LoRaMacUplinkStatus.Port = 0;
dudmuck 0:8f0d0ae0a077 326 LoRaMacUplinkStatus.Buffer = NULL;
dudmuck 0:8f0d0ae0a077 327 LoRaMacUplinkStatus.BufferSize = 0;
dudmuck 0:8f0d0ae0a077 328 }
dudmuck 0:8f0d0ae0a077 329 else
dudmuck 0:8f0d0ae0a077 330 {
dudmuck 0:8f0d0ae0a077 331 LoRaMacUplinkStatus.Acked = false;
dudmuck 0:8f0d0ae0a077 332 LoRaMacUplinkStatus.Port = AppPort;
dudmuck 0:8f0d0ae0a077 333 LoRaMacUplinkStatus.Buffer = AppData;
dudmuck 0:8f0d0ae0a077 334 LoRaMacUplinkStatus.BufferSize = AppDataSize;
dudmuck 0:8f0d0ae0a077 335
dudmuck 0:8f0d0ae0a077 336 if( IsTxConfirmed == false )
dudmuck 0:8f0d0ae0a077 337 {
dudmuck 0:8f0d0ae0a077 338 mcpsReq.Type = MCPS_UNCONFIRMED;
dudmuck 0:8f0d0ae0a077 339 mcpsReq.Req.Unconfirmed.fPort = AppPort;
dudmuck 0:8f0d0ae0a077 340 mcpsReq.Req.Unconfirmed.fBuffer = AppData;
dudmuck 0:8f0d0ae0a077 341 mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize;
dudmuck 0:8f0d0ae0a077 342 //mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
dudmuck 0:8f0d0ae0a077 343 }
dudmuck 0:8f0d0ae0a077 344 else
dudmuck 0:8f0d0ae0a077 345 {
dudmuck 0:8f0d0ae0a077 346 mcpsReq.Type = MCPS_CONFIRMED;
dudmuck 0:8f0d0ae0a077 347 mcpsReq.Req.Confirmed.fPort = AppPort;
dudmuck 0:8f0d0ae0a077 348 mcpsReq.Req.Confirmed.fBuffer = AppData;
dudmuck 0:8f0d0ae0a077 349 mcpsReq.Req.Confirmed.fBufferSize = AppDataSize;
dudmuck 0:8f0d0ae0a077 350 mcpsReq.Req.Confirmed.NbTrials = 8;
dudmuck 0:8f0d0ae0a077 351 //mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
dudmuck 0:8f0d0ae0a077 352 }
dudmuck 0:8f0d0ae0a077 353 }
dudmuck 0:8f0d0ae0a077 354
dudmuck 0:8f0d0ae0a077 355 status = LoRaMacMcpsRequest( &mcpsReq );
dudmuck 0:8f0d0ae0a077 356 if( status == LORAMAC_STATUS_OK )
dudmuck 0:8f0d0ae0a077 357 {
dudmuck 0:8f0d0ae0a077 358 awaiting_mcps_indic = true;
dudmuck 0:8f0d0ae0a077 359 return false;
dudmuck 0:8f0d0ae0a077 360 }
dudmuck 0:8f0d0ae0a077 361 LoRaMacStatus_to_string(status, str);
dudmuck 1:53c30224eda8 362 isr_printf("send failed:%s\r\n", str);
dudmuck 5:c108560af4c3 363 if (status == LORAMAC_STATUS_NO_NETWORK_JOINED) {
dudmuck 5:c108560af4c3 364 TxNextPacketTimer.attach_us(&OnTxNextPacketTimerEvent, randr(1000000, 5000000) + 1000000);
dudmuck 5:c108560af4c3 365 }
dudmuck 0:8f0d0ae0a077 366 send_at_beacon = true;
dudmuck 0:8f0d0ae0a077 367 return true;
dudmuck 0:8f0d0ae0a077 368 }
dudmuck 0:8f0d0ae0a077 369
dudmuck 0:8f0d0ae0a077 370
dudmuck 0:8f0d0ae0a077 371 void
dudmuck 0:8f0d0ae0a077 372 send_uplink()
dudmuck 0:8f0d0ae0a077 373 {
dudmuck 0:8f0d0ae0a077 374 AppDataSize = uplink_length;
dudmuck 1:53c30224eda8 375 NextTx = true;
dudmuck 1:53c30224eda8 376 DeviceState = DEVICE_STATE_SEND;
dudmuck 0:8f0d0ae0a077 377 }
dudmuck 0:8f0d0ae0a077 378
dudmuck 0:8f0d0ae0a077 379
dudmuck 0:8f0d0ae0a077 380 /*!
dudmuck 0:8f0d0ae0a077 381 * \brief MCPS-Confirm event function
dudmuck 0:8f0d0ae0a077 382 *
dudmuck 0:8f0d0ae0a077 383 * \param [IN] mcpsConfirm - Pointer to the confirm structure,
dudmuck 0:8f0d0ae0a077 384 * containing confirm attributes.
dudmuck 0:8f0d0ae0a077 385 */
dudmuck 0:8f0d0ae0a077 386 static void McpsConfirm( McpsConfirm_t *mcpsConfirm )
dudmuck 0:8f0d0ae0a077 387 {
dudmuck 2:f2d9aa163652 388 static uint8_t fail_count = 0;
dudmuck 0:8f0d0ae0a077 389 char str[64];
dudmuck 2:f2d9aa163652 390
dudmuck 1:53c30224eda8 391 isr_printf("McpsConfirm ");
dudmuck 0:8f0d0ae0a077 392 if( mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
dudmuck 0:8f0d0ae0a077 393 {
dudmuck 2:f2d9aa163652 394 fail_count = 0;
dudmuck 1:53c30224eda8 395 isr_printf("OK ");
dudmuck 0:8f0d0ae0a077 396 switch( mcpsConfirm->McpsRequest )
dudmuck 0:8f0d0ae0a077 397 {
dudmuck 0:8f0d0ae0a077 398 case MCPS_UNCONFIRMED:
dudmuck 0:8f0d0ae0a077 399 {
dudmuck 1:53c30224eda8 400 isr_printf("UNCONFIRMED");
dudmuck 0:8f0d0ae0a077 401 // Check Datarate
dudmuck 0:8f0d0ae0a077 402 // Check TxPower
dudmuck 0:8f0d0ae0a077 403 break;
dudmuck 0:8f0d0ae0a077 404 }
dudmuck 0:8f0d0ae0a077 405 case MCPS_CONFIRMED:
dudmuck 0:8f0d0ae0a077 406 {
dudmuck 1:53c30224eda8 407 isr_printf("CONFIRMED");
dudmuck 0:8f0d0ae0a077 408 // Check Datarate
dudmuck 0:8f0d0ae0a077 409 // Check TxPower
dudmuck 0:8f0d0ae0a077 410 // Check AckReceived
dudmuck 0:8f0d0ae0a077 411 // Check NbTrials
dudmuck 0:8f0d0ae0a077 412 LoRaMacUplinkStatus.Acked = mcpsConfirm->AckReceived;
dudmuck 0:8f0d0ae0a077 413 break;
dudmuck 0:8f0d0ae0a077 414 }
dudmuck 0:8f0d0ae0a077 415 case MCPS_PROPRIETARY:
dudmuck 0:8f0d0ae0a077 416 {
dudmuck 0:8f0d0ae0a077 417 break;
dudmuck 0:8f0d0ae0a077 418 }
dudmuck 0:8f0d0ae0a077 419 default:
dudmuck 0:8f0d0ae0a077 420 break;
dudmuck 0:8f0d0ae0a077 421 }
dudmuck 0:8f0d0ae0a077 422 //LoRaMacUplinkStatus.Datarate = mcpsConfirm->Datarate;
dudmuck 0:8f0d0ae0a077 423 LoRaMacUplinkStatus.UplinkCounter = mcpsConfirm->UpLinkCounter;
dudmuck 0:8f0d0ae0a077 424
dudmuck 0:8f0d0ae0a077 425 } else {
dudmuck 0:8f0d0ae0a077 426 LoRaMacEventInfoStatus_to_string(mcpsConfirm->Status, str);
dudmuck 1:53c30224eda8 427 isr_printf("%s ", str);
dudmuck 0:8f0d0ae0a077 428
dudmuck 10:00997daeb0c0 429 //#ifndef MANUAL_UPLINK
dudmuck 0:8f0d0ae0a077 430 /* mcpsIndication may not come. last uplink done, send another uplink */
dudmuck 10:00997daeb0c0 431 if (jumper_in.read()) /* jumper installe: auto uplink */
dudmuck 10:00997daeb0c0 432 TxNextPacketTimer.attach_us(&send_uplink, 100000);
dudmuck 10:00997daeb0c0 433 //#endif /* !MANUAL_UPLINK */
dudmuck 2:f2d9aa163652 434 if (++fail_count > 10) {
dudmuck 2:f2d9aa163652 435 /* cause re-join */
dudmuck 2:f2d9aa163652 436 MibRequestConfirm_t mibReq;
dudmuck 2:f2d9aa163652 437 mibReq.Type = MIB_NETWORK_JOINED;
dudmuck 2:f2d9aa163652 438 mibReq.Param.IsNetworkJoined = false;
dudmuck 2:f2d9aa163652 439 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 2:f2d9aa163652 440 }
dudmuck 0:8f0d0ae0a077 441 }
dudmuck 0:8f0d0ae0a077 442
dudmuck 0:8f0d0ae0a077 443 NextTx = true;
dudmuck 1:53c30224eda8 444 isr_printf("\r\n");
dudmuck 0:8f0d0ae0a077 445 }
dudmuck 0:8f0d0ae0a077 446
dudmuck 11:4c337f5bbe4c 447 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 11:4c337f5bbe4c 448 void grove_led_cb()
dudmuck 10:00997daeb0c0 449 {
dudmuck 11:4c337f5bbe4c 450 grove_led = !grove_led;
dudmuck 10:00997daeb0c0 451
dudmuck 11:4c337f5bbe4c 452 if (grove_cnt > 0 || grove_led.read()) {
dudmuck 11:4c337f5bbe4c 453 TxNextPacketTimer.attach_us(&grove_led_cb, RED_LED_RATE_US);
dudmuck 11:4c337f5bbe4c 454 if (grove_led.read()) /* only decrement on falling edge */
dudmuck 11:4c337f5bbe4c 455 grove_cnt--;
dudmuck 10:00997daeb0c0 456 }
dudmuck 10:00997daeb0c0 457 }
dudmuck 10:00997daeb0c0 458 #endif /* SENSORS */
dudmuck 10:00997daeb0c0 459
dudmuck 0:8f0d0ae0a077 460 /*!
dudmuck 0:8f0d0ae0a077 461 * \brief MCPS-Indication event function
dudmuck 0:8f0d0ae0a077 462 *
dudmuck 0:8f0d0ae0a077 463 * \param [IN] mcpsIndication - Pointer to the indication structure,
dudmuck 0:8f0d0ae0a077 464 * containing indication attributes.
dudmuck 0:8f0d0ae0a077 465 */
dudmuck 0:8f0d0ae0a077 466 static void McpsIndication( McpsIndication_t *mcpsIndication )
dudmuck 0:8f0d0ae0a077 467 {
dudmuck 11:4c337f5bbe4c 468 char str[64];
dudmuck 1:53c30224eda8 469 isr_printf("McpsIndication ");
dudmuck 0:8f0d0ae0a077 470
dudmuck 10:00997daeb0c0 471 //#ifndef MANUAL_UPLINK
dudmuck 0:8f0d0ae0a077 472 /* last uplink done, send another uplink */
dudmuck 10:00997daeb0c0 473 if (jumper_in.read()) /* jumper installed: auto uplink */
dudmuck 10:00997daeb0c0 474 TxNextPacketTimer.attach_us(&send_uplink, 100000);
dudmuck 10:00997daeb0c0 475 //#endif /* !MANUAL_UPLINK */
dudmuck 0:8f0d0ae0a077 476
dudmuck 0:8f0d0ae0a077 477 if( mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
dudmuck 0:8f0d0ae0a077 478 {
dudmuck 11:4c337f5bbe4c 479 LoRaMacEventInfoStatus_to_string(mcpsIndication->Status, str);
dudmuck 11:4c337f5bbe4c 480 isr_printf("%s\r\n", str);
dudmuck 0:8f0d0ae0a077 481 return;
dudmuck 0:8f0d0ae0a077 482 }
dudmuck 0:8f0d0ae0a077 483
dudmuck 0:8f0d0ae0a077 484 awaiting_mcps_indic = false;
dudmuck 11:4c337f5bbe4c 485 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 11:4c337f5bbe4c 486 grove_led = 0;
dudmuck 10:00997daeb0c0 487 #endif /* SENSORS */
dudmuck 0:8f0d0ae0a077 488
dudmuck 0:8f0d0ae0a077 489 switch( mcpsIndication->McpsIndication )
dudmuck 0:8f0d0ae0a077 490 {
dudmuck 5:c108560af4c3 491 /* this refers to the downlink from gateway, not the uplink that was sent to it */
dudmuck 0:8f0d0ae0a077 492 case MCPS_UNCONFIRMED:
dudmuck 0:8f0d0ae0a077 493 {
dudmuck 1:53c30224eda8 494 isr_printf("UNCONFIRMED ");
dudmuck 0:8f0d0ae0a077 495 break;
dudmuck 0:8f0d0ae0a077 496 }
dudmuck 0:8f0d0ae0a077 497 case MCPS_CONFIRMED:
dudmuck 0:8f0d0ae0a077 498 {
dudmuck 5:c108560af4c3 499 /* downlink has requested Ack */
dudmuck 1:53c30224eda8 500 isr_printf("CONFIRMED ");
dudmuck 0:8f0d0ae0a077 501 break;
dudmuck 0:8f0d0ae0a077 502 }
dudmuck 0:8f0d0ae0a077 503 case MCPS_PROPRIETARY:
dudmuck 0:8f0d0ae0a077 504 {
dudmuck 0:8f0d0ae0a077 505 break;
dudmuck 0:8f0d0ae0a077 506 }
dudmuck 0:8f0d0ae0a077 507 case MCPS_MULTICAST:
dudmuck 0:8f0d0ae0a077 508 {
dudmuck 10:00997daeb0c0 509 isr_printf("MCPS_MULTICAST ");
dudmuck 10:00997daeb0c0 510 if (mcpsIndication->RxData) {
dudmuck 11:4c337f5bbe4c 511 switch (mcpsIndication->Buffer[3]) {
dudmuck 11:4c337f5bbe4c 512 default:
dudmuck 11:4c337f5bbe4c 513 case BCAST_CMD_NONE: break;
dudmuck 11:4c337f5bbe4c 514 case BCAST_CMD_LED_OFF: grove_led = 0; isr_printf("LED_OFF "); break;
dudmuck 11:4c337f5bbe4c 515 case BCAST_CMD_LED_ON: grove_led = 1; isr_printf("LED_ON "); break;
dudmuck 11:4c337f5bbe4c 516 case BCAST_CMD_LED_COUNT:
dudmuck 11:4c337f5bbe4c 517 isr_printf("LED_BLINK ");
dudmuck 11:4c337f5bbe4c 518 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 11:4c337f5bbe4c 519 grove_cnt = mcpsIndication->Buffer[0] - 1;
dudmuck 11:4c337f5bbe4c 520 grove_led = 1;
dudmuck 11:4c337f5bbe4c 521 TxNextPacketTimer.attach_us(&grove_led_cb, RED_LED_RATE_US);
dudmuck 11:4c337f5bbe4c 522 #endif /* SENSORS */
dudmuck 11:4c337f5bbe4c 523 break;
dudmuck 11:4c337f5bbe4c 524 } // ..switch (mcpsIndication->Buffer[3])
dudmuck 10:00997daeb0c0 525 }
dudmuck 0:8f0d0ae0a077 526 break;
dudmuck 0:8f0d0ae0a077 527 }
dudmuck 0:8f0d0ae0a077 528 default:
dudmuck 0:8f0d0ae0a077 529 break;
dudmuck 0:8f0d0ae0a077 530 }
dudmuck 0:8f0d0ae0a077 531
dudmuck 0:8f0d0ae0a077 532 // Check Multicast
dudmuck 0:8f0d0ae0a077 533 // Check Port
dudmuck 0:8f0d0ae0a077 534 // Check Datarate
dudmuck 0:8f0d0ae0a077 535 // Check FramePending
dudmuck 0:8f0d0ae0a077 536 // Check Buffer
dudmuck 0:8f0d0ae0a077 537 // Check BufferSize
dudmuck 0:8f0d0ae0a077 538 // Check Rssi
dudmuck 0:8f0d0ae0a077 539 // Check Snr
dudmuck 0:8f0d0ae0a077 540 // Check RxSlot
dudmuck 0:8f0d0ae0a077 541 LoRaMacDownlinkStatus.Rssi = mcpsIndication->Rssi;
dudmuck 0:8f0d0ae0a077 542 if( mcpsIndication->Snr & 0x80 ) // The SNR sign bit is 1
dudmuck 0:8f0d0ae0a077 543 {
dudmuck 0:8f0d0ae0a077 544 // Invert and divide by 4
dudmuck 0:8f0d0ae0a077 545 LoRaMacDownlinkStatus.Snr = ( ( ~mcpsIndication->Snr + 1 ) & 0xFF ) >> 2;
dudmuck 0:8f0d0ae0a077 546 LoRaMacDownlinkStatus.Snr = -LoRaMacDownlinkStatus.Snr;
dudmuck 0:8f0d0ae0a077 547 }
dudmuck 0:8f0d0ae0a077 548 else
dudmuck 0:8f0d0ae0a077 549 {
dudmuck 0:8f0d0ae0a077 550 // Divide by 4
dudmuck 0:8f0d0ae0a077 551 LoRaMacDownlinkStatus.Snr = ( mcpsIndication->Snr & 0xFF ) >> 2;
dudmuck 0:8f0d0ae0a077 552 }
dudmuck 0:8f0d0ae0a077 553 LoRaMacDownlinkStatus.DownlinkCounter++;
dudmuck 0:8f0d0ae0a077 554 LoRaMacDownlinkStatus.RxData = mcpsIndication->RxData;
dudmuck 0:8f0d0ae0a077 555 LoRaMacDownlinkStatus.Port = mcpsIndication->Port;
dudmuck 0:8f0d0ae0a077 556 LoRaMacDownlinkStatus.Buffer = mcpsIndication->Buffer;
dudmuck 0:8f0d0ae0a077 557 LoRaMacDownlinkStatus.BufferSize = mcpsIndication->BufferSize;
dudmuck 0:8f0d0ae0a077 558
dudmuck 0:8f0d0ae0a077 559 if( mcpsIndication->RxData == true )
dudmuck 0:8f0d0ae0a077 560 {
dudmuck 0:8f0d0ae0a077 561 int i;
dudmuck 1:53c30224eda8 562 isr_printf("RxData %u ", mcpsIndication->BufferSize);
dudmuck 0:8f0d0ae0a077 563 for (i = 0; i < mcpsIndication->BufferSize; i++) {
dudmuck 1:53c30224eda8 564 isr_printf("%02x ", mcpsIndication->Buffer[i]);
dudmuck 0:8f0d0ae0a077 565 }
dudmuck 1:53c30224eda8 566 isr_printf("\r\n");
dudmuck 0:8f0d0ae0a077 567
dudmuck 0:8f0d0ae0a077 568 switch( mcpsIndication->Port )
dudmuck 0:8f0d0ae0a077 569 {
dudmuck 0:8f0d0ae0a077 570 case 1: // The application LED can be controlled on port 1 or 2
dudmuck 0:8f0d0ae0a077 571 case 2:
dudmuck 0:8f0d0ae0a077 572 if( mcpsIndication->BufferSize == 1 )
dudmuck 0:8f0d0ae0a077 573 {
dudmuck 0:8f0d0ae0a077 574 AppLedStateOn = mcpsIndication->Buffer[0] & 0x01;
dudmuck 0:8f0d0ae0a077 575 //Led3StateChanged = true;
dudmuck 0:8f0d0ae0a077 576 }
dudmuck 0:8f0d0ae0a077 577 break;
dudmuck 0:8f0d0ae0a077 578 default:
dudmuck 0:8f0d0ae0a077 579 break;
dudmuck 0:8f0d0ae0a077 580 }
dudmuck 0:8f0d0ae0a077 581 }
dudmuck 0:8f0d0ae0a077 582
dudmuck 1:53c30224eda8 583 isr_printf("\r\n");
dudmuck 0:8f0d0ae0a077 584 }
dudmuck 0:8f0d0ae0a077 585
dudmuck 0:8f0d0ae0a077 586 /*!
dudmuck 0:8f0d0ae0a077 587 * \brief MLME-Confirm event function
dudmuck 0:8f0d0ae0a077 588 *
dudmuck 0:8f0d0ae0a077 589 * \param [IN] mlmeConfirm - Pointer to the confirm structure,
dudmuck 0:8f0d0ae0a077 590 * containing confirm attributes.
dudmuck 0:8f0d0ae0a077 591 */
dudmuck 0:8f0d0ae0a077 592 static void MlmeConfirm( MlmeConfirm_t *mlmeConfirm )
dudmuck 0:8f0d0ae0a077 593 {
dudmuck 1:53c30224eda8 594 isr_printf("MlmeConfirm ");
dudmuck 0:8f0d0ae0a077 595 switch( mlmeConfirm->MlmeRequest )
dudmuck 0:8f0d0ae0a077 596 {
dudmuck 0:8f0d0ae0a077 597 case MLME_JOIN:
dudmuck 0:8f0d0ae0a077 598 {
dudmuck 1:53c30224eda8 599 isr_printf("MLME_JOIN ");
dudmuck 11:4c337f5bbe4c 600 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 11:4c337f5bbe4c 601 grove_led = 0;
dudmuck 10:00997daeb0c0 602 #endif /* SENSORS */
dudmuck 0:8f0d0ae0a077 603 if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
dudmuck 0:8f0d0ae0a077 604 {
dudmuck 0:8f0d0ae0a077 605 // Status is OK, node has joined the network
dudmuck 0:8f0d0ae0a077 606 //DeviceState = DEVICE_STATE_SEND;
dudmuck 0:8f0d0ae0a077 607 DeviceState = DEVICE_STATE_SLEEP;
dudmuck 1:53c30224eda8 608 isr_printf("ok");
dudmuck 2:f2d9aa163652 609 missed_count = 0;
dudmuck 0:8f0d0ae0a077 610 }
dudmuck 0:8f0d0ae0a077 611 else
dudmuck 0:8f0d0ae0a077 612 {
dudmuck 0:8f0d0ae0a077 613 // Join was not successful. Try to join again
dudmuck 0:8f0d0ae0a077 614 DeviceState = DEVICE_STATE_JOIN;
dudmuck 1:53c30224eda8 615 isr_printf("fail");
dudmuck 0:8f0d0ae0a077 616 }
dudmuck 0:8f0d0ae0a077 617 break;
dudmuck 0:8f0d0ae0a077 618 }
dudmuck 0:8f0d0ae0a077 619 case MLME_LINK_CHECK:
dudmuck 0:8f0d0ae0a077 620 {
dudmuck 1:53c30224eda8 621 isr_printf("LINK_CHECK");
dudmuck 0:8f0d0ae0a077 622 if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
dudmuck 0:8f0d0ae0a077 623 {
dudmuck 0:8f0d0ae0a077 624 // Check DemodMargin
dudmuck 0:8f0d0ae0a077 625 //mlmeConfirm->DemodMargin;
dudmuck 0:8f0d0ae0a077 626 // Check NbGateways
dudmuck 0:8f0d0ae0a077 627 //mlmeConfirm->NbGateways;
dudmuck 0:8f0d0ae0a077 628 }
dudmuck 0:8f0d0ae0a077 629 break;
dudmuck 0:8f0d0ae0a077 630 }
dudmuck 0:8f0d0ae0a077 631 default:
dudmuck 0:8f0d0ae0a077 632 break;
dudmuck 0:8f0d0ae0a077 633 }
dudmuck 0:8f0d0ae0a077 634 NextTx = true;
dudmuck 1:53c30224eda8 635 isr_printf("\r\n");
dudmuck 0:8f0d0ae0a077 636 }
dudmuck 0:8f0d0ae0a077 637
dudmuck 0:8f0d0ae0a077 638
dudmuck 0:8f0d0ae0a077 639 static void MlmeIndication( MlmeIndication_t *MlmeIndication )
dudmuck 0:8f0d0ae0a077 640 {
dudmuck 0:8f0d0ae0a077 641 char str[64];
dudmuck 0:8f0d0ae0a077 642 //MibRequestConfirm_t mibReq;
dudmuck 0:8f0d0ae0a077 643
dudmuck 1:53c30224eda8 644 isr_printf("MlmeIndication ");
dudmuck 0:8f0d0ae0a077 645 switch( MlmeIndication->MlmeIndication )
dudmuck 0:8f0d0ae0a077 646 {
dudmuck 0:8f0d0ae0a077 647 case MLME_BEACON:
dudmuck 0:8f0d0ae0a077 648 {
dudmuck 2:f2d9aa163652 649 isr_printf("missed:%u BEACON ", missed_count);
dudmuck 0:8f0d0ae0a077 650 LoRaMacEventInfoStatus_to_string(MlmeIndication->Status, str);
dudmuck 1:53c30224eda8 651 isr_printf("%s ", str);
dudmuck 10:00997daeb0c0 652 //#ifndef MANUAL_UPLINK
dudmuck 0:8f0d0ae0a077 653 if (send_at_beacon) {
dudmuck 0:8f0d0ae0a077 654 TxNextPacketTimer.attach_us(&send_uplink, 100000);
dudmuck 0:8f0d0ae0a077 655 send_at_beacon = false;
dudmuck 0:8f0d0ae0a077 656 }
dudmuck 10:00997daeb0c0 657 //#endif /* !MANUAL_UPLINK */
dudmuck 2:f2d9aa163652 658 if (LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED == MlmeIndication->Status)
dudmuck 2:f2d9aa163652 659 missed_count = 0;
dudmuck 2:f2d9aa163652 660 else if (++missed_count > 4) {
dudmuck 2:f2d9aa163652 661 /* cause re-join */
dudmuck 2:f2d9aa163652 662 MibRequestConfirm_t mibReq;
dudmuck 2:f2d9aa163652 663 mibReq.Type = MIB_NETWORK_JOINED;
dudmuck 2:f2d9aa163652 664 mibReq.Param.IsNetworkJoined = false;
dudmuck 2:f2d9aa163652 665 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 2:f2d9aa163652 666 TxNextPacketTimer.attach_us(&OnTxNextPacketTimerEvent, randr(1000000, 5000000) + 1000000);
dudmuck 2:f2d9aa163652 667 }
dudmuck 0:8f0d0ae0a077 668 break;
dudmuck 0:8f0d0ae0a077 669
dudmuck 0:8f0d0ae0a077 670 }
dudmuck 10:00997daeb0c0 671 case MLME_TXDONE:
dudmuck 10:00997daeb0c0 672 isr_printf("MLME_TXDONE ");
dudmuck 11:4c337f5bbe4c 673 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 11:4c337f5bbe4c 674 grove_led = 1;
dudmuck 10:00997daeb0c0 675 #endif /* SENSORS */
dudmuck 10:00997daeb0c0 676 break;
dudmuck 0:8f0d0ae0a077 677 default:
dudmuck 1:53c30224eda8 678 isr_printf("<%d> ", MlmeIndication->MlmeIndication);
dudmuck 0:8f0d0ae0a077 679 break;
dudmuck 0:8f0d0ae0a077 680 }
dudmuck 0:8f0d0ae0a077 681
dudmuck 1:53c30224eda8 682 isr_printf("\r\n");
dudmuck 0:8f0d0ae0a077 683 }
dudmuck 0:8f0d0ae0a077 684
dudmuck 0:8f0d0ae0a077 685 void
dudmuck 0:8f0d0ae0a077 686 send_pcbuf_uplink()
dudmuck 0:8f0d0ae0a077 687 {
dudmuck 0:8f0d0ae0a077 688 bool ret;
dudmuck 0:8f0d0ae0a077 689 memcpy(AppData, pcbuf, pcbuf_len);
dudmuck 0:8f0d0ae0a077 690 AppDataSize = pcbuf_len;
dudmuck 0:8f0d0ae0a077 691
dudmuck 0:8f0d0ae0a077 692 ret = SendFrame( );
dudmuck 1:53c30224eda8 693 isr_printf("%d = SendFrame()\r\n", ret);
dudmuck 0:8f0d0ae0a077 694 }
dudmuck 0:8f0d0ae0a077 695
dudmuck 10:00997daeb0c0 696
dudmuck 0:8f0d0ae0a077 697 void cmd_status(uint8_t idx)
dudmuck 0:8f0d0ae0a077 698 {
dudmuck 2:f2d9aa163652 699 MibRequestConfirm_t mibReq;
dudmuck 2:f2d9aa163652 700
dudmuck 2:f2d9aa163652 701 isr_printf("DevEUI ");
dudmuck 2:f2d9aa163652 702 for (int i = 0; i < 8; i++)
dudmuck 2:f2d9aa163652 703 isr_printf("%02x ", DevEui[i]);
dudmuck 2:f2d9aa163652 704 mibReq.Type = MIB_DEV_ADDR;
dudmuck 2:f2d9aa163652 705 LoRaMacMibGetRequestConfirm( &mibReq );
dudmuck 2:f2d9aa163652 706 isr_printf(", DevAddr:%x\r\n", mibReq.Param.DevAddr);
dudmuck 2:f2d9aa163652 707
dudmuck 11:4c337f5bbe4c 708 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 10:00997daeb0c0 709 //printf("button:%d,%u water:%f ", button.read(), button_cnt, water.read());
dudmuck 10:00997daeb0c0 710 printf("button:%d,%u water:%d jumper:%d ", button.read(), button_cnt, water.read(), jumper_in.read());
dudmuck 10:00997daeb0c0 711 #endif
dudmuck 1:53c30224eda8 712 isr_printf("DeviceState:%d\r\n", DeviceState);
dudmuck 1:53c30224eda8 713 isr_printf("send_at_beacon:%d\r\n", send_at_beacon);
dudmuck 1:53c30224eda8 714 isr_printf("awaiting_mcps_indic:%d\r\n", awaiting_mcps_indic);
dudmuck 0:8f0d0ae0a077 715 loramac_print_status();
dudmuck 10:00997daeb0c0 716
dudmuck 0:8f0d0ae0a077 717 }
dudmuck 0:8f0d0ae0a077 718
dudmuck 0:8f0d0ae0a077 719 void cmd_uplink_length(uint8_t idx)
dudmuck 0:8f0d0ae0a077 720 {
dudmuck 0:8f0d0ae0a077 721 if (pcbuf[idx] >= '0' && pcbuf[idx] <= '9') {
dudmuck 0:8f0d0ae0a077 722 sscanf(pcbuf+idx, "%u", &uplink_length);
dudmuck 0:8f0d0ae0a077 723 }
dudmuck 1:53c30224eda8 724 isr_printf("uplink_length:%u\r\n", uplink_length);
dudmuck 0:8f0d0ae0a077 725 }
dudmuck 0:8f0d0ae0a077 726
dudmuck 11:4c337f5bbe4c 727 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 10:00997daeb0c0 728 void cmd_sensor(uint8_t idx)
dudmuck 10:00997daeb0c0 729 {
dudmuck 10:00997daeb0c0 730 int current_quality = airqualitysensor.slope();
dudmuck 10:00997daeb0c0 731 if (current_quality >= 0) { // if a valid data returned.
dudmuck 10:00997daeb0c0 732 if (current_quality == 0)
dudmuck 10:00997daeb0c0 733 isr_printf("High pollution! Force signal active\n\r");
dudmuck 10:00997daeb0c0 734 else if (current_quality == 1)
dudmuck 10:00997daeb0c0 735 isr_printf("High pollution!\n\r");
dudmuck 10:00997daeb0c0 736 else if (current_quality == 2)
dudmuck 10:00997daeb0c0 737 isr_printf("Low pollution!\n\r");
dudmuck 10:00997daeb0c0 738 else if (current_quality == 3)
dudmuck 10:00997daeb0c0 739 isr_printf("Fresh air\n\r");
dudmuck 10:00997daeb0c0 740 }
dudmuck 10:00997daeb0c0 741 }
dudmuck 10:00997daeb0c0 742
dudmuck 10:00997daeb0c0 743 void cmd_red_led(uint8_t idx)
dudmuck 10:00997daeb0c0 744 {
dudmuck 11:4c337f5bbe4c 745 grove_led = !grove_led;
dudmuck 11:4c337f5bbe4c 746 printf("red_led:%u\r\n", grove_led.read());
dudmuck 10:00997daeb0c0 747 }
dudmuck 10:00997daeb0c0 748
dudmuck 10:00997daeb0c0 749 void cmd_water_pull(uint8_t idx)
dudmuck 10:00997daeb0c0 750 {
dudmuck 10:00997daeb0c0 751 printf("water pull:");
dudmuck 10:00997daeb0c0 752 if (pcbuf[idx] == 'u') {
dudmuck 10:00997daeb0c0 753 water.mode(PullUp);
dudmuck 10:00997daeb0c0 754 printf("up");
dudmuck 10:00997daeb0c0 755 }else if (pcbuf[idx] == 'n') {
dudmuck 10:00997daeb0c0 756 water.mode(PullNone);
dudmuck 10:00997daeb0c0 757 printf("none");
dudmuck 10:00997daeb0c0 758 } else if (pcbuf[idx] == 'd') {
dudmuck 10:00997daeb0c0 759 water.mode(PullDown);
dudmuck 10:00997daeb0c0 760 printf("down");
dudmuck 10:00997daeb0c0 761 } else if (pcbuf[idx] == 'o') {
dudmuck 10:00997daeb0c0 762 water.mode(OpenDrain);
dudmuck 10:00997daeb0c0 763 printf("od");
dudmuck 10:00997daeb0c0 764 }
dudmuck 10:00997daeb0c0 765 printf("\r\n");
dudmuck 10:00997daeb0c0 766 }
dudmuck 10:00997daeb0c0 767
dudmuck 10:00997daeb0c0 768 void cmd_led_flash(uint8_t idx)
dudmuck 10:00997daeb0c0 769 {
dudmuck 10:00997daeb0c0 770 if (pcbuf[idx] >= '0' && pcbuf[idx] <= '9') {
dudmuck 11:4c337f5bbe4c 771 sscanf(pcbuf+idx, "%u", &grove_cnt);
dudmuck 11:4c337f5bbe4c 772 if (grove_cnt > 0) {
dudmuck 11:4c337f5bbe4c 773 grove_cnt--;
dudmuck 11:4c337f5bbe4c 774 grove_led = 1;
dudmuck 11:4c337f5bbe4c 775 TxNextPacketTimer.attach_us(&grove_led_cb, RED_LED_RATE_US);
dudmuck 10:00997daeb0c0 776 }
dudmuck 10:00997daeb0c0 777 }
dudmuck 10:00997daeb0c0 778 }
dudmuck 10:00997daeb0c0 779 #endif /* SENSORS */
dudmuck 10:00997daeb0c0 780
dudmuck 0:8f0d0ae0a077 781 typedef struct {
dudmuck 0:8f0d0ae0a077 782 const char* const cmd;
dudmuck 0:8f0d0ae0a077 783 void (*handler)(uint8_t args_at);
dudmuck 0:8f0d0ae0a077 784 const char* const arg_descr;
dudmuck 0:8f0d0ae0a077 785 const char* const description;
dudmuck 0:8f0d0ae0a077 786 } menu_item_t;
dudmuck 0:8f0d0ae0a077 787
dudmuck 0:8f0d0ae0a077 788 void cmd_help(uint8_t args_at);
dudmuck 0:8f0d0ae0a077 789
dudmuck 0:8f0d0ae0a077 790 const menu_item_t menu_items[] =
dudmuck 0:8f0d0ae0a077 791 { /* after first character, command names must be [A-Za-z] */
dudmuck 0:8f0d0ae0a077 792 { "?", cmd_help, "","show available commands"},
dudmuck 0:8f0d0ae0a077 793 { ".", cmd_status, "","print status"},
dudmuck 10:00997daeb0c0 794 { "ul", cmd_uplink_length, "%u","set uplink payload length"},
dudmuck 11:4c337f5bbe4c 795 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 10:00997daeb0c0 796 { "s", cmd_sensor, "","read sensor"},
dudmuck 10:00997daeb0c0 797 { "l", cmd_red_led, "","toggle red LED"},
dudmuck 10:00997daeb0c0 798 { "w", cmd_water_pull, "%c","config water pull: u,d,n,o"},
dudmuck 10:00997daeb0c0 799 { "f", cmd_led_flash, "%d","flash LED n times"},
dudmuck 10:00997daeb0c0 800 #endif
dudmuck 0:8f0d0ae0a077 801 { NULL, NULL, NULL, NULL }
dudmuck 0:8f0d0ae0a077 802 };
dudmuck 0:8f0d0ae0a077 803
dudmuck 0:8f0d0ae0a077 804 void cmd_help(uint8_t args_at)
dudmuck 0:8f0d0ae0a077 805 {
dudmuck 0:8f0d0ae0a077 806 int i;
dudmuck 0:8f0d0ae0a077 807
dudmuck 0:8f0d0ae0a077 808 for (i = 0; menu_items[i].cmd != NULL ; i++) {
dudmuck 1:53c30224eda8 809 isr_printf("%s%s\t%s\r\n", menu_items[i].cmd, menu_items[i].arg_descr, menu_items[i].description);
dudmuck 0:8f0d0ae0a077 810 }
dudmuck 0:8f0d0ae0a077 811
dudmuck 0:8f0d0ae0a077 812 }
dudmuck 0:8f0d0ae0a077 813
dudmuck 0:8f0d0ae0a077 814 void
dudmuck 0:8f0d0ae0a077 815 console()
dudmuck 0:8f0d0ae0a077 816 {
dudmuck 0:8f0d0ae0a077 817 bool parsed;
dudmuck 0:8f0d0ae0a077 818 int i;
dudmuck 0:8f0d0ae0a077 819 uint8_t user_cmd_len;
dudmuck 0:8f0d0ae0a077 820
dudmuck 0:8f0d0ae0a077 821 if (pcbuf_len < 0) { // ctrl-C
dudmuck 1:53c30224eda8 822 //isr_printf("abort\r\n");
dudmuck 0:8f0d0ae0a077 823 return;
dudmuck 0:8f0d0ae0a077 824 }
dudmuck 0:8f0d0ae0a077 825 if (pcbuf_len == 0)
dudmuck 0:8f0d0ae0a077 826 return;
dudmuck 0:8f0d0ae0a077 827
dudmuck 1:53c30224eda8 828 isr_printf("\r\n");
dudmuck 0:8f0d0ae0a077 829
dudmuck 0:8f0d0ae0a077 830 /* get end of user-entered command */
dudmuck 0:8f0d0ae0a077 831 user_cmd_len = 1; // first character can be any character
dudmuck 0:8f0d0ae0a077 832 for (i = 1; i <= pcbuf_len; i++) {
dudmuck 0:8f0d0ae0a077 833 if (pcbuf[i] < 'A' || (pcbuf[i] > 'Z' && pcbuf[i] < 'a') || pcbuf[i] > 'z') {
dudmuck 0:8f0d0ae0a077 834 user_cmd_len = i;
dudmuck 0:8f0d0ae0a077 835 break;
dudmuck 0:8f0d0ae0a077 836 }
dudmuck 0:8f0d0ae0a077 837 }
dudmuck 0:8f0d0ae0a077 838
dudmuck 0:8f0d0ae0a077 839 parsed = false;
dudmuck 0:8f0d0ae0a077 840 for (i = 0; menu_items[i].cmd != NULL ; i++) {
dudmuck 0:8f0d0ae0a077 841 int mi_len = strlen(menu_items[i].cmd);
dudmuck 0:8f0d0ae0a077 842
dudmuck 0:8f0d0ae0a077 843 if (menu_items[i].handler && user_cmd_len == mi_len && (strncmp(pcbuf, menu_items[i].cmd, mi_len) == 0)) {
dudmuck 0:8f0d0ae0a077 844 while (pcbuf[mi_len] == ' ') // skip past spaces
dudmuck 0:8f0d0ae0a077 845 mi_len++;
dudmuck 0:8f0d0ae0a077 846 menu_items[i].handler(mi_len);
dudmuck 0:8f0d0ae0a077 847 parsed = true;
dudmuck 0:8f0d0ae0a077 848 break;
dudmuck 0:8f0d0ae0a077 849 }
dudmuck 0:8f0d0ae0a077 850 }
dudmuck 0:8f0d0ae0a077 851
dudmuck 0:8f0d0ae0a077 852 if (!parsed)
dudmuck 0:8f0d0ae0a077 853 send_pcbuf_uplink();
dudmuck 0:8f0d0ae0a077 854
dudmuck 0:8f0d0ae0a077 855 pcbuf_len = 0;
dudmuck 1:53c30224eda8 856 isr_printf("> ");
dudmuck 0:8f0d0ae0a077 857 fflush(stdout);
dudmuck 0:8f0d0ae0a077 858 }
dudmuck 0:8f0d0ae0a077 859
dudmuck 0:8f0d0ae0a077 860 void rx_callback()
dudmuck 0:8f0d0ae0a077 861 {
dudmuck 0:8f0d0ae0a077 862 static uint8_t pcbuf_idx = 0;
dudmuck 0:8f0d0ae0a077 863 static uint8_t prev_len = 0;;
dudmuck 0:8f0d0ae0a077 864 char c = pc.getc();
dudmuck 0:8f0d0ae0a077 865
dudmuck 0:8f0d0ae0a077 866 if (c == 8) {
dudmuck 0:8f0d0ae0a077 867 if (pcbuf_idx > 0) {
dudmuck 0:8f0d0ae0a077 868 pc.putc(8);
dudmuck 0:8f0d0ae0a077 869 pc.putc(' ');
dudmuck 0:8f0d0ae0a077 870 pc.putc(8);
dudmuck 0:8f0d0ae0a077 871 pcbuf_idx--;
dudmuck 0:8f0d0ae0a077 872 }
dudmuck 0:8f0d0ae0a077 873 } else if (c == 3) { // ctrl-C
dudmuck 0:8f0d0ae0a077 874 pcbuf_len = -1;
dudmuck 0:8f0d0ae0a077 875 } else if (c == '\r') {
dudmuck 0:8f0d0ae0a077 876 if (pcbuf_idx == 0) {
dudmuck 0:8f0d0ae0a077 877 pcbuf_len = prev_len;
dudmuck 0:8f0d0ae0a077 878 } else {
dudmuck 0:8f0d0ae0a077 879 pcbuf[pcbuf_idx] = 0; // null terminate
dudmuck 0:8f0d0ae0a077 880 prev_len = pcbuf_idx;
dudmuck 0:8f0d0ae0a077 881 pcbuf_idx = 0;
dudmuck 0:8f0d0ae0a077 882 pcbuf_len = prev_len;
dudmuck 0:8f0d0ae0a077 883 }
dudmuck 0:8f0d0ae0a077 884 } else if (pcbuf_idx < sizeof(pcbuf)) {
dudmuck 0:8f0d0ae0a077 885 pcbuf[pcbuf_idx++] = c;
dudmuck 0:8f0d0ae0a077 886 pc.putc(c);
dudmuck 0:8f0d0ae0a077 887 }
dudmuck 0:8f0d0ae0a077 888 }
dudmuck 0:8f0d0ae0a077 889
dudmuck 11:4c337f5bbe4c 890 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 10:00997daeb0c0 891 // Interrupt Handler
dudmuck 10:00997daeb0c0 892 void AirQualityInterrupt()
dudmuck 10:00997daeb0c0 893 {
dudmuck 10:00997daeb0c0 894 AnalogIn sensor(analogPin);
dudmuck 10:00997daeb0c0 895 airqualitysensor.last_vol = airqualitysensor.first_vol;
dudmuck 10:00997daeb0c0 896 airqualitysensor.first_vol = sensor.read()*1000;
dudmuck 10:00997daeb0c0 897 airqualitysensor.timer_index = 1;
dudmuck 10:00997daeb0c0 898 }
dudmuck 10:00997daeb0c0 899
dudmuck 10:00997daeb0c0 900 void button_isr()
dudmuck 10:00997daeb0c0 901 {
dudmuck 10:00997daeb0c0 902 button_cnt++;
dudmuck 10:00997daeb0c0 903 isr_printf("button_isr\r\n");
dudmuck 10:00997daeb0c0 904 if (!jumper_in.read()) {
dudmuck 10:00997daeb0c0 905 /* jumper not installed: manual uplink */
dudmuck 10:00997daeb0c0 906 send_uplink();
dudmuck 10:00997daeb0c0 907 }
dudmuck 10:00997daeb0c0 908 }
dudmuck 10:00997daeb0c0 909 #endif /* SENSORS */
dudmuck 10:00997daeb0c0 910
dudmuck 10:00997daeb0c0 911
dudmuck 0:8f0d0ae0a077 912 /**
dudmuck 0:8f0d0ae0a077 913 * Main application entry point.
dudmuck 0:8f0d0ae0a077 914 */
dudmuck 0:8f0d0ae0a077 915 int main( void )
dudmuck 0:8f0d0ae0a077 916 {
dudmuck 0:8f0d0ae0a077 917 LoRaMacPrimitives_t LoRaMacPrimitives;
dudmuck 0:8f0d0ae0a077 918 LoRaMacCallback_t LoRaMacCallbacks;
dudmuck 0:8f0d0ae0a077 919 MibRequestConfirm_t mibReq;
dudmuck 0:8f0d0ae0a077 920
dudmuck 4:d9201410c87b 921 pc.baud(38400);
dudmuck 7:e238827f0e47 922 pc.attach(&rx_callback);
dudmuck 1:53c30224eda8 923 isr_printf("\r\nreset\r\n");
dudmuck 10:00997daeb0c0 924
dudmuck 10:00997daeb0c0 925 BoardInit( );
dudmuck 10:00997daeb0c0 926
dudmuck 0:8f0d0ae0a077 927 DeviceState = DEVICE_STATE_INIT;
dudmuck 10:00997daeb0c0 928
dudmuck 11:4c337f5bbe4c 929 #if defined(SENSORS) && defined(ENABLE_SX1272)
dudmuck 10:00997daeb0c0 930 airqualitysensor.init(analogPin, AirQualityInterrupt);
dudmuck 10:00997daeb0c0 931 if (button) {
dudmuck 10:00997daeb0c0 932 button.rise(&button_isr);
dudmuck 10:00997daeb0c0 933 printf("button-rise\r\n");
dudmuck 10:00997daeb0c0 934 } else {
dudmuck 10:00997daeb0c0 935 button.rise(&button_isr);
dudmuck 10:00997daeb0c0 936 printf("button-fall\r\n");
dudmuck 10:00997daeb0c0 937 }
dudmuck 10:00997daeb0c0 938 //water.mode(PullNone);
dudmuck 10:00997daeb0c0 939 water.mode(PullUp);
dudmuck 10:00997daeb0c0 940 #endif
dudmuck 10:00997daeb0c0 941
dudmuck 10:00997daeb0c0 942 jumper_out = 1;
dudmuck 10:00997daeb0c0 943 jumper_in.mode(PullDown);
dudmuck 0:8f0d0ae0a077 944
dudmuck 0:8f0d0ae0a077 945 while( 1 )
dudmuck 0:8f0d0ae0a077 946 {
dudmuck 0:8f0d0ae0a077 947 console();
dudmuck 0:8f0d0ae0a077 948
dudmuck 0:8f0d0ae0a077 949 switch( DeviceState )
dudmuck 0:8f0d0ae0a077 950 {
dudmuck 0:8f0d0ae0a077 951 case DEVICE_STATE_INIT:
dudmuck 0:8f0d0ae0a077 952 {
dudmuck 1:53c30224eda8 953 isr_printf("DEVICE_STATE_INIT\r\n");
dudmuck 0:8f0d0ae0a077 954 uplink_length = 2;
dudmuck 0:8f0d0ae0a077 955 LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
dudmuck 0:8f0d0ae0a077 956 LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
dudmuck 0:8f0d0ae0a077 957 LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
dudmuck 0:8f0d0ae0a077 958 LoRaMacPrimitives.MacMlmeIndication = MlmeIndication;
dudmuck 0:8f0d0ae0a077 959 LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
dudmuck 0:8f0d0ae0a077 960 if (LORAMAC_STATUS_OK != LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks )) {
dudmuck 1:53c30224eda8 961 isr_printf("LoRaMacInitialization() failed\r\n");
dudmuck 0:8f0d0ae0a077 962 for (;;) ;
dudmuck 0:8f0d0ae0a077 963 }
dudmuck 1:53c30224eda8 964 isr_printf("INIT-ok\r\n");
dudmuck 0:8f0d0ae0a077 965
dudmuck 0:8f0d0ae0a077 966 mibReq.Type = MIB_PUBLIC_NETWORK;
dudmuck 0:8f0d0ae0a077 967 mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK;
dudmuck 0:8f0d0ae0a077 968 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 969
dudmuck 0:8f0d0ae0a077 970 LoRaMacDownlinkStatus.DownlinkCounter = 0;
dudmuck 0:8f0d0ae0a077 971
dudmuck 0:8f0d0ae0a077 972 DeviceState = DEVICE_STATE_JOIN;
dudmuck 0:8f0d0ae0a077 973 break;
dudmuck 0:8f0d0ae0a077 974 }
dudmuck 0:8f0d0ae0a077 975 case DEVICE_STATE_JOIN:
dudmuck 0:8f0d0ae0a077 976 {
dudmuck 10:00997daeb0c0 977 if (jumper_in.read()) /* if jumper installed: auto uplink */
dudmuck 10:00997daeb0c0 978 send_at_beacon = true;
dudmuck 0:8f0d0ae0a077 979 #if( OVER_THE_AIR_ACTIVATION != 0 )
dudmuck 0:8f0d0ae0a077 980 MlmeReq_t mlmeReq;
dudmuck 0:8f0d0ae0a077 981 // override software definition with hardware value
dudmuck 0:8f0d0ae0a077 982 BoardGetUniqueId(DevEui);
dudmuck 1:53c30224eda8 983 isr_printf("DevEUI ");
dudmuck 0:8f0d0ae0a077 984 for (int i = 0; i < 8; i++)
dudmuck 1:53c30224eda8 985 isr_printf("%02x ", DevEui[i]);
dudmuck 1:53c30224eda8 986 isr_printf("\r\n");
dudmuck 0:8f0d0ae0a077 987
dudmuck 0:8f0d0ae0a077 988 mlmeReq.Type = MLME_JOIN;
dudmuck 0:8f0d0ae0a077 989
dudmuck 0:8f0d0ae0a077 990 mlmeReq.Req.Join.DevEui = DevEui;
dudmuck 0:8f0d0ae0a077 991 mlmeReq.Req.Join.AppEui = AppEui;
dudmuck 0:8f0d0ae0a077 992 mlmeReq.Req.Join.AppKey = AppKey;
dudmuck 0:8f0d0ae0a077 993 mlmeReq.Req.Join.NbTrials = 255;
dudmuck 0:8f0d0ae0a077 994
dudmuck 0:8f0d0ae0a077 995 if( NextTx == true )
dudmuck 0:8f0d0ae0a077 996 {
dudmuck 0:8f0d0ae0a077 997 LoRaMacMlmeRequest( &mlmeReq );
dudmuck 0:8f0d0ae0a077 998 }
dudmuck 0:8f0d0ae0a077 999 DeviceState = DEVICE_STATE_SLEEP;
dudmuck 0:8f0d0ae0a077 1000 #else
dudmuck 0:8f0d0ae0a077 1001 mibReq.Type = MIB_NET_ID;
dudmuck 0:8f0d0ae0a077 1002 mibReq.Param.NetID = LORAWAN_NETWORK_ID;
dudmuck 0:8f0d0ae0a077 1003 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1004
dudmuck 0:8f0d0ae0a077 1005 mibReq.Type = MIB_DEV_ADDR;
dudmuck 0:8f0d0ae0a077 1006 mibReq.Param.DevAddr = DevAddr;
dudmuck 0:8f0d0ae0a077 1007 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1008
dudmuck 0:8f0d0ae0a077 1009 mibReq.Type = MIB_NWK_SKEY;
dudmuck 0:8f0d0ae0a077 1010 mibReq.Param.NwkSKey = NwkSKey;
dudmuck 0:8f0d0ae0a077 1011 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1012
dudmuck 0:8f0d0ae0a077 1013 mibReq.Type = MIB_APP_SKEY;
dudmuck 0:8f0d0ae0a077 1014 mibReq.Param.AppSKey = AppSKey;
dudmuck 0:8f0d0ae0a077 1015 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1016
dudmuck 0:8f0d0ae0a077 1017 mibReq.Type = MIB_NETWORK_JOINED;
dudmuck 0:8f0d0ae0a077 1018 mibReq.Param.IsNetworkJoined = true;
dudmuck 0:8f0d0ae0a077 1019 LoRaMacMibSetRequestConfirm( &mibReq );
dudmuck 0:8f0d0ae0a077 1020
dudmuck 0:8f0d0ae0a077 1021 DeviceState = DEVICE_STATE_SEND;
dudmuck 0:8f0d0ae0a077 1022 #endif
dudmuck 0:8f0d0ae0a077 1023 break;
dudmuck 0:8f0d0ae0a077 1024 }
dudmuck 0:8f0d0ae0a077 1025 case DEVICE_STATE_SEND:
dudmuck 0:8f0d0ae0a077 1026 {
dudmuck 0:8f0d0ae0a077 1027 if( NextTx == true )
dudmuck 0:8f0d0ae0a077 1028 {
dudmuck 0:8f0d0ae0a077 1029 PrepareTxFrame( AppPort );
dudmuck 0:8f0d0ae0a077 1030
dudmuck 0:8f0d0ae0a077 1031 NextTx = SendFrame( );
dudmuck 0:8f0d0ae0a077 1032 }
dudmuck 2:f2d9aa163652 1033
dudmuck 0:8f0d0ae0a077 1034 // Schedule next packet transmission
dudmuck 0:8f0d0ae0a077 1035 TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
dudmuck 2:f2d9aa163652 1036 DeviceState = DEVICE_STATE_SLEEP;
dudmuck 0:8f0d0ae0a077 1037 break;
dudmuck 0:8f0d0ae0a077 1038 }
dudmuck 0:8f0d0ae0a077 1039 case DEVICE_STATE_CYCLE:
dudmuck 0:8f0d0ae0a077 1040 {
dudmuck 0:8f0d0ae0a077 1041 DeviceState = DEVICE_STATE_SLEEP;
dudmuck 0:8f0d0ae0a077 1042
dudmuck 0:8f0d0ae0a077 1043 // Schedule next packet transmission
dudmuck 0:8f0d0ae0a077 1044 TxNextPacketTimer.attach_us(&OnTxNextPacketTimerEvent, TxDutyCycleTime * 1000);
dudmuck 0:8f0d0ae0a077 1045 break;
dudmuck 0:8f0d0ae0a077 1046 }
dudmuck 0:8f0d0ae0a077 1047 case DEVICE_STATE_SLEEP:
dudmuck 0:8f0d0ae0a077 1048 {
dudmuck 1:53c30224eda8 1049 //isr_printf("sleep %u\r\n", queue.tick());
dudmuck 0:8f0d0ae0a077 1050 // Wake up through events
dudmuck 0:8f0d0ae0a077 1051 break;
dudmuck 0:8f0d0ae0a077 1052 }
dudmuck 0:8f0d0ae0a077 1053 default:
dudmuck 0:8f0d0ae0a077 1054 {
dudmuck 0:8f0d0ae0a077 1055 DeviceState = DEVICE_STATE_INIT;
dudmuck 0:8f0d0ae0a077 1056 break;
dudmuck 0:8f0d0ae0a077 1057 }
dudmuck 0:8f0d0ae0a077 1058 }
dudmuck 1:53c30224eda8 1059
dudmuck 1:53c30224eda8 1060 bottom_half();
dudmuck 1:53c30224eda8 1061
dudmuck 1:53c30224eda8 1062 } // ..while( 1 )
dudmuck 0:8f0d0ae0a077 1063 }