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 Jul 10 21:54:08 2017 +0000
Revision:
14:7ac0add1123e
Parent:
12:ed33c53afcaf
Child:
15:9023bf4cf168
application layer: for sensors use uplink_length

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