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:
Fri Aug 12 01:01:42 2016 +0000
Revision:
8:6757b3e3bf3d
Parent:
7:6a23db89f2a6
Child:
9:65a83f20cf3b
cleaning up orientation handling

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