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:
dkjendal
Date:
Thu Aug 25 16:54:30 2016 +0000
Revision:
14:b2c6a9dc039c
Parent:
13:89ddcc4dfc66
OSV Workshop behavior

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