Senet network coverage survey tool

Dependencies:   GeoPosition Senet_Packet lib_gps lib_mma8451q lib_mpl3115a2 lib_sx9500 lmic_MOTE_L152RC mbed-src

Senet Network Coverage Program

Test Senet Network coverage with various data rates and transmit powers

/media/uploads/shaunkrnelson/norammote.jpg

Configure Device ID and App Key

For your device to connect to the Senet Network, set Device ID and App Key in Commissioning.h

Commissioning.h

/* CHANGE: Device ID  registered to your Developer Portal account */
 u1_t reverse_DEVEUI[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 

/* CHANGE: Device App Key. To get this select the device, click on Gear button at top left then select Device Edit */  
u1_t DEVKEY[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
                                                                        
/*NOCHANGE: Senet Developer Portal Application ID */ 
 u1_t reverse_APPEUI[8]={0x00,0x25,0x0C,0x00,0x00,0x01,0x00,0x01};
 

Connecting to the Senet Network

When the device is turned on the USR LED will blink while it is joining the Senet Network. When LED state changes to solid green it has joined the network. Failure to join network will be the result of:

  1. No network coverage in that area
  2. App Key configuration is incorrect

Siting Mode

The device is in Siting test mode when positioned vertically with LEDs facing up. The Siting test consists of transmitting Senet GPS packets with acknowledgment requested at transmit power levels 14, 20, 30 in that order. For each power level the device will attempt 3 transmits at DR0, stopping if ack is received and moving on to next tx power. After first run through all powers at DR0 the test will stop if acknowledgements received at all power levels; otherwise, the test will proceed to alternate between 3 transmits at DR4 and 3 at DR0 for remaining unacknowledged tx powers until ack received.

Siting LED Profile

  1. USR
    1. Blink fast while joining
    2. Solid when joined and GPS lock
    3. Blink slow when not GPS lock
  1. RED
    1. 30 dBm status indicator
    2. Blink on transmit
    3. Solid after downlink received
  1. YELLOW
    1. 20 dBm status indicator
    2. Blink on transmit
    3. Solid after ack received
  1. GREEN
    1. 14 dBm status indicator
    2. Blink on transmit
    3. Solid after downlink received

Range Mode

The device is in this mode when not in the siting orientation.
This test consists of transmitting 8 packets at:

  1. DR3 Tx Power 14
  2. DR0 Tx Power 14
  3. DR4 Tx Power 20
  4. DR3 Tx Power 20
  5. DR0 Tx Power 20
  6. DR4 Tx Power 26
  7. DR3 Tx Power 30
  8. DR0 Tx Power 30

After transmit cycle completes the next test will start in 560 seconds unless following:

  1. After 140 seconds if no ack received
  2. After 80 seconds if 30 meters travelled from last transmit location

Range LED Profile

  • USR
    • Blink fast while joining
    • Solid when joined and GPS lock
    • Blink slow when not GPS locked
  • RED
    • Transmit indicator
    • Blink on transmit
  • YELLOW
    • Ack indicator
    • Set at beginning of transmit cycle and cleared when ack received
  • GREEN
    • V3 Mote
      • Test indicator
      • Solid while test transmit cycle in progress
    • V2 Mote
      • Not controllable by firmware

Switching Mode

Set mote orientation to desired mode. After a few seconds the new orientation will be detected and the device will indicate it is switching mode by blinking the red, yellow and green LEDs simultaneously for a couple seconds before switching to the new mode.

Committer:
shaunkrnelson
Date:
Thu Apr 21 11:13:49 2016 -0400
Revision:
1:fbf2fb2c2718
Parent:
0:46990814dc89
Child:
2:b9b2840d0d8b
Send self-id packets when gps coordinates are unknown

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shaunkrnelson 0:46990814dc89 1 #include "mbed.h"
shaunkrnelson 0:46990814dc89 2 #include "lmic.h"
shaunkrnelson 0:46990814dc89 3 #include "debug.h"
shaunkrnelson 0:46990814dc89 4 #include "gps.h"
shaunkrnelson 0:46990814dc89 5 #include "mpl3115a2.h"
shaunkrnelson 0:46990814dc89 6 #include "mma8451q.h"
shaunkrnelson 0:46990814dc89 7 #include "sx9500.h"
shaunkrnelson 0:46990814dc89 8 #include "GeoPosition.h"
shaunkrnelson 0:46990814dc89 9 #include "senet_packet.h"
shaunkrnelson 0:46990814dc89 10
shaunkrnelson 1:fbf2fb2c2718 11 #define NORAM_MOTE_DEVICE_TYPE 0x786531
shaunkrnelson 0:46990814dc89 12
shaunkrnelson 1:fbf2fb2c2718 13 // Automatically generated by the program_device script
shaunkrnelson 1:fbf2fb2c2718 14 #include "Commissioning.h"
shaunkrnelson 1:fbf2fb2c2718 15 NORAM_MOTE_DEVICE_TYPE 0x786532
shaunkrnelson 1:fbf2fb2c2718 16 #define MAJOR 1
shaunkrnelson 1:fbf2fb2c2718 17 #define MINOR 1
shaunkrnelson 1:fbf2fb2c2718 18 #define POINT 1
shaunkrnelson 1:fbf2fb2c2718 19 #define BUILD_NUMBER 0
shaunkrnelson 1:fbf2fb2c2718 20 #define DEVELOPER_ID 0
shaunkrnelson 0:46990814dc89 21
shaunkrnelson 0:46990814dc89 22
shaunkrnelson 0:46990814dc89 23
shaunkrnelson 0:46990814dc89 24 // provide application router ID (8 bytes, LSBF)
shaunkrnelson 0:46990814dc89 25 void os_getArtEui (u1_t* buf) {
shaunkrnelson 0:46990814dc89 26 //memcpy(buf, APPEUI, 8);
shaunkrnelson 0:46990814dc89 27 LMIC_reverse_memcpy(buf, reverse_APPEUI, 8);
shaunkrnelson 0:46990814dc89 28 }
shaunkrnelson 0:46990814dc89 29
shaunkrnelson 0:46990814dc89 30 // provide device ID (8 bytes, LSBF)
shaunkrnelson 0:46990814dc89 31 void os_getDevEui (u1_t* buf) {
shaunkrnelson 0:46990814dc89 32 //memcpy(buf, DEVEUI, 8);
shaunkrnelson 0:46990814dc89 33 LMIC_reverse_memcpy(buf, reverse_DEVEUI, 8);
shaunkrnelson 0:46990814dc89 34 }
shaunkrnelson 0:46990814dc89 35
shaunkrnelson 0:46990814dc89 36 // provide device key (16 bytes)
shaunkrnelson 0:46990814dc89 37 void os_getDevKey (u1_t* buf) {
shaunkrnelson 0:46990814dc89 38 memcpy(buf, DEVKEY, 16);
shaunkrnelson 0:46990814dc89 39 }
shaunkrnelson 0:46990814dc89 40
shaunkrnelson 0:46990814dc89 41 typedef enum {
shaunkrnelson 0:46990814dc89 42 MOTE_NONE = 0,
shaunkrnelson 0:46990814dc89 43 MOTE_V2,
shaunkrnelson 0:46990814dc89 44 MOTE_V3
shaunkrnelson 0:46990814dc89 45 } mote_version_e;
shaunkrnelson 0:46990814dc89 46
shaunkrnelson 0:46990814dc89 47 /***********************************************************************
shaunkrnelson 0:46990814dc89 48 * END LORA Device configuration
shaunkrnelson 0:46990814dc89 49 ***********************************************************************/
shaunkrnelson 0:46990814dc89 50
shaunkrnelson 0:46990814dc89 51 // Following is peripheral configuration
shaunkrnelson 0:46990814dc89 52 GPS gps(PB_6, PB_7, PB_11);
shaunkrnelson 0:46990814dc89 53 GeoPosition lastTxPos;
shaunkrnelson 0:46990814dc89 54
shaunkrnelson 0:46990814dc89 55 // I2C Bus connecting sensors
shaunkrnelson 0:46990814dc89 56 I2C i2c(I2C_SDA, I2C_SCL);
shaunkrnelson 0:46990814dc89 57 DigitalIn i2c_int_pin(PB_4);
shaunkrnelson 0:46990814dc89 58
shaunkrnelson 0:46990814dc89 59 // Accelerometer
shaunkrnelson 0:46990814dc89 60 MMA8451Q mma8451q(i2c, i2c_int_pin);
shaunkrnelson 0:46990814dc89 61 // Altimeter
shaunkrnelson 0:46990814dc89 62 MPL3115A2 mpl3115a2(i2c, i2c_int_pin);
shaunkrnelson 0:46990814dc89 63 // Proximity sensor
shaunkrnelson 0:46990814dc89 64 SX9500 sx9500(i2c, PA_9, PA_10);
shaunkrnelson 0:46990814dc89 65
shaunkrnelson 0:46990814dc89 66 // Applicative transmit datarate
shaunkrnelson 0:46990814dc89 67 u1_t dr = 0;
shaunkrnelson 0:46990814dc89 68 // Applicative transmit power
shaunkrnelson 0:46990814dc89 69 u1_t pw = 0;
shaunkrnelson 0:46990814dc89 70
shaunkrnelson 0:46990814dc89 71 // LEDs
shaunkrnelson 0:46990814dc89 72 #define LED_RED PB_1
shaunkrnelson 0:46990814dc89 73 #define LED_YEL PB_10
shaunkrnelson 0:46990814dc89 74 #define LED_GREEN PC_3
shaunkrnelson 0:46990814dc89 75 #define LED_USR PA_5
shaunkrnelson 0:46990814dc89 76
shaunkrnelson 0:46990814dc89 77 DigitalOut ledRed(LED_RED);
shaunkrnelson 0:46990814dc89 78 DigitalOut ledYellow(LED_YEL);
shaunkrnelson 0:46990814dc89 79 DigitalOut ledGreen(LED_GREEN);
shaunkrnelson 0:46990814dc89 80 DigitalOut ledUsr(LED_USR);
shaunkrnelson 0:46990814dc89 81
shaunkrnelson 0:46990814dc89 82 DigitalOut pc_7(PC_7);
shaunkrnelson 0:46990814dc89 83 DigitalIn pc_1(PC_1);
shaunkrnelson 0:46990814dc89 84 AnalogIn *bat;
shaunkrnelson 0:46990814dc89 85
shaunkrnelson 0:46990814dc89 86 uint8_t ReadBatteryLevel()
shaunkrnelson 0:46990814dc89 87 {
shaunkrnelson 0:46990814dc89 88 uint8_t level = 0;
shaunkrnelson 0:46990814dc89 89
shaunkrnelson 0:46990814dc89 90 if(bat != NULL)
shaunkrnelson 1:fbf2fb2c2718 91 level = ((bat->read_u16() >> 8) + (bat->read_u16() >> 9))>>5;
shaunkrnelson 0:46990814dc89 92
shaunkrnelson 0:46990814dc89 93 debug("Battery level: %d\r\n", level);
shaunkrnelson 0:46990814dc89 94 return level;
shaunkrnelson 0:46990814dc89 95 }
shaunkrnelson 0:46990814dc89 96
shaunkrnelson 0:46990814dc89 97 // Get Mote version
shaunkrnelson 0:46990814dc89 98 mote_version_e get_mote_version()
shaunkrnelson 0:46990814dc89 99 {
shaunkrnelson 0:46990814dc89 100 static mote_version_e mote_version = MOTE_NONE;
shaunkrnelson 0:46990814dc89 101
shaunkrnelson 0:46990814dc89 102 if (mote_version == MOTE_NONE)
shaunkrnelson 0:46990814dc89 103 {
shaunkrnelson 0:46990814dc89 104 pc_7 = 1;
shaunkrnelson 0:46990814dc89 105 char first = pc_1;
shaunkrnelson 0:46990814dc89 106 pc_7 = 0;
shaunkrnelson 0:46990814dc89 107
shaunkrnelson 0:46990814dc89 108 if (first && !pc_1) {
shaunkrnelson 0:46990814dc89 109 printf("v2\r\n");
shaunkrnelson 0:46990814dc89 110 mote_version = MOTE_V2;
shaunkrnelson 0:46990814dc89 111 bat = new AnalogIn(PA_0);
shaunkrnelson 0:46990814dc89 112 } else {
shaunkrnelson 0:46990814dc89 113 printf("v3\r\n");
shaunkrnelson 0:46990814dc89 114 mote_version = MOTE_V3;
shaunkrnelson 0:46990814dc89 115 bat = new AnalogIn(PA_1);
shaunkrnelson 0:46990814dc89 116 }
shaunkrnelson 0:46990814dc89 117 }
shaunkrnelson 0:46990814dc89 118 return mote_version;
shaunkrnelson 0:46990814dc89 119 }
shaunkrnelson 0:46990814dc89 120
shaunkrnelson 0:46990814dc89 121 void board_peripherals_init()
shaunkrnelson 0:46990814dc89 122 {
shaunkrnelson 0:46990814dc89 123 ledRed = 1;
shaunkrnelson 0:46990814dc89 124 ledYellow = 1;
shaunkrnelson 0:46990814dc89 125 ledGreen = 1;
shaunkrnelson 0:46990814dc89 126 ledUsr = 0;
shaunkrnelson 0:46990814dc89 127
shaunkrnelson 0:46990814dc89 128 // Start GPS
shaunkrnelson 0:46990814dc89 129 gps.init();
shaunkrnelson 0:46990814dc89 130 if(get_mote_version() == MOTE_V3)
shaunkrnelson 0:46990814dc89 131 gps.en_invert = false;
shaunkrnelson 0:46990814dc89 132 else
shaunkrnelson 0:46990814dc89 133 gps.en_invert = true;
shaunkrnelson 0:46990814dc89 134
shaunkrnelson 0:46990814dc89 135 gps.enable(false);
shaunkrnelson 0:46990814dc89 136
shaunkrnelson 0:46990814dc89 137 GPIOA->MODER |= 0x01415500; // unused pins as outputs: PA4, PA5, PA6, PA7, PA8, (PA11,PA12 USB)
shaunkrnelson 0:46990814dc89 138 //printf("GPIOA->MODER:%08x\r\n", GPIOA->MODER);
shaunkrnelson 0:46990814dc89 139
shaunkrnelson 0:46990814dc89 140 GPIOB->MODER |= 0x00000401; // unused pins as outputs: PB0(HDR_DIO1), PB5 (PB10 pulled hi by LED), PB3-T_SWO
shaunkrnelson 0:46990814dc89 141 //printf("GPIOB->MODER:%08x\r\n", GPIOB->MODER);
shaunkrnelson 0:46990814dc89 142
shaunkrnelson 0:46990814dc89 143 GPIOC->MODER |= 0x00000045; // unused pins as outputs: PC0(hdr_fem_csd) PC1(hdr_fem_ctx) PC3(SPI3_enable)
shaunkrnelson 0:46990814dc89 144 //printf("GPIOC->MODER:%08x\r\n", GPIOC->MODER);
shaunkrnelson 0:46990814dc89 145
shaunkrnelson 0:46990814dc89 146 sx9500.RegProxCtrl0.bits.sensor_en = 3; // only CS0 and CS1 connected
shaunkrnelson 0:46990814dc89 147 sx9500.write(SX9500_REG_PROXCTRL0, sx9500.RegProxCtrl0.octet);
shaunkrnelson 0:46990814dc89 148
shaunkrnelson 0:46990814dc89 149 // set PROXTHRESH to 80 because CS1 has 48 showing always on PROXDIFF
shaunkrnelson 0:46990814dc89 150 sx9500.write(SX9500_REG_PROXCTRL6, 0x04);
shaunkrnelson 0:46990814dc89 151
shaunkrnelson 0:46990814dc89 152 // Enable accelerometer orientation detection
shaunkrnelson 0:46990814dc89 153 #define DEBUG
shaunkrnelson 0:46990814dc89 154 #ifdef DEBUG
shaunkrnelson 0:46990814dc89 155 mma8451q.verbose = true;
shaunkrnelson 0:46990814dc89 156 #endif
shaunkrnelson 0:46990814dc89 157 mma8451q.orient_detect();
shaunkrnelson 0:46990814dc89 158 mma8451q.set_active(true);
shaunkrnelson 0:46990814dc89 159
shaunkrnelson 0:46990814dc89 160 mpl3115a2.init();
shaunkrnelson 0:46990814dc89 161 mpl3115a2.SetModeStandby();
shaunkrnelson 0:46990814dc89 162
shaunkrnelson 0:46990814dc89 163 gps.enable(true);
shaunkrnelson 0:46990814dc89 164 }
shaunkrnelson 0:46990814dc89 165
shaunkrnelson 0:46990814dc89 166 // application commmon
shaunkrnelson 0:46990814dc89 167 bool gps_service()
shaunkrnelson 0:46990814dc89 168 {
shaunkrnelson 0:46990814dc89 169 gps.have_fix = false;
shaunkrnelson 0:46990814dc89 170 if (gps.enabled()) {
shaunkrnelson 0:46990814dc89 171 for(int32_t i = 0; i < 10; i++)
shaunkrnelson 0:46990814dc89 172 {
shaunkrnelson 0:46990814dc89 173 gps.service();
shaunkrnelson 0:46990814dc89 174 if (gps.have_fix == true) {
shaunkrnelson 0:46990814dc89 175 return true;
shaunkrnelson 0:46990814dc89 176 }
shaunkrnelson 0:46990814dc89 177 else
shaunkrnelson 1:fbf2fb2c2718 178 wait(.1);
shaunkrnelson 0:46990814dc89 179 }
shaunkrnelson 0:46990814dc89 180 }
shaunkrnelson 0:46990814dc89 181 return false;
shaunkrnelson 0:46990814dc89 182 }
shaunkrnelson 0:46990814dc89 183
shaunkrnelson 0:46990814dc89 184
shaunkrnelson 0:46990814dc89 185
shaunkrnelson 0:46990814dc89 186 static void restore_hsi()
shaunkrnelson 0:46990814dc89 187 {
shaunkrnelson 0:46990814dc89 188 RCC_OscInitTypeDef osc_init;
shaunkrnelson 0:46990814dc89 189 /* if HSI was shut off in deep sleep (needed for AnalogIn) */
shaunkrnelson 0:46990814dc89 190 HAL_RCC_GetOscConfig(&osc_init);
shaunkrnelson 0:46990814dc89 191 if (osc_init.HSIState != RCC_HSI_ON) {
shaunkrnelson 0:46990814dc89 192 // Enable the HSI (to clock the ADC)
shaunkrnelson 0:46990814dc89 193 osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSI;
shaunkrnelson 0:46990814dc89 194 osc_init.HSIState = RCC_HSI_ON;
shaunkrnelson 0:46990814dc89 195 osc_init.PLL.PLLState = RCC_PLL_NONE;
shaunkrnelson 0:46990814dc89 196 HAL_RCC_OscConfig(&osc_init);
shaunkrnelson 0:46990814dc89 197 }
shaunkrnelson 0:46990814dc89 198 }
shaunkrnelson 0:46990814dc89 199
shaunkrnelson 0:46990814dc89 200
shaunkrnelson 0:46990814dc89 201 u1_t PrepareDataFrame( SenetPacketT type )
shaunkrnelson 0:46990814dc89 202 {
shaunkrnelson 0:46990814dc89 203 u1_t pktLen = 0;
shaunkrnelson 0:46990814dc89 204
shaunkrnelson 0:46990814dc89 205 restore_hsi();
shaunkrnelson 0:46990814dc89 206
shaunkrnelson 0:46990814dc89 207 switch (type)
shaunkrnelson 0:46990814dc89 208 {
shaunkrnelson 0:46990814dc89 209 case SELF_ID_PACKET:
shaunkrnelson 0:46990814dc89 210 {
shaunkrnelson 0:46990814dc89 211 // Self Id packet type serialized to the LMIC frame buffer
shaunkrnelson 0:46990814dc89 212 SelfIdPacket packet(LMIC.frame, MAX_LEN_FRAME);
shaunkrnelson 1:fbf2fb2c2718 213
shaunkrnelson 0:46990814dc89 214 // Device Type
shaunkrnelson 0:46990814dc89 215 packet.setDeviceType(NORAM_MOTE_DEVICE_TYPE, get_mote_version());
shaunkrnelson 0:46990814dc89 216
shaunkrnelson 0:46990814dc89 217 // Software version
shaunkrnelson 0:46990814dc89 218 packet.setSwVersion(MAJOR, MINOR, POINT, BUILD_NUMBER, DEVELOPER_ID);
shaunkrnelson 0:46990814dc89 219
shaunkrnelson 0:46990814dc89 220 // Battery level
shaunkrnelson 0:46990814dc89 221 packet.setBatteryLevel(ReadBatteryLevel());
shaunkrnelson 0:46990814dc89 222
shaunkrnelson 0:46990814dc89 223 // Serialize packet to LMIC transmit buffer
shaunkrnelson 0:46990814dc89 224 pktLen = packet.serialize();
shaunkrnelson 0:46990814dc89 225
shaunkrnelson 0:46990814dc89 226 break;
shaunkrnelson 0:46990814dc89 227 }
shaunkrnelson 0:46990814dc89 228 case GPS_PACKET:
shaunkrnelson 0:46990814dc89 229 default:
shaunkrnelson 0:46990814dc89 230 {
shaunkrnelson 0:46990814dc89 231 // Gps packet type serialized to the LMIC frame buffer
shaunkrnelson 0:46990814dc89 232 GpsPacket packet(LMIC.frame, MAX_LEN_FRAME);
shaunkrnelson 1:fbf2fb2c2718 233
shaunkrnelson 0:46990814dc89 234 // set packet transmit power
shaunkrnelson 0:46990814dc89 235 packet.setTxPower(pw);
shaunkrnelson 0:46990814dc89 236
shaunkrnelson 1:fbf2fb2c2718 237 // Set packet coordinates
shaunkrnelson 1:fbf2fb2c2718 238 uint16_t altitudeGps = atoi(gps.NmeaGpsData.NmeaAltitude);
shaunkrnelson 1:fbf2fb2c2718 239 packet.setCoordinates(gps.LatitudeBinary, gps.LongitudeBinary, altitudeGps);
shaunkrnelson 1:fbf2fb2c2718 240 lastTxPos.set(gps.Latitude,gps.Longitude);
shaunkrnelson 1:fbf2fb2c2718 241
shaunkrnelson 0:46990814dc89 242 // Serialize packet
shaunkrnelson 0:46990814dc89 243 pktLen = packet.serialize();
shaunkrnelson 0:46990814dc89 244 break;
shaunkrnelson 0:46990814dc89 245 }
shaunkrnelson 0:46990814dc89 246 }
shaunkrnelson 0:46990814dc89 247
shaunkrnelson 0:46990814dc89 248 return pktLen;
shaunkrnelson 0:46990814dc89 249 }
shaunkrnelson 0:46990814dc89 250
shaunkrnelson 0:46990814dc89 251 void displayBuildInfo()
shaunkrnelson 0:46990814dc89 252 {
shaunkrnelson 0:46990814dc89 253 debug("Range & Site Tester\r\n");
shaunkrnelson 0:46990814dc89 254 debug("Version %02d.%02d.%02d.%04d.%02d\r\n",MAJOR,MINOR,POINT,BUILD_NUMBER,DEVELOPER_ID);
shaunkrnelson 0:46990814dc89 255 debug("\r\nDevEUI: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\r\n",
shaunkrnelson 0:46990814dc89 256 reverse_DEVEUI[0],
shaunkrnelson 0:46990814dc89 257 reverse_DEVEUI[1],
shaunkrnelson 0:46990814dc89 258 reverse_DEVEUI[2],
shaunkrnelson 0:46990814dc89 259 reverse_DEVEUI[3],
shaunkrnelson 0:46990814dc89 260 reverse_DEVEUI[4],
shaunkrnelson 0:46990814dc89 261 reverse_DEVEUI[5],
shaunkrnelson 0:46990814dc89 262 reverse_DEVEUI[6],
shaunkrnelson 0:46990814dc89 263 reverse_DEVEUI[7]);
shaunkrnelson 0:46990814dc89 264 debug("AppEUI: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\r\n",
shaunkrnelson 0:46990814dc89 265 reverse_APPEUI[0],
shaunkrnelson 0:46990814dc89 266 reverse_APPEUI[1],
shaunkrnelson 0:46990814dc89 267 reverse_APPEUI[2],
shaunkrnelson 0:46990814dc89 268 reverse_APPEUI[3],
shaunkrnelson 0:46990814dc89 269 reverse_APPEUI[4],
shaunkrnelson 0:46990814dc89 270 reverse_APPEUI[5],
shaunkrnelson 0:46990814dc89 271 reverse_APPEUI[6],
shaunkrnelson 0:46990814dc89 272 reverse_APPEUI[7]);
shaunkrnelson 0:46990814dc89 273 }
shaunkrnelson 0:46990814dc89 274
shaunkrnelson 0:46990814dc89 275
shaunkrnelson 0:46990814dc89 276 void startLMIC()
shaunkrnelson 0:46990814dc89 277 {
shaunkrnelson 0:46990814dc89 278 // reset MAC state
shaunkrnelson 0:46990814dc89 279 LMIC_reset();
shaunkrnelson 0:46990814dc89 280 // start joining
shaunkrnelson 0:46990814dc89 281 LMIC_startJoining();
shaunkrnelson 0:46990814dc89 282 }
shaunkrnelson 0:46990814dc89 283
shaunkrnelson 0:46990814dc89 284
shaunkrnelson 0:46990814dc89 285
shaunkrnelson 0:46990814dc89 286 // Operational mode
shaunkrnelson 0:46990814dc89 287 enum OperMode
shaunkrnelson 0:46990814dc89 288 {
shaunkrnelson 0:46990814dc89 289 // Range testing
shaunkrnelson 0:46990814dc89 290 RANGE_TEST,
shaunkrnelson 0:46990814dc89 291 // Site testing
shaunkrnelson 0:46990814dc89 292 SITE_TEST,
shaunkrnelson 0:46990814dc89 293 // Sending self-id packet
shaunkrnelson 0:46990814dc89 294 SELF_ID,
shaunkrnelson 0:46990814dc89 295 // No mode set
shaunkrnelson 0:46990814dc89 296 IDLE
shaunkrnelson 0:46990814dc89 297 };
shaunkrnelson 0:46990814dc89 298
shaunkrnelson 0:46990814dc89 299 // OS job management objects
shaunkrnelson 0:46990814dc89 300 static osjob_t statusLedJob;
shaunkrnelson 0:46990814dc89 301 static osjob_t txLedJob;
shaunkrnelson 0:46990814dc89 302 static osjob_t orientationJob;
shaunkrnelson 0:46990814dc89 303 static osjob_t sendFrameJob;
shaunkrnelson 0:46990814dc89 304
shaunkrnelson 0:46990814dc89 305 // Mote orientation is checked periodically. The mote test mode
shaunkrnelson 0:46990814dc89 306 // is selected by orientation. When mote is vertical it is in
shaunkrnelson 0:46990814dc89 307 // site test mode and range test mode when horizontal.
shaunkrnelson 0:46990814dc89 308 // Note that changing mote mode will abort previous mode testing
shaunkrnelson 0:46990814dc89 309 #define ORIENTATION_CHECK_PERIOD 5
shaunkrnelson 0:46990814dc89 310
shaunkrnelson 0:46990814dc89 311 // Debounce orientation change
shaunkrnelson 0:46990814dc89 312 #define ORIENTATION_DEBOUNCE_TIME 5
shaunkrnelson 0:46990814dc89 313
shaunkrnelson 0:46990814dc89 314 #define STATUS_FAST_BLINK 1
shaunkrnelson 0:46990814dc89 315 #define STATUS_SLOW_BLINK 4
shaunkrnelson 0:46990814dc89 316 #define STATUS_OK_PERIOD 5
shaunkrnelson 0:46990814dc89 317
shaunkrnelson 0:46990814dc89 318 static u4_t txCount = 0;
shaunkrnelson 0:46990814dc89 319 static ostime_t lastTestDoneT = 0;
shaunkrnelson 0:46990814dc89 320 static bool ackRequested = false;
shaunkrnelson 0:46990814dc89 321 static OperMode operMode = IDLE;
shaunkrnelson 0:46990814dc89 322 static OperMode txMode = IDLE;
shaunkrnelson 0:46990814dc89 323
shaunkrnelson 0:46990814dc89 324 //////////////////////////////////////////////////
shaunkrnelson 0:46990814dc89 325 // Range test configuration
shaunkrnelson 0:46990814dc89 326 //////////////////////////////////////////////////
shaunkrnelson 0:46990814dc89 327 #define RANGE_TXCYCLE_TRANSMITS 8
shaunkrnelson 0:46990814dc89 328 #define RANGE_NEXT_TEST_LONG 560
shaunkrnelson 0:46990814dc89 329 #define RANGE_NEXT_TEST_NOACK 140
shaunkrnelson 0:46990814dc89 330 #define RANGE_NEXT_TEST_DISTANCE 80
shaunkrnelson 0:46990814dc89 331 #define RANGE_NEXT_TEST_MIN_TIME 80
shaunkrnelson 0:46990814dc89 332 #define RANGE_NEXT_TX 5
shaunkrnelson 0:46990814dc89 333 #define RANGE_START_TEST_DISTANCE 30 // meters
shaunkrnelson 0:46990814dc89 334 #define RANGE_NEXT_TEST_DISTANCE_T 15
shaunkrnelson 0:46990814dc89 335
shaunkrnelson 0:46990814dc89 336
shaunkrnelson 0:46990814dc89 337 //////////////////////////////////////////////////
shaunkrnelson 0:46990814dc89 338 // Site test configuration
shaunkrnelson 0:46990814dc89 339 //////////////////////////////////////////////////
shaunkrnelson 0:46990814dc89 340 #define SITE_TX_PW1 14
shaunkrnelson 0:46990814dc89 341 #define SITE_TX_PW2 20
shaunkrnelson 0:46990814dc89 342 #define SITE_TX_PW3 30
shaunkrnelson 0:46990814dc89 343 #define SITE_GREEN_LED_PW SITE_TX_PW1
shaunkrnelson 0:46990814dc89 344 #define SITE_YELLOW_LED_PW SITE_TX_PW2
shaunkrnelson 0:46990814dc89 345 #define SITE_RED_LED_PW SITE_TX_PW3
shaunkrnelson 0:46990814dc89 346
shaunkrnelson 0:46990814dc89 347 static u1_t siteDrs[2] = {0,4};
shaunkrnelson 0:46990814dc89 348 static u1_t sitePws[3] = {SITE_TX_PW1, SITE_TX_PW2, SITE_TX_PW3};
shaunkrnelson 0:46990814dc89 349 static u1_t siteAck[3] = {0,0,0};
shaunkrnelson 0:46990814dc89 350 static u1_t siteDr = 0;
shaunkrnelson 0:46990814dc89 351 static u1_t sitePw = 0;
shaunkrnelson 0:46990814dc89 352 static u1_t siteDrPwAttempts = 0;
shaunkrnelson 0:46990814dc89 353 #define SITE_DR_MAX sizeof(siteDrs)
shaunkrnelson 0:46990814dc89 354 #define SITE_PW_MAX sizeof(sitePws)
shaunkrnelson 0:46990814dc89 355 #define SITE_PW_DR_ATTEMPTS 3
shaunkrnelson 0:46990814dc89 356
shaunkrnelson 0:46990814dc89 357
shaunkrnelson 0:46990814dc89 358 static void txLedCb(osjob_t *job)
shaunkrnelson 0:46990814dc89 359 {
shaunkrnelson 0:46990814dc89 360 if(operMode == RANGE_TEST)
shaunkrnelson 0:46990814dc89 361 {
shaunkrnelson 0:46990814dc89 362 ledRed = 1;
shaunkrnelson 0:46990814dc89 363 }
shaunkrnelson 0:46990814dc89 364 else if(operMode == SITE_TEST)
shaunkrnelson 0:46990814dc89 365 {
shaunkrnelson 0:46990814dc89 366 switch(pw)
shaunkrnelson 0:46990814dc89 367 {
shaunkrnelson 0:46990814dc89 368 case SITE_GREEN_LED_PW:
shaunkrnelson 0:46990814dc89 369 ledGreen = 1;
shaunkrnelson 0:46990814dc89 370 break;
shaunkrnelson 0:46990814dc89 371 case SITE_YELLOW_LED_PW:
shaunkrnelson 0:46990814dc89 372 ledYellow = 1;
shaunkrnelson 0:46990814dc89 373 break;
shaunkrnelson 0:46990814dc89 374 case SITE_RED_LED_PW:
shaunkrnelson 0:46990814dc89 375 ledRed = 1;
shaunkrnelson 0:46990814dc89 376 break;
shaunkrnelson 0:46990814dc89 377 }
shaunkrnelson 0:46990814dc89 378 }
shaunkrnelson 0:46990814dc89 379 }
shaunkrnelson 0:46990814dc89 380
shaunkrnelson 0:46990814dc89 381
shaunkrnelson 0:46990814dc89 382 static void onSendFrame(osjob_t* j)
shaunkrnelson 0:46990814dc89 383 {
shaunkrnelson 1:fbf2fb2c2718 384 u1_t pktSize = 0;
shaunkrnelson 0:46990814dc89 385
shaunkrnelson 0:46990814dc89 386 // Return if still transmitting. Next transmit will be scheduled by onEvent() when tx finishes
shaunkrnelson 0:46990814dc89 387 if (LMIC.opmode & OP_TXRXPEND)
shaunkrnelson 0:46990814dc89 388 return;
shaunkrnelson 0:46990814dc89 389
shaunkrnelson 0:46990814dc89 390 if(operMode == RANGE_TEST)
shaunkrnelson 0:46990814dc89 391 {
shaunkrnelson 0:46990814dc89 392 // Select dr and tx power
shaunkrnelson 0:46990814dc89 393 switch(txCount&0x07)
shaunkrnelson 0:46990814dc89 394 {
shaunkrnelson 0:46990814dc89 395 case 0:
shaunkrnelson 0:46990814dc89 396 dr = 3;
shaunkrnelson 0:46990814dc89 397 pw = 14;
shaunkrnelson 0:46990814dc89 398 ackRequested = true; // set this on the first tx of the group
shaunkrnelson 0:46990814dc89 399 ledYellow = 0;
shaunkrnelson 0:46990814dc89 400 ledGreen = 0;
shaunkrnelson 0:46990814dc89 401 break;
shaunkrnelson 0:46990814dc89 402 case 1:
shaunkrnelson 0:46990814dc89 403 dr = 0;
shaunkrnelson 0:46990814dc89 404 pw = 14;
shaunkrnelson 0:46990814dc89 405 break;
shaunkrnelson 0:46990814dc89 406 case 2:
shaunkrnelson 0:46990814dc89 407 dr = 4;
shaunkrnelson 0:46990814dc89 408 pw = 20;
shaunkrnelson 0:46990814dc89 409 break;
shaunkrnelson 0:46990814dc89 410 case 3:
shaunkrnelson 0:46990814dc89 411 dr = 3;
shaunkrnelson 0:46990814dc89 412 pw = 20;
shaunkrnelson 0:46990814dc89 413 break;
shaunkrnelson 0:46990814dc89 414 case 4:
shaunkrnelson 0:46990814dc89 415 dr = 0;
shaunkrnelson 0:46990814dc89 416 pw = 20;
shaunkrnelson 0:46990814dc89 417 break;
shaunkrnelson 0:46990814dc89 418 case 5:
shaunkrnelson 0:46990814dc89 419 dr = 4;
shaunkrnelson 0:46990814dc89 420 pw = 26;
shaunkrnelson 0:46990814dc89 421 break;
shaunkrnelson 0:46990814dc89 422 case 6:
shaunkrnelson 0:46990814dc89 423 dr = 3;
shaunkrnelson 0:46990814dc89 424 pw = 30;
shaunkrnelson 0:46990814dc89 425 break;
shaunkrnelson 0:46990814dc89 426 case 7:
shaunkrnelson 0:46990814dc89 427 dr = 0;
shaunkrnelson 0:46990814dc89 428 pw = 30;
shaunkrnelson 0:46990814dc89 429 break;
shaunkrnelson 0:46990814dc89 430 }
shaunkrnelson 0:46990814dc89 431 // Blink transmit LED
shaunkrnelson 0:46990814dc89 432 ledRed = 0;
shaunkrnelson 0:46990814dc89 433 os_setTimedCallback( &txLedJob, os_getTime() + 1, txLedCb);
shaunkrnelson 0:46990814dc89 434 }
shaunkrnelson 0:46990814dc89 435 else if (operMode == SITE_TEST)
shaunkrnelson 0:46990814dc89 436 {
shaunkrnelson 0:46990814dc89 437 ackRequested = true;
shaunkrnelson 0:46990814dc89 438
shaunkrnelson 0:46990814dc89 439 if((siteDr < SITE_DR_MAX) && (sitePw < SITE_PW_MAX))
shaunkrnelson 0:46990814dc89 440 {
shaunkrnelson 0:46990814dc89 441 dr = siteDrs[siteDr];
shaunkrnelson 0:46990814dc89 442 pw = sitePws[sitePw];
shaunkrnelson 0:46990814dc89 443 }
shaunkrnelson 0:46990814dc89 444 // Restarting test
shaunkrnelson 0:46990814dc89 445 else
shaunkrnelson 0:46990814dc89 446 {
shaunkrnelson 0:46990814dc89 447 debug("Bad dr=%d or pw=%d index\r\n", siteDr, sitePw);
shaunkrnelson 0:46990814dc89 448 siteDr = 0;
shaunkrnelson 0:46990814dc89 449 sitePw = 0;
shaunkrnelson 0:46990814dc89 450 }
shaunkrnelson 0:46990814dc89 451 // Blink tx LED
shaunkrnelson 0:46990814dc89 452 switch(pw)
shaunkrnelson 0:46990814dc89 453 {
shaunkrnelson 0:46990814dc89 454 case SITE_GREEN_LED_PW:
shaunkrnelson 0:46990814dc89 455 ledGreen = 0;
shaunkrnelson 0:46990814dc89 456 break;
shaunkrnelson 0:46990814dc89 457 case SITE_YELLOW_LED_PW:
shaunkrnelson 0:46990814dc89 458 ledYellow = 0;
shaunkrnelson 0:46990814dc89 459 break;
shaunkrnelson 0:46990814dc89 460 case SITE_RED_LED_PW:
shaunkrnelson 0:46990814dc89 461 ledRed = 0;
shaunkrnelson 0:46990814dc89 462 break;
shaunkrnelson 0:46990814dc89 463 }
shaunkrnelson 0:46990814dc89 464 os_setTimedCallback( &txLedJob, os_getTime() + 1, txLedCb);
shaunkrnelson 0:46990814dc89 465 }
shaunkrnelson 1:fbf2fb2c2718 466
shaunkrnelson 1:fbf2fb2c2718 467 // Send GPS data
shaunkrnelson 1:fbf2fb2c2718 468 for(int32_t i=0; i<3; i++)
shaunkrnelson 1:fbf2fb2c2718 469 {
shaunkrnelson 1:fbf2fb2c2718 470 if(gps_service() == true)
shaunkrnelson 1:fbf2fb2c2718 471 {
shaunkrnelson 1:fbf2fb2c2718 472 pktSize = PrepareDataFrame(GPS_PACKET);
shaunkrnelson 1:fbf2fb2c2718 473 break;
shaunkrnelson 1:fbf2fb2c2718 474 }
shaunkrnelson 1:fbf2fb2c2718 475 }
shaunkrnelson 1:fbf2fb2c2718 476
shaunkrnelson 1:fbf2fb2c2718 477 // if unable to get GPS, send self-id
shaunkrnelson 1:fbf2fb2c2718 478 if(0 == pktSize)
shaunkrnelson 1:fbf2fb2c2718 479 pktSize = PrepareDataFrame(SELF_ID_PACKET);
shaunkrnelson 0:46990814dc89 480
shaunkrnelson 0:46990814dc89 481
shaunkrnelson 0:46990814dc89 482 // Set next dr and tx power
shaunkrnelson 0:46990814dc89 483 LMIC_setDrTxpow(dr,pw);
shaunkrnelson 0:46990814dc89 484
shaunkrnelson 0:46990814dc89 485 txCount++;
shaunkrnelson 0:46990814dc89 486 txMode = operMode;
shaunkrnelson 0:46990814dc89 487
shaunkrnelson 0:46990814dc89 488 debug("onSendFrame mode=%d: dr=%d, pw=%d, ack=%d\r\n",operMode, dr, pw, ackRequested);
shaunkrnelson 0:46990814dc89 489 LMIC_setTxData2(1, LMIC.frame, pktSize, ackRequested);
shaunkrnelson 0:46990814dc89 490 }
shaunkrnelson 0:46990814dc89 491
shaunkrnelson 0:46990814dc89 492 static void checkIfRangeTestStart(osjob_t *job)
shaunkrnelson 0:46990814dc89 493 {
shaunkrnelson 0:46990814dc89 494 const ostime_t waitT = ackRequested ? RANGE_NEXT_TEST_NOACK : RANGE_NEXT_TEST_LONG;
shaunkrnelson 0:46990814dc89 495 const ostime_t startT = lastTestDoneT + sec2osticks(waitT);
shaunkrnelson 0:46990814dc89 496
shaunkrnelson 0:46990814dc89 497 debug("%u seconds elapsed since last test\r\n",osticks2ms(os_getTime()-lastTestDoneT)/1000);
shaunkrnelson 0:46990814dc89 498
shaunkrnelson 0:46990814dc89 499 if(os_getTime() >= startT)
shaunkrnelson 0:46990814dc89 500 {
shaunkrnelson 0:46990814dc89 501 os_setCallback( &sendFrameJob, onSendFrame );
shaunkrnelson 0:46990814dc89 502 }
shaunkrnelson 0:46990814dc89 503 else if(gps_service())
shaunkrnelson 0:46990814dc89 504 {
shaunkrnelson 0:46990814dc89 505 // Do we have last tx coordinates
shaunkrnelson 0:46990814dc89 506 if((lastTxPos.latitude() == 0) && (lastTxPos.longitude() == 0))
shaunkrnelson 0:46990814dc89 507 {
shaunkrnelson 0:46990814dc89 508 // Set last tx position to current location
shaunkrnelson 0:46990814dc89 509 lastTxPos.set(gps.Latitude,gps.Longitude);
shaunkrnelson 0:46990814dc89 510 }
shaunkrnelson 0:46990814dc89 511 else
shaunkrnelson 0:46990814dc89 512 {
shaunkrnelson 0:46990814dc89 513 GeoPosition location(gps.Latitude, gps.Longitude);
shaunkrnelson 0:46990814dc89 514 double distance = location.distance(lastTxPos);
shaunkrnelson 0:46990814dc89 515
shaunkrnelson 0:46990814dc89 516 if(distance >= RANGE_START_TEST_DISTANCE)
shaunkrnelson 0:46990814dc89 517 {
shaunkrnelson 0:46990814dc89 518 debug("position change %f >= %u\r\n",distance, RANGE_START_TEST_DISTANCE);
shaunkrnelson 0:46990814dc89 519 os_setCallback( &sendFrameJob, onSendFrame );
shaunkrnelson 0:46990814dc89 520 return;
shaunkrnelson 0:46990814dc89 521 }
shaunkrnelson 0:46990814dc89 522 }
shaunkrnelson 0:46990814dc89 523 }
shaunkrnelson 0:46990814dc89 524
shaunkrnelson 0:46990814dc89 525 // Schedule next check
shaunkrnelson 0:46990814dc89 526 ostime_t nextChkT = os_getTime() + sec2osticks(RANGE_NEXT_TEST_DISTANCE_T);
shaunkrnelson 0:46990814dc89 527
shaunkrnelson 0:46990814dc89 528 // If distance check time less than test start, schedule distance check
shaunkrnelson 0:46990814dc89 529 if(nextChkT <= startT)
shaunkrnelson 0:46990814dc89 530 {
shaunkrnelson 0:46990814dc89 531 os_setTimedCallback( &sendFrameJob, nextChkT, checkIfRangeTestStart);
shaunkrnelson 0:46990814dc89 532 }
shaunkrnelson 0:46990814dc89 533 // Else test start less than distance check time
shaunkrnelson 0:46990814dc89 534 else
shaunkrnelson 0:46990814dc89 535 {
shaunkrnelson 0:46990814dc89 536 os_setTimedCallback( &sendFrameJob, startT, onSendFrame);
shaunkrnelson 0:46990814dc89 537 }
shaunkrnelson 0:46990814dc89 538 }
shaunkrnelson 0:46990814dc89 539
shaunkrnelson 0:46990814dc89 540 static void preTestStart(osjob_t *job)
shaunkrnelson 0:46990814dc89 541 {
shaunkrnelson 0:46990814dc89 542 static u1_t wait = 0;
shaunkrnelson 0:46990814dc89 543
shaunkrnelson 0:46990814dc89 544 // onEvent will initiate test on join or tx complete
shaunkrnelson 0:46990814dc89 545 if(((LMIC.opmode & OP_JOINING) != 0) || ((LMIC.opmode & OP_TXRXPEND) != 0))
shaunkrnelson 0:46990814dc89 546 return;
shaunkrnelson 0:46990814dc89 547
shaunkrnelson 0:46990814dc89 548 if(wait < 6)
shaunkrnelson 0:46990814dc89 549 {
shaunkrnelson 0:46990814dc89 550 if((wait & 1) == 0)
shaunkrnelson 0:46990814dc89 551 {
shaunkrnelson 0:46990814dc89 552 ledRed = 0;
shaunkrnelson 0:46990814dc89 553 ledGreen = 0;
shaunkrnelson 0:46990814dc89 554 ledYellow = 0;
shaunkrnelson 0:46990814dc89 555 }
shaunkrnelson 0:46990814dc89 556 else
shaunkrnelson 0:46990814dc89 557 {
shaunkrnelson 0:46990814dc89 558 ledRed = 1;
shaunkrnelson 0:46990814dc89 559 ledGreen = 1;
shaunkrnelson 0:46990814dc89 560 ledYellow = 1;
shaunkrnelson 0:46990814dc89 561 }
shaunkrnelson 0:46990814dc89 562 wait++;
shaunkrnelson 0:46990814dc89 563 os_setTimedCallback( &sendFrameJob, os_getTime() + sec2osticks(1), preTestStart);
shaunkrnelson 0:46990814dc89 564 }
shaunkrnelson 0:46990814dc89 565 else
shaunkrnelson 0:46990814dc89 566 {
shaunkrnelson 0:46990814dc89 567 wait = 0;
shaunkrnelson 0:46990814dc89 568 os_setCallback( &sendFrameJob, onSendFrame);
shaunkrnelson 0:46990814dc89 569 }
shaunkrnelson 0:46990814dc89 570 }
shaunkrnelson 0:46990814dc89 571
shaunkrnelson 0:46990814dc89 572
shaunkrnelson 0:46990814dc89 573 // Protocol event handler
shaunkrnelson 0:46990814dc89 574 void onEvent (ev_t ev)
shaunkrnelson 0:46990814dc89 575 {
shaunkrnelson 0:46990814dc89 576 debug_event(ev);
shaunkrnelson 0:46990814dc89 577 switch(ev)
shaunkrnelson 0:46990814dc89 578 {
shaunkrnelson 0:46990814dc89 579 // network joined, session established
shaunkrnelson 0:46990814dc89 580 case EV_JOINED:
shaunkrnelson 1:fbf2fb2c2718 581 {
shaunkrnelson 1:fbf2fb2c2718 582 displayBuildInfo();
shaunkrnelson 1:fbf2fb2c2718 583 //
shaunkrnelson 0:46990814dc89 584 // Disable link check validation
shaunkrnelson 0:46990814dc89 585 LMIC_setLinkCheckMode(false);
shaunkrnelson 0:46990814dc89 586
shaunkrnelson 1:fbf2fb2c2718 587 // Start transmitting
shaunkrnelson 1:fbf2fb2c2718 588 os_setCallback( &sendFrameJob, onSendFrame);
shaunkrnelson 0:46990814dc89 589
shaunkrnelson 0:46990814dc89 590 break;
shaunkrnelson 0:46990814dc89 591 }
shaunkrnelson 0:46990814dc89 592 // scheduled data sent (optionally data received)
shaunkrnelson 0:46990814dc89 593 case EV_TXCOMPLETE:
shaunkrnelson 0:46990814dc89 594 // Check transmitted frame mode matches running mode. If not, skip results
shaunkrnelson 0:46990814dc89 595 // and start sending frames for current mode
shaunkrnelson 0:46990814dc89 596 if(txMode != operMode)
shaunkrnelson 0:46990814dc89 597 {
shaunkrnelson 0:46990814dc89 598 // Prepare to start test
shaunkrnelson 0:46990814dc89 599 os_setCallback( &sendFrameJob, preTestStart);
shaunkrnelson 0:46990814dc89 600 }
shaunkrnelson 0:46990814dc89 601 else if(operMode == RANGE_TEST)
shaunkrnelson 0:46990814dc89 602 {
shaunkrnelson 0:46990814dc89 603 // Check ack received
shaunkrnelson 0:46990814dc89 604 if((LMIC.txrxFlags & (TXRX_DNW1|TXRX_DNW2) )!= 0 )
shaunkrnelson 0:46990814dc89 605 {
shaunkrnelson 0:46990814dc89 606 ackRequested = false;
shaunkrnelson 0:46990814dc89 607 ledYellow = 1;
shaunkrnelson 0:46990814dc89 608 }
shaunkrnelson 0:46990814dc89 609
shaunkrnelson 0:46990814dc89 610 if(0 == (txCount & 0x07))
shaunkrnelson 0:46990814dc89 611 {
shaunkrnelson 0:46990814dc89 612 // Schedule job to check for range test restart
shaunkrnelson 0:46990814dc89 613 lastTestDoneT = os_getTime();
shaunkrnelson 0:46990814dc89 614 os_setTimedCallback( &sendFrameJob, lastTestDoneT + sec2osticks(RANGE_NEXT_TEST_MIN_TIME), checkIfRangeTestStart);
shaunkrnelson 0:46990814dc89 615 debug("Check for test restart in %u seconds\r\n",RANGE_NEXT_TEST_MIN_TIME);
shaunkrnelson 0:46990814dc89 616
shaunkrnelson 0:46990814dc89 617 // Turn off transmit cycle indicator led
shaunkrnelson 0:46990814dc89 618 ledGreen = 1;
shaunkrnelson 0:46990814dc89 619 }
shaunkrnelson 0:46990814dc89 620 else
shaunkrnelson 0:46990814dc89 621 {
shaunkrnelson 0:46990814dc89 622 os_setTimedCallback( &sendFrameJob, os_getTime() + sec2osticks(RANGE_NEXT_TX), onSendFrame);
shaunkrnelson 0:46990814dc89 623 }
shaunkrnelson 0:46990814dc89 624 }
shaunkrnelson 0:46990814dc89 625 else if(operMode == SITE_TEST)
shaunkrnelson 0:46990814dc89 626 {
shaunkrnelson 0:46990814dc89 627 // Ack received
shaunkrnelson 0:46990814dc89 628 if(((LMIC.txrxFlags & (TXRX_DNW1|TXRX_DNW2) ) != 0 ))
shaunkrnelson 0:46990814dc89 629 {
shaunkrnelson 0:46990814dc89 630 siteAck[sitePw] = 1;
shaunkrnelson 0:46990814dc89 631
shaunkrnelson 0:46990814dc89 632 // Turn on LED
shaunkrnelson 0:46990814dc89 633 switch(pw)
shaunkrnelson 0:46990814dc89 634 {
shaunkrnelson 0:46990814dc89 635 case SITE_GREEN_LED_PW:
shaunkrnelson 0:46990814dc89 636 ledGreen = 0;
shaunkrnelson 0:46990814dc89 637 break;
shaunkrnelson 0:46990814dc89 638 case SITE_YELLOW_LED_PW:
shaunkrnelson 0:46990814dc89 639 ledYellow = 0;
shaunkrnelson 0:46990814dc89 640 break;
shaunkrnelson 0:46990814dc89 641 case SITE_RED_LED_PW:
shaunkrnelson 0:46990814dc89 642 ledRed = 0;
shaunkrnelson 0:46990814dc89 643 break;
shaunkrnelson 0:46990814dc89 644 }
shaunkrnelson 0:46990814dc89 645
shaunkrnelson 0:46990814dc89 646 // Set next tx power first transmit rate
shaunkrnelson 0:46990814dc89 647 sitePw++;
shaunkrnelson 0:46990814dc89 648 siteDrPwAttempts = 0;
shaunkrnelson 0:46990814dc89 649 }
shaunkrnelson 0:46990814dc89 650 // No ACK
shaunkrnelson 0:46990814dc89 651 else if(++siteDrPwAttempts >= SITE_PW_DR_ATTEMPTS)
shaunkrnelson 0:46990814dc89 652 {
shaunkrnelson 0:46990814dc89 653 sitePw++;
shaunkrnelson 0:46990814dc89 654 siteDrPwAttempts = 0;
shaunkrnelson 0:46990814dc89 655 }
shaunkrnelson 0:46990814dc89 656
shaunkrnelson 0:46990814dc89 657 if(sitePw >= SITE_PW_MAX)
shaunkrnelson 0:46990814dc89 658 {
shaunkrnelson 0:46990814dc89 659 sitePw=0;
shaunkrnelson 0:46990814dc89 660 siteDr++;
shaunkrnelson 0:46990814dc89 661 if(siteDr >= SITE_DR_MAX)
shaunkrnelson 0:46990814dc89 662 siteDr=0;
shaunkrnelson 0:46990814dc89 663 }
shaunkrnelson 0:46990814dc89 664
shaunkrnelson 0:46990814dc89 665 if(siteAck[sitePw] == 0)
shaunkrnelson 0:46990814dc89 666 {
shaunkrnelson 0:46990814dc89 667 os_setTimedCallback( &sendFrameJob, os_getTime() + sec2osticks(1), onSendFrame );
shaunkrnelson 0:46990814dc89 668 }
shaunkrnelson 0:46990814dc89 669 else
shaunkrnelson 0:46990814dc89 670 {
shaunkrnelson 0:46990814dc89 671 bool foundNACK = false;
shaunkrnelson 0:46990814dc89 672
shaunkrnelson 0:46990814dc89 673 for(uint32_t i=sitePw; i < SITE_PW_MAX;i++)
shaunkrnelson 0:46990814dc89 674 {
shaunkrnelson 0:46990814dc89 675 if(siteAck[i] == 0)
shaunkrnelson 0:46990814dc89 676 {
shaunkrnelson 0:46990814dc89 677 sitePw = i;
shaunkrnelson 0:46990814dc89 678 os_setTimedCallback( &sendFrameJob, os_getTime() + sec2osticks(1), onSendFrame );
shaunkrnelson 0:46990814dc89 679 foundNACK = true;
shaunkrnelson 0:46990814dc89 680 break;
shaunkrnelson 0:46990814dc89 681 }
shaunkrnelson 0:46990814dc89 682 }
shaunkrnelson 0:46990814dc89 683
shaunkrnelson 0:46990814dc89 684 if(foundNACK == false)
shaunkrnelson 0:46990814dc89 685 {
shaunkrnelson 0:46990814dc89 686 siteDr++;
shaunkrnelson 0:46990814dc89 687 if(siteDr >= SITE_DR_MAX)
shaunkrnelson 0:46990814dc89 688 siteDr=0;
shaunkrnelson 0:46990814dc89 689
shaunkrnelson 0:46990814dc89 690 for(uint32_t i=0; i < sitePw;i++)
shaunkrnelson 0:46990814dc89 691 {
shaunkrnelson 0:46990814dc89 692 if(siteAck[i] == 0)
shaunkrnelson 0:46990814dc89 693 {
shaunkrnelson 0:46990814dc89 694 sitePw = i;
shaunkrnelson 0:46990814dc89 695 os_setTimedCallback( &sendFrameJob, os_getTime() + sec2osticks(1), onSendFrame );
shaunkrnelson 0:46990814dc89 696 break;
shaunkrnelson 0:46990814dc89 697 }
shaunkrnelson 0:46990814dc89 698 }
shaunkrnelson 0:46990814dc89 699 }
shaunkrnelson 0:46990814dc89 700 }
shaunkrnelson 0:46990814dc89 701 }
shaunkrnelson 0:46990814dc89 702 break;
shaunkrnelson 0:46990814dc89 703 default:
shaunkrnelson 0:46990814dc89 704 break;
shaunkrnelson 0:46990814dc89 705 }
shaunkrnelson 0:46990814dc89 706 }
shaunkrnelson 0:46990814dc89 707
shaunkrnelson 0:46990814dc89 708
shaunkrnelson 0:46990814dc89 709 static void statusLedCb(osjob_t *job)
shaunkrnelson 0:46990814dc89 710 {
shaunkrnelson 0:46990814dc89 711 ostime_t sleep;
shaunkrnelson 0:46990814dc89 712
shaunkrnelson 0:46990814dc89 713 if(ledUsr == 1)
shaunkrnelson 0:46990814dc89 714 {
shaunkrnelson 0:46990814dc89 715 if((LMIC.opmode & OP_JOINING) != 0)
shaunkrnelson 0:46990814dc89 716 {
shaunkrnelson 0:46990814dc89 717 ledUsr = 0;
shaunkrnelson 0:46990814dc89 718 sleep = STATUS_FAST_BLINK;
shaunkrnelson 0:46990814dc89 719 }
shaunkrnelson 0:46990814dc89 720 else if(gps.have_fix == false)
shaunkrnelson 0:46990814dc89 721 {
shaunkrnelson 0:46990814dc89 722 ledUsr = 0;
shaunkrnelson 0:46990814dc89 723 sleep = STATUS_SLOW_BLINK;
shaunkrnelson 0:46990814dc89 724 }
shaunkrnelson 0:46990814dc89 725 else
shaunkrnelson 0:46990814dc89 726 {
shaunkrnelson 0:46990814dc89 727 sleep = STATUS_OK_PERIOD;
shaunkrnelson 0:46990814dc89 728 }
shaunkrnelson 0:46990814dc89 729 }
shaunkrnelson 0:46990814dc89 730 else
shaunkrnelson 0:46990814dc89 731 {
shaunkrnelson 0:46990814dc89 732 ledUsr = 1;
shaunkrnelson 0:46990814dc89 733 sleep = 1;
shaunkrnelson 0:46990814dc89 734 }
shaunkrnelson 0:46990814dc89 735
shaunkrnelson 0:46990814dc89 736 os_setTimedCallback( &statusLedJob, os_getTime() + sec2osticks(sleep), statusLedCb );
shaunkrnelson 0:46990814dc89 737 }
shaunkrnelson 0:46990814dc89 738
shaunkrnelson 0:46990814dc89 739
shaunkrnelson 0:46990814dc89 740 static void orientationJobCb(osjob_t *job)
shaunkrnelson 0:46990814dc89 741 {
shaunkrnelson 0:46990814dc89 742 static MMA_orientation last;
shaunkrnelson 0:46990814dc89 743 MMA_orientation current;
shaunkrnelson 0:46990814dc89 744 int sleepTime = ORIENTATION_CHECK_PERIOD;
shaunkrnelson 0:46990814dc89 745
shaunkrnelson 0:46990814dc89 746 mma8451q.service();
shaunkrnelson 0:46990814dc89 747 current = mma8451q.getOrientation();
shaunkrnelson 0:46990814dc89 748
shaunkrnelson 0:46990814dc89 749 if(current != last)
shaunkrnelson 0:46990814dc89 750 {
shaunkrnelson 0:46990814dc89 751 last = current;
shaunkrnelson 0:46990814dc89 752 sleepTime = ORIENTATION_DEBOUNCE_TIME;
shaunkrnelson 0:46990814dc89 753 }
shaunkrnelson 0:46990814dc89 754 else
shaunkrnelson 0:46990814dc89 755 {
shaunkrnelson 0:46990814dc89 756 const bool currIsVertical = (current.left && (current.front||current.back) && !current.low);
shaunkrnelson 0:46990814dc89 757 const OperMode mode = currIsVertical ? SITE_TEST : RANGE_TEST;
shaunkrnelson 0:46990814dc89 758
shaunkrnelson 0:46990814dc89 759 if(mode != operMode)
shaunkrnelson 0:46990814dc89 760 {
shaunkrnelson 0:46990814dc89 761 debug("Change to %s mode\r\n", mode==SITE_TEST?"Site":"Range");
shaunkrnelson 0:46990814dc89 762
shaunkrnelson 0:46990814dc89 763 // onEvent will start test if currently joining or transmitting
shaunkrnelson 0:46990814dc89 764 if(((LMIC.opmode & OP_JOINING) == 0) && ((LMIC.opmode & OP_TXRXPEND) == 0))
shaunkrnelson 0:46990814dc89 765 {
shaunkrnelson 0:46990814dc89 766 if(operMode != IDLE)
shaunkrnelson 0:46990814dc89 767 {
shaunkrnelson 0:46990814dc89 768 os_setCallback( &sendFrameJob, preTestStart);
shaunkrnelson 0:46990814dc89 769 }
shaunkrnelson 0:46990814dc89 770 else
shaunkrnelson 0:46990814dc89 771 {
shaunkrnelson 0:46990814dc89 772 os_setCallback( &sendFrameJob, onSendFrame);
shaunkrnelson 0:46990814dc89 773 }
shaunkrnelson 0:46990814dc89 774 }
shaunkrnelson 0:46990814dc89 775
shaunkrnelson 0:46990814dc89 776 // Set mode
shaunkrnelson 0:46990814dc89 777 operMode = mode;
shaunkrnelson 0:46990814dc89 778
shaunkrnelson 0:46990814dc89 779 // Reset test indicator LEDs
shaunkrnelson 0:46990814dc89 780 ledRed = 1;
shaunkrnelson 0:46990814dc89 781 ledGreen = 1;
shaunkrnelson 0:46990814dc89 782 ledYellow = 1;
shaunkrnelson 0:46990814dc89 783
shaunkrnelson 0:46990814dc89 784 // Reset test state
shaunkrnelson 0:46990814dc89 785 txCount = 0;
shaunkrnelson 0:46990814dc89 786 siteDr = 0;
shaunkrnelson 0:46990814dc89 787 sitePw = 0;
shaunkrnelson 0:46990814dc89 788 memset(siteAck, 0, sizeof(siteAck));
shaunkrnelson 0:46990814dc89 789 }
shaunkrnelson 0:46990814dc89 790 }
shaunkrnelson 0:46990814dc89 791
shaunkrnelson 0:46990814dc89 792 os_setTimedCallback( &orientationJob, os_getTime() + sec2osticks(sleepTime), orientationJobCb );
shaunkrnelson 0:46990814dc89 793 }
shaunkrnelson 0:46990814dc89 794
shaunkrnelson 0:46990814dc89 795 // Kick off initial jobs
shaunkrnelson 0:46990814dc89 796 void application_init()
shaunkrnelson 0:46990814dc89 797 {
shaunkrnelson 0:46990814dc89 798 // Start status led job
shaunkrnelson 0:46990814dc89 799 os_setCallback(&statusLedJob, statusLedCb);
shaunkrnelson 0:46990814dc89 800
shaunkrnelson 0:46990814dc89 801 // Start orientation job - Test will start once orientation is determined
shaunkrnelson 0:46990814dc89 802 os_setCallback(&orientationJob, orientationJobCb);
shaunkrnelson 0:46990814dc89 803
shaunkrnelson 0:46990814dc89 804 // Get current gps coordinates
shaunkrnelson 0:46990814dc89 805 if(gps_service() == true)
shaunkrnelson 0:46990814dc89 806 lastTxPos.set(gps.Latitude,gps.Longitude);
shaunkrnelson 0:46990814dc89 807 else
shaunkrnelson 0:46990814dc89 808 lastTxPos.set(0,0);
shaunkrnelson 0:46990814dc89 809 }
shaunkrnelson 0:46990814dc89 810
shaunkrnelson 0:46990814dc89 811
shaunkrnelson 0:46990814dc89 812 int main(void)
shaunkrnelson 0:46990814dc89 813 {
shaunkrnelson 0:46990814dc89 814 // initialize runtime env
shaunkrnelson 0:46990814dc89 815 os_init();
shaunkrnelson 0:46990814dc89 816
shaunkrnelson 0:46990814dc89 817 // initialize debug system
shaunkrnelson 0:46990814dc89 818 debug_init();
shaunkrnelson 0:46990814dc89 819
shaunkrnelson 0:46990814dc89 820 // Display build info
shaunkrnelson 0:46990814dc89 821 displayBuildInfo();
shaunkrnelson 0:46990814dc89 822
shaunkrnelson 0:46990814dc89 823 // initialize peripherals
shaunkrnelson 0:46990814dc89 824 board_peripherals_init();
shaunkrnelson 0:46990814dc89 825
shaunkrnelson 0:46990814dc89 826 // Application initialization
shaunkrnelson 0:46990814dc89 827 application_init();
shaunkrnelson 0:46990814dc89 828
shaunkrnelson 0:46990814dc89 829 // Start protocol
shaunkrnelson 0:46990814dc89 830 startLMIC();
shaunkrnelson 0:46990814dc89 831
shaunkrnelson 0:46990814dc89 832 // execute scheduled jobs and events
shaunkrnelson 0:46990814dc89 833 os_runloop();
shaunkrnelson 0:46990814dc89 834 // (not reached)
shaunkrnelson 0:46990814dc89 835 }
shaunkrnelson 0:46990814dc89 836