Senet / Senet NAMote

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

Committer:
dkjendal
Date:
Thu Aug 11 15:45:38 2016 +0000
Revision:
4:059d004186ed
Parent:
3:35e8af53c6cf
Child:
7:6a23db89f2a6
Add support for sending sensor messages

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 0:46990814dc89 775 MMA_orientation current;
shaunkrnelson 0:46990814dc89 776 int sleepTime = ORIENTATION_CHECK_PERIOD;
shaunkrnelson 0:46990814dc89 777
shaunkrnelson 0:46990814dc89 778 mma8451q.service();
shaunkrnelson 0:46990814dc89 779 current = mma8451q.getOrientation();
shaunkrnelson 0:46990814dc89 780
shaunkrnelson 0:46990814dc89 781 if(current != last)
shaunkrnelson 0:46990814dc89 782 {
shaunkrnelson 0:46990814dc89 783 last = current;
shaunkrnelson 0:46990814dc89 784 sleepTime = ORIENTATION_DEBOUNCE_TIME;
shaunkrnelson 0:46990814dc89 785 }
shaunkrnelson 0:46990814dc89 786 else
shaunkrnelson 0:46990814dc89 787 {
shaunkrnelson 0:46990814dc89 788 const bool currIsVertical = (current.left && (current.front||current.back) && !current.low);
dkjendal 4:059d004186ed 789 uint16_t new_orientation_mask = (current.left << 12) | (current.right << 8) | (current.front << 4) | current.back;
dkjendal 4:059d004186ed 790 leds_are_down = (current.right && (current.front || current.back) && !current.low);
shaunkrnelson 0:46990814dc89 791 const OperMode mode = currIsVertical ? SITE_TEST : RANGE_TEST;
dkjendal 4:059d004186ed 792
dkjendal 4:059d004186ed 793 bool send_now = new_orientation_mask != orientation_mask;
dkjendal 4:059d004186ed 794 orientation_mask = new_orientation_mask;
shaunkrnelson 0:46990814dc89 795
shaunkrnelson 0:46990814dc89 796 if(mode != operMode)
shaunkrnelson 0:46990814dc89 797 {
shaunkrnelson 0:46990814dc89 798 debug("Change to %s mode\r\n", mode==SITE_TEST?"Site":"Range");
shaunkrnelson 0:46990814dc89 799
shaunkrnelson 0:46990814dc89 800 // onEvent will start test if currently joining or transmitting
shaunkrnelson 0:46990814dc89 801 if(((LMIC.opmode & OP_JOINING) == 0) && ((LMIC.opmode & OP_TXRXPEND) == 0))
shaunkrnelson 0:46990814dc89 802 {
shaunkrnelson 0:46990814dc89 803 if(operMode != IDLE)
shaunkrnelson 0:46990814dc89 804 {
shaunkrnelson 0:46990814dc89 805 os_setCallback( &sendFrameJob, preTestStart);
shaunkrnelson 0:46990814dc89 806 }
shaunkrnelson 0:46990814dc89 807 else
shaunkrnelson 0:46990814dc89 808 {
shaunkrnelson 0:46990814dc89 809 os_setCallback( &sendFrameJob, onSendFrame);
shaunkrnelson 0:46990814dc89 810 }
shaunkrnelson 0:46990814dc89 811 }
shaunkrnelson 0:46990814dc89 812
shaunkrnelson 0:46990814dc89 813 // Set mode
shaunkrnelson 0:46990814dc89 814 operMode = mode;
shaunkrnelson 0:46990814dc89 815
shaunkrnelson 0:46990814dc89 816 // Reset test indicator LEDs
shaunkrnelson 0:46990814dc89 817 ledRed = 1;
shaunkrnelson 0:46990814dc89 818 ledGreen = 1;
shaunkrnelson 0:46990814dc89 819 ledYellow = 1;
shaunkrnelson 0:46990814dc89 820
shaunkrnelson 0:46990814dc89 821 // Reset test state
shaunkrnelson 0:46990814dc89 822 txCount = 0;
shaunkrnelson 0:46990814dc89 823 siteDr = 0;
shaunkrnelson 0:46990814dc89 824 sitePw = 0;
shaunkrnelson 0:46990814dc89 825 memset(siteAck, 0, sizeof(siteAck));
shaunkrnelson 0:46990814dc89 826 }
dkjendal 4:059d004186ed 827 else if (send_now)
dkjendal 4:059d004186ed 828 os_setCallback( &sendFrameJob, onSendFrame);
shaunkrnelson 0:46990814dc89 829 }
shaunkrnelson 0:46990814dc89 830
shaunkrnelson 0:46990814dc89 831 os_setTimedCallback( &orientationJob, os_getTime() + sec2osticks(sleepTime), orientationJobCb );
shaunkrnelson 0:46990814dc89 832 }
shaunkrnelson 0:46990814dc89 833
shaunkrnelson 0:46990814dc89 834 // Kick off initial jobs
shaunkrnelson 0:46990814dc89 835 void application_init()
shaunkrnelson 0:46990814dc89 836 {
shaunkrnelson 0:46990814dc89 837 // Start status led job
shaunkrnelson 0:46990814dc89 838 os_setCallback(&statusLedJob, statusLedCb);
shaunkrnelson 0:46990814dc89 839
shaunkrnelson 0:46990814dc89 840 // Start orientation job - Test will start once orientation is determined
shaunkrnelson 0:46990814dc89 841 os_setCallback(&orientationJob, orientationJobCb);
shaunkrnelson 0:46990814dc89 842
shaunkrnelson 0:46990814dc89 843 // Get current gps coordinates
shaunkrnelson 0:46990814dc89 844 if(gps_service() == true)
shaunkrnelson 0:46990814dc89 845 lastTxPos.set(gps.Latitude,gps.Longitude);
shaunkrnelson 0:46990814dc89 846 else
shaunkrnelson 0:46990814dc89 847 lastTxPos.set(0,0);
shaunkrnelson 0:46990814dc89 848 }
shaunkrnelson 0:46990814dc89 849
shaunkrnelson 0:46990814dc89 850
shaunkrnelson 0:46990814dc89 851 int main(void)
shaunkrnelson 0:46990814dc89 852 {
shaunkrnelson 0:46990814dc89 853 // initialize runtime env
shaunkrnelson 0:46990814dc89 854 os_init();
shaunkrnelson 0:46990814dc89 855
shaunkrnelson 0:46990814dc89 856 // initialize debug system
shaunkrnelson 0:46990814dc89 857 debug_init();
shaunkrnelson 0:46990814dc89 858
shaunkrnelson 0:46990814dc89 859 // Display build info
shaunkrnelson 0:46990814dc89 860 displayBuildInfo();
shaunkrnelson 0:46990814dc89 861
shaunkrnelson 0:46990814dc89 862 // initialize peripherals
shaunkrnelson 0:46990814dc89 863 board_peripherals_init();
shaunkrnelson 0:46990814dc89 864
shaunkrnelson 0:46990814dc89 865 // Application initialization
shaunkrnelson 0:46990814dc89 866 application_init();
shaunkrnelson 0:46990814dc89 867
shaunkrnelson 0:46990814dc89 868 // Start protocol
shaunkrnelson 0:46990814dc89 869 startLMIC();
shaunkrnelson 0:46990814dc89 870
shaunkrnelson 0:46990814dc89 871 // execute scheduled jobs and events
shaunkrnelson 0:46990814dc89 872 os_runloop();
shaunkrnelson 0:46990814dc89 873 // (not reached)
shaunkrnelson 0:46990814dc89 874 }
shaunkrnelson 0:46990814dc89 875