Mobile Life IoT project using the AT&T IoT Starter Kit Software and files for my device to monitor the status or our Airstream travel trailer RV. A full description of the project is at Hackster.IO here as part of the Realtime AT&T IoT Starter Kit Challenge: https://www.hackster.io/Anubus/mobile-life-iot-9c10be
Dependencies: FXOS8700CQ MODSERIAL mbed
Revision 0:bd276b1f1249, committed 2017-04-02
- Comitter:
- Anubus
- Date:
- Sun Apr 02 12:28:21 2017 +0000
- Commit message:
- public version commit
Changed in this revision
diff -r 000000000000 -r bd276b1f1249 FXOS8700CQ.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FXOS8700CQ.lib Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/Anubus/code/FXOS8700CQ/#fb4cef1399b8
diff -r 000000000000 -r bd276b1f1249 HTS221.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTS221.h Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,108 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#ifndef HTS221_H_ +#define HTS221_H_ + +class HTS221 { +public: + HTS221(void); + int begin(void); + int activate(void); + int deactivate(void); + + int bduActivate(void); + int bduDeactivate(void); + + int readHumidity(void); + double readTemperature(void); +private: + int storeCalibration(void); + unsigned char _h0_rH, _h1_rH; + unsigned int _T0_degC, _T1_degC; + unsigned int _H0_T0, _H1_T0; + unsigned int _T0_OUT, _T1_OUT; + double _temperature; + int _humidity; + unsigned char _address; + + unsigned char readRegister(unsigned char slaveAddress, unsigned char regToRead); + int writeRegister(unsigned char slaveAddress, unsigned char regToWrite, unsigned char dataToWrite); +}; + +#define HTS221_ADDRESS 0xBF + +//Define a few of the registers that we will be accessing on the HTS221 +#define WHO_AM_I 0x0F +#define WHO_AM_I_RETURN 0xBC //This read-only register contains the device identifier, set to BCh + +#define AVERAGE_REG 0x10 // To configure humidity/temperature average. +#define AVERAGE_DEFAULT 0x1B + +/* + * [7] PD: power down control + * (0: power-down mode; 1: active mode) + * + * [6:3] Reserved + * + * [2] BDU: block data update + * (0: continuous update; 1: output registers not updated until MSB and LSB reading) +The BDU bit is used to inhibit the output register update between the reading of the upper +and lower register parts. In default mode (BDU = ?0?), the lower and upper register parts are +updated continuously. If it is not certain whether the read will be faster than output data rate, +it is recommended to set the BDU bit to ?1?. In this way, after the reading of the lower (upper) +register part, the content of that output register is not updated until the upper (lower) part is +read also. + * + * [1:0] ODR1, ODR0: output data rate selection (see table 17) + */ +#define CTRL_REG1 0x20 +#define POWER_UP 0x80 +#define BDU_SET 0x4 +#define ODR0_SET 0x1 // setting sensor reading period 1Hz + +#define CTRL_REG2 0x21 +#define CTRL_REG3 0x22 +#define REG_DEFAULT 0x00 + +#define STATUS_REG 0x27 +#define TEMPERATURE_READY 0x1 +#define HUMIDITY_READY 0x2 + +#define HUMIDITY_L_REG 0x28 +#define HUMIDITY_H_REG 0x29 +#define TEMP_L_REG 0x2A +#define TEMP_H_REG 0x2B +/* + * calibration registry should be read for temperature and humidity calculation. + * Before the first calculation of temperature and humidity, + * the master reads out the calibration coefficients. + * will do at init phase + */ +#define CALIB_START 0x30 +#define CALIB_END 0x3F +/* +#define CALIB_T0_DEGC_X8 0x32 +#define CALIB_T1_DEGC_X8 0x33 +#define CALIB_T1_T0_MSB 0x35 +#define CALIB_T0_OUT_L 0x3C +#define CALIB_T0_OUT_H 0x3D +#define CALIB_T1_OUT_L 0x3E +#define CALIB_T1_OUT_H 0x3F + */ + +#endif
diff -r 000000000000 -r bd276b1f1249 MODSERIAL.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MODSERIAL.lib Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/stefanrousseau/code/MODSERIAL/#ae4c4f174d1f
diff -r 000000000000 -r bd276b1f1249 cell_modem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cell_modem.cpp Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,350 @@ +/* =================================================================== +Copyright c 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#include "mbed.h" +#include <cctype> +#include <string> + +#include "config_me.h" +#include "wnc_control.h" +#include "hardware.h" + +#define MDM_DBG_OFF 0 +#define MDM_DBG_AT_CMDS (1 << 0) +int mdm_dbgmask = MDM_DBG_OFF; + +#define WNC_WAIT_FOR_AT_CMD_MS 40 + +DigitalOut mdm_uart2_rx_boot_mode_sel(PTC17); // on powerup, 0 = boot mode, 1 = normal boot +DigitalOut mdm_power_on(PTB9); // 0 = turn modem on, 1 = turn modem off (should be held high for >5 seconds to cycle modem) +DigitalOut mdm_wakeup_in(PTC2); // 0 = let modem sleep, 1 = keep modem awake -- Note: pulled high on shield + +DigitalOut mdm_reset(PTC12); // active high + +DigitalOut shield_3v3_1v8_sig_trans_ena(PTC4); // 0 = disabled (all signals high impedence, 1 = translation active +DigitalOut mdm_uart1_cts(PTD0); + +#define TOUPPER(a) (a) //toupper(a) + +const char ok_str[] = "OK"; +const char error_str[] = "ERROR"; + +#define MDM_OK 0 +#define MDM_ERR_TIMEOUT -1 + +#define MAX_AT_RSP_LEN 255 + +ssize_t mdm_getline(char *buff, size_t size, int timeout_ms) { + int cin = -1; + int cin_last; + + if (NULL == buff || size == 0) { + return -1; + } + + size_t len = 0; + Timer timer; + timer.start(); + while ((len < (size-1)) && (timer.read_ms() < timeout_ms)) { + if (mdm.readable()) { + cin_last = cin; + cin = mdm.getc(); + if (isprint(cin)) { + buff[len++] = (char)cin; + continue; + } else if (('\r' == cin_last) && ('\n' == cin)) { + break; + } + } +// wait_ms(1); + } + buff[len] = (char)NULL; + + return len; +} + +int mdm_sendAtCmd(const char *cmd, const char **rsp_list, int timeout_ms) { + // Per WNC wait: + wait_ms(WNC_WAIT_FOR_AT_CMD_MS); + + if (cmd && strlen(cmd) > 0) { + if (mdm_dbgmask & MDM_DBG_AT_CMDS) { + PRINTF(MAG "ATCMD: " DEF "--> " GRN "%s" DEF "\n", cmd); + } + mdm.puts(cmd); + mdm.puts("\r\n"); + } + + if (rsp_list) { + Timer timer; + char rsp[MAX_AT_RSP_LEN+1]; + int len; + + timer.start(); + while (timer.read_ms() < timeout_ms) { + len = mdm_getline(rsp, sizeof(rsp), timeout_ms - timer.read_ms()); + + if (len < 0) + return MDM_ERR_TIMEOUT; + + if (len == 0) + continue; + + if (mdm_dbgmask & MDM_DBG_AT_CMDS) { + PRINTF(MAG "ATRSP: " DEF "<-- " CYN "%s" DEF "\n", rsp); + } + + if (rsp_list) { + int rsp_idx = 0; + while (rsp_list[rsp_idx]) { + if (strcasecmp(rsp, rsp_list[rsp_idx]) == 0) { + return rsp_idx; + } else if (strncmp(rsp, "@EXTERR", 7) == 0){ + pc.printf("----- We got EXTERR ---\r\n"); + return 2; + } else if (strncmp(rsp, "+CME", 4) == 0){ + return 3; + } + rsp_idx++; + } + } + } + return MDM_ERR_TIMEOUT; + } + return MDM_OK; +} + +int mdm_init(void) { + // Hard reset the modem (doesn't go through + // the signal level translator) + mdm_reset = 0; + + // disable signal level translator (necessary + // for the modem to boot properly). All signals + // except mdm_reset go through the level translator + // and have internal pull-up/down in the module. While + // the level translator is disabled, these pins will + // be in the correct state. + shield_3v3_1v8_sig_trans_ena = 0; + + // While the level translator is disabled and ouptut pins + // are tristated, make sure the inputs are in the same state + // as the WNC Module pins so that when the level translator is + // enabled, there are no differences. + mdm_uart2_rx_boot_mode_sel = 1; // UART2_RX should be high + mdm_power_on = 0; // powr_on should be low + mdm_wakeup_in = 1; // wake-up should be high + mdm_uart1_cts = 0; // indicate that it is ok to send + + // Now, wait for the WNC Module to perform its initial boot correctly + wait(1.0); + + // The WNC module initializes comms at 115200 8N1 so set it up + mdm.baud(115200); + + //Now, enable the level translator, the input pins should now be the + //same as how the M14A module is driving them with internal pull ups/downs. + //When enabled, there will be no changes in these 4 pins... + shield_3v3_1v8_sig_trans_ena = 1; + + // Now, give the modem 60 seconds to start responding by + // sending simple 'AT' commands to modem once per second. + Timer timer; + timer.start(); + while (timer.read() < 60) { + const char * rsp_lst[] = { ok_str, error_str, NULL }; + int rc = mdm_sendAtCmd("AT", rsp_lst, 500); + if (rc == 0) + return true; //timer.read(); + wait_ms(1000 - (timer.read_ms() % 1000)); + PRINTF("\r%d",timer.read_ms()/1000); + } + return false; +} + +int mdm_sendAtCmdRsp(const char *cmd, const char **rsp_list, int timeout_ms, string * rsp, int * len) { + static char cmd_buf[3200]; // Need enough room for the WNC sockreads (over 3000 chars) + size_t n = strlen(cmd); + + // Per WNC wait: + wait_ms(WNC_WAIT_FOR_AT_CMD_MS); + + if (cmd && n > 0) { + if (mdm_dbgmask & MDM_DBG_AT_CMDS) { + PRINTF(MAG "ATCMD: " DEF "--> " GRN "%s" DEF "\n", cmd); + } +// mdm.puts(cmd); +// mdm.puts("\r\n"); + while (n--) { + mdm.putc(*cmd++); + wait_us(1000); + }; + mdm.putc('\r'); + wait_us(1000); + mdm.putc('\n'); + wait_us(1000); + } + + if (rsp_list) { + rsp->erase(); // Clean up from prior cmd response + *len = 0; + Timer timer; + timer.start(); + while (timer.read_ms() < timeout_ms) { + int lenCmd = mdm_getline(cmd_buf, sizeof(cmd_buf), timeout_ms - timer.read_ms()); + + if (lenCmd == 0) + continue; + + if (lenCmd < 0) + return MDM_ERR_TIMEOUT; + else { + *len += lenCmd; + *rsp += cmd_buf; + } + + if (mdm_dbgmask & MDM_DBG_AT_CMDS) { + PRINTF(MAG "ATRSP: " DEF "<-- " CYN "%s" DEF "\n", cmd_buf); + } + + int rsp_idx = 0; + // TODO: Test if @EXTERR:<code> + while (rsp_list[rsp_idx]) { + if (strcasecmp(cmd_buf, rsp_list[rsp_idx]) == 0) { + return rsp_idx; + } else if (strncmp(cmd_buf, "@EXTERR", 7) == 0){ + PRINTF("----- We got EXTERR ---\r\n"); + return 2; + } else if (strncmp(cmd_buf, "+CME", 4) == 0){ + return 3; + } + rsp_idx++; + } + } + return MDM_ERR_TIMEOUT; + } + + return MDM_OK; +} + +void reinitialize_mdm(void) +{ + // Initialize the modem + PRINTF(GRN "Modem RE-initializing..." DEF "\r\n"); + if (!mdm_init()) { + PRINTF(RED "\n\rModem RE-initialization failed!" DEF "\n"); + } + PRINTF("\r\n"); +} +// These are built on the fly +string MyServerIpAddress; +string MySocketData; + +//******************************************************************************************************************************************** +//* Process JSON response messages +//******************************************************************************************************************************************** +bool extract_JSON(char* search_field, char* found_string) +{ + char* beginquote; + char* endquote; + beginquote = strchr(search_field, '{'); //start of JSON + endquote = strchr(search_field, '}'); //end of JSON + if (beginquote) + { + uint16_t ifoundlen; + if (endquote) + { + ifoundlen = (uint16_t) (endquote - beginquote) + 1; + strncpy(found_string, beginquote, ifoundlen ); + found_string[ifoundlen] = 0; //null terminate + return true; + } + else + { + endquote = strchr(search_field, '\0'); //end of string... sometimes the end bracket is missing + ifoundlen = (uint16_t) (endquote - beginquote) + 1; + strncpy(found_string, beginquote, ifoundlen ); + found_string[ifoundlen] = 0; //null terminate + return false; + } + } + else + { + return false; + } +} //extract_JSON + +int cell_modem_init() +{ + int i; + + pc.baud(115200); + // Initialize the modem + PRINTF(GRN "Modem initializing... will take up to 60 seconds" DEF "\r\n"); + do { + i=mdm_init(); + if (!i) { + PRINTF(RED "Modem initialization failed!" DEF "\n"); + } + } while (!i); + + //Software init + software_init_mdm(); + + // Resolve URL to IP address to connect to + resolve_mdm(); + // Open the socket (connect to the server) + sockopen_mdm(); + return (0); +} + +int cell_modem_Sendreceive(char* tx_string, char* rx_string) +{ + int iStatus = 0; //error by default + PRINTF(DEF "\r\n"); + PRINTF(BLU "Sending to modem : %s" DEF "\r\n", &tx_string[0]); + sockwrite_mdm(&tx_string[0]); + if (sockread_mdm(&MySocketData, 1024, 20)) + { + PRINTF(DEF "\r\n"); + PRINTF(YEL "Read back : %s" DEF "\r\n", MySocketData.c_str()); + char stringToCharBuf[BUF_SIZE_FOR_N_MAX_SOCKREAD*MAX_WNC_SOCKREAD_PAYLOAD+1]; // WNC can return max of 1500 (per sockread) + if ((MySocketData.length() + 1) < sizeof(stringToCharBuf)) + { + strcpy(stringToCharBuf, MySocketData.c_str()); + if (extract_JSON(stringToCharBuf, &rx_string[0])) + { + PRINTF(GRN "JSON : %s" DEF "\n", &rx_string[0]); + iStatus = 1; //all good + } + } + else + { + PRINTF(RED "BUFFER not big enough for sock data!" DEF "\r\n"); + } + } + else + { + PRINTF(RED "No response..." DEF "\r\n"); + } + return iStatus; +} + +void display_wnc_firmware_rev(void) +{ + display_modem_firmware_version(); +} \ No newline at end of file
diff -r 000000000000 -r bd276b1f1249 cell_modem.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cell_modem.h Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,23 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#ifndef __CELL_MODEM_H_ +#define __CELL_MODEM_H_ +int cell_modem_init(); +int cell_modem_Sendreceive(char* tx_string, char* rx_string); +void display_wnc_firmware_rev(void); +#endif \ No newline at end of file
diff -r 000000000000 -r bd276b1f1249 config_me.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config_me.h Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,77 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. +======================================================= +Modified by Robert Bolling +January 2017 +for the Mobile Life IoT project + - refactored the sensor list defines to fit project +======================================================= + +======================================================================== */ + + +#ifndef __CONFIG_ME_H_ +#define __CONFIG_ME_H_ + +// User must set these for own context: + +#define BUF_SIZE_FOR_N_MAX_SOCKREAD (10) +#define MAX_WNC_SOCKREAD_PAYLOAD (1500) + +// This is the server's base URL name. Example "www.google.com" +// Note that when you Fork a FLOW, it will typically assign either +// "run-east.att.io" or "run-west.att.io", so be sure to check this. +static const char * MY_SERVER_URL = "run-east.att.io"; + +// These are FLOW fields from the Endpoints tab: +#define FLOW_BASE_URL "/your_base_url_goes_here/in/flow" +#define FLOW_INPUT_NAME "/status" + +// Unless you want to use a different protocol, this field should be left as is: +#define FLOW_URL_TYPE " HTTP/1.1\r\nHost: " + +// This identifier specifies with which FLOW device you are communicating. +// If you only have one devive there then you can just leave this as is. +// Once your FLOW device has been initialized (Virtual Device Initialize clicked), +// the Virtual Device will show up in M2X. This is its "DEVICE SERIAL" field +#define FLOW_DEVICE_NAME "mobilelife001" + +// This constant defines how often sensors are read and sent up to FLOW +#define SENSOR_UPDATE_INTERVAL_MS 30000; //30 seconds + +// Specify here how many sensor parameters you want reported to FLOW. +// You can use only the temperature and humidity from the shield HTS221 +// or you can add the reading of the FXO8700CQ motion sensor on the FRDM-K64F board +// or if you have a SiLabs PMOD plugged into the shield, you can add its proximity sensor, +// UV light, visible ambient light and infrared ambient light readings +// If you run the Windows "Sensor Simulator" utility, 8 additional virtual +// sensors can also be made available via USB. + +#define SHIELDTEMP_ACCELEROMETER_BATTERY 1 +#define SHIELDTEMP_ACCELEROMETER_BATTERY_INTRUSION 2 +#define SHIELDTEMP_ACCELEROMETER_BATTERY_GPS 3 +#define SHIELDTEMP_ACCELEROMETER_BATTERY_EXTERNALTEMP 4 +#define SHIELDTEMP_ACCELEROMETER_BATTERY_EXTERNALTEMP_GPS 5 +#define SHIELDTEMP_ACCELEROMETER_BATTERY_EXTERNALTEMP_GPS_INTRUSION 6 +static int iSensorsToReport = SHIELDTEMP_ACCELEROMETER_BATTERY_EXTERNALTEMP_GPS_INTRUSION; //modify this to change your selection + + +// This is the APN name for the cellular network, you will need to change this, check the instructions included with your SIM card kit: +static const char * MY_APN_STR = "m2m.com.attz"; + +//This is for normal HTTP. If you want to use TCP to a specific port, change that here: +static const char * MY_PORT_STR = "80"; + +#endif
diff -r 000000000000 -r bd276b1f1249 hardware.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hardware.h Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,64 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#ifndef Hardware_H_ +#define Hardware_H_ +#include "MODSERIAL.h" + +extern I2C i2c; //SDA, SCL -- define the I2C pins being used +extern MODSERIAL pc; //UART to USB host +extern MODSERIAL mdm; //UART to WNC modem +//extern SerialBuffered mdm; //UART to WNC modem + +//Un-comment the definition below if you want to use the USB rx for another purpose. +//otherwise the USB rx will be used to receive virtual sensor data from Avnet's +//"Sensor Simulator Dashboard" utility +#define USE_VIRTUAL_SENSORS + +// comment out the following line if color is not supported on the terminal +#define USE_COLOR +#ifdef USE_COLOR + #define BLK "\033[30m" + #define RED "\033[31m" + #define GRN "\033[32m" + #define YEL "\033[33m" + #define BLU "\033[34m" + #define MAG "\033[35m" + #define CYN "\033[36m" + #define WHT "\033[37m" + #define DEF "\033[39m" +#else + #define BLK + #define RED + #define GRN + #define YEL + #define BLU + #define MAG + #define CYN + #define WHT + #define DEF +#endif + +#ifdef _ULINK_PRINT +#include "itm_output.h" +#else +#define PRINTF pc.printf +#define PUTS pc.puts +#endif + + +#endif
diff -r 000000000000 -r bd276b1f1249 hts221_driver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hts221_driver.cpp Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,266 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#include "HTS221.h" + + +// ------------------------------------------------------------------------------ +//jmf -- define I2C pins and functions to read & write to I2C device + +#include <string> +#include "mbed.h" + +#include "hardware.h" +//I2C i2c(PTC11, PTC10); //SDA, SCL -- define the I2C pins being used. Defined in a +//common locatioin since sensors also use I2C + +// Read a single unsigned char from addressToRead and return it as a unsigned char +unsigned char HTS221::readRegister(unsigned char slaveAddress, unsigned char ToRead) +{ + char data = ToRead; + + //i2c.write(slaveAddress, &data, 1, 0); + i2c.write(slaveAddress, &data, 1, 1); //by Stefan + i2c.read(slaveAddress, &data, 1, 0); + return data; +} + +// Writes a single unsigned char (dataToWrite) into regToWrite +int HTS221::writeRegister(unsigned char slaveAddress, unsigned char regToWrite, unsigned char dataToWrite) +{ + const char data[] = {regToWrite, dataToWrite}; + + return i2c.write(slaveAddress,data,2,0); +} + + +//jmf end +// ------------------------------------------------------------------------------ + +//static inline int humidityReady(uint8_t data) { +// return (data & 0x02); +//} +//static inline int temperatureReady(uint8_t data) { +// return (data & 0x01); +//} + + +HTS221::HTS221(void) : _address(HTS221_ADDRESS) +{ + _temperature = 0; + _humidity = 0; +} + + +int HTS221::begin(void) +{ + uint8_t data; + + data = readRegister(_address, WHO_AM_I); + if (data == WHO_AM_I_RETURN){ + if (activate()){ + storeCalibration(); + return data; + } + } + + return 0; +} + +int +HTS221::storeCalibration(void) +{ + uint8_t data; + uint16_t tmp; + + for (int reg=CALIB_START; reg<=CALIB_END; reg++) { + if ((reg!=CALIB_START+8) && (reg!=CALIB_START+9) && (reg!=CALIB_START+4)) { + + data = readRegister(HTS221_ADDRESS, reg); + + switch (reg) { + case CALIB_START: + _h0_rH = data; + break; + case CALIB_START+1: + _h1_rH = data; + break; + case CALIB_START+2: + _T0_degC = data; + break; + case CALIB_START+3: + _T1_degC = data; + break; + + case CALIB_START+5: + tmp = _T0_degC; + _T0_degC = (data&0x3)<<8; + _T0_degC |= tmp; + + tmp = _T1_degC; + _T1_degC = ((data&0xC)>>2)<<8; + _T1_degC |= tmp; + break; + case CALIB_START+6: + _H0_T0 = data; + break; + case CALIB_START+7: + _H0_T0 |= data<<8; + break; + case CALIB_START+0xA: + _H1_T0 = data; + break; + case CALIB_START+0xB: + _H1_T0 |= data <<8; + break; + case CALIB_START+0xC: + _T0_OUT = data; + break; + case CALIB_START+0xD: + _T0_OUT |= data << 8; + break; + case CALIB_START+0xE: + _T1_OUT = data; + break; + case CALIB_START+0xF: + _T1_OUT |= data << 8; + break; + + + case CALIB_START+8: + case CALIB_START+9: + case CALIB_START+4: + //DO NOTHING + break; + + // to cover any possible error + default: + return false; + } /* switch */ + } /* if */ + } /* for */ + return true; +} + + +int +HTS221::activate(void) +{ + uint8_t data; + + data = readRegister(_address, CTRL_REG1); + data |= POWER_UP; + data |= ODR0_SET; + writeRegister(_address, CTRL_REG1, data); + + return true; +} + + +int HTS221::deactivate(void) +{ + uint8_t data; + + data = readRegister(_address, CTRL_REG1); + data &= ~POWER_UP; + writeRegister(_address, CTRL_REG1, data); + return true; +} + + +int +HTS221::bduActivate(void) +{ + uint8_t data; + + data = readRegister(_address, CTRL_REG1); + data |= BDU_SET; + writeRegister(_address, CTRL_REG1, data); + + return true; +} + + +int +HTS221::bduDeactivate(void) +{ + uint8_t data; + + data = readRegister(_address, CTRL_REG1); + data &= ~BDU_SET; + writeRegister(_address, CTRL_REG1, data); + return true; +} + + +int +HTS221::readHumidity(void) +{ + uint8_t data = 0; + uint16_t h_out = 0; + double h_temp = 0.0; + double hum = 0.0; + + data = readRegister(_address, STATUS_REG); + + if (data & HUMIDITY_READY) { + data = readRegister(_address, HUMIDITY_H_REG); + h_out = data << 8; // MSB + data = readRegister(_address, HUMIDITY_L_REG); + h_out |= data; // LSB + + // Decode Humidity + hum = ((int16_t)(_h1_rH) - (int16_t)(_h0_rH))/2.0; // remove x2 multiple + + // Calculate humidity in decimal of grade centigrades i.e. 15.0 = 150. + h_temp = (((int16_t)h_out - (int16_t)_H0_T0) * hum) / ((int16_t)_H1_T0 - (int16_t)_H0_T0); + hum = ((int16_t)_h0_rH) / 2.0; // remove x2 multiple + _humidity = (int16_t)((hum + h_temp)); // provide signed % measurement unit + } + return _humidity; +} + + + +double +HTS221::readTemperature(void) +{ + uint8_t data = 0; + uint16_t t_out = 0; + double t_temp = 0.0; + double deg = 0.0; + + data = readRegister(_address, STATUS_REG); + + if (data & TEMPERATURE_READY) { + + data= readRegister(_address, TEMP_H_REG); + t_out = data << 8; // MSB + data = readRegister(_address, TEMP_L_REG); + t_out |= data; // LSB + + // Decode Temperature + deg = ((int16_t)(_T1_degC) - (int16_t)(_T0_degC))/8.0; // remove x8 multiple + + // Calculate Temperature in decimal of grade centigrades i.e. 15.0 = 150. + t_temp = (((int16_t)t_out - (int16_t)_T0_OUT) * deg) / ((int16_t)_T1_OUT - (int16_t)_T0_OUT); + deg = ((int16_t)_T0_degC) / 8.0; // remove x8 multiple + _temperature = deg + t_temp; // provide signed celsius measurement unit + } + + return _temperature; +}
diff -r 000000000000 -r bd276b1f1249 itm_output.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/itm_output.cpp Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,91 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +//Used for ULINK output only +// + +/* ITM registers */ +#define ITM_PORT0_U8 (*((volatile unsigned int *)0xE0000000)) +#define ITM_PORT0_U32 (*((volatile unsigned long *)0xE0000000)) +#define ITM_TER (*((volatile unsigned long *)0xE0000E00)) +#define ITM_TCR (*((volatile unsigned long *)0xE0000E80)) + +#define ITM_TCR_ITMENA_Msk (1UL << 0) + +/*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 + +/*!< Variable to receive characters. */ +extern +volatile int ITM_RxBuffer; +volatile int ITM_RxBuffer = ITM_RXBUFFER_EMPTY; + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character + sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +int ITM_putc (int ch) { + if ((ITM_TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM_TER & (1UL << 0) )) { /* ITM Port #0 enabled */ + while (ITM_PORT0_U32 == 0); + ITM_PORT0_U8 = (int)ch; + } + return (ch); +} + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + This variable is monitored and altered by the debugger to provide input. + + \return Received character. + \return -1 No character pending. + */ +int ITM_getc (void) { + int ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + +/** \brief ITM send string + + The function sends a null terminated string via the external variable \ref ITM_RxBuffer. + This variable is monitored and altered by the debugger to provide input. + + \return Received character. + \return -1 No character pending. + */ +int ITM_puts (char * str) { + int i=0; + + while(str[i]) + ITM_putc(str[i++]); + return i; +} +
diff -r 000000000000 -r bd276b1f1249 itm_output.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/itm_output.h Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,31 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#ifndef __ITM_OUTPUT__ +#define __ITM_OUTPUT__ + +//This file is only used when building for ULINK output + +#define PRINTF(format, ...) { char xyz[80]; sprintf (xyz, format, ## __VA_ARGS__); ITM_puts(xyz);} +#define PUTS(st) ITM_puts((char*)st); + + +int ITM_putc (int ch); +int ITM_getc (void); +int ITM_puts ((char *) str); + +#endif
diff -r 000000000000 -r bd276b1f1249 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,271 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================= +Modified by Robert Bolling +January 2017 +for the Mobile Life IoT project + - refactored to add new sensor lists from + "config_me.h", and "sensors.cpp" +======================================================= + +======================================================================== */ + +#include "mbed.h" +#include <cctype> +#include <string> +#include "config_me.h" +#include "sensors.h" +#include "cell_modem.h" +#include "hardware.h" + +I2C i2c(PTC11, PTC10); //SDA, SCL -- define the I2C pins being used - I2C1 +MODSERIAL pc(USBTX, USBRX, 256, 256); // tx, rx with default tx, rx buffer sizes +MODSERIAL mdm(PTD3, PTD2, 4096, 4096); +DigitalOut led_green(LED_GREEN); +DigitalOut led_red(LED_RED); +DigitalOut led_blue(LED_BLUE); + + +//******************************************************************************************************************************************** +//* Create string with sensor readings that can be sent to flow as an HTTP get +//******************************************************************************************************************************************** +K64F_Sensors_t SENSOR_DATA = +{ + .Temperature = "0", + .Humidity = "0", + .AccelX = "0", + .AccelY = "0", + .AccelZ = "0", + .MagnetometerX = "0", + .MagnetometerY = "0", + .MagnetometerZ = "0", + .Temperature_Si7020 = "0", + .Humidity_Si7020 = "0", + .GPS_Satellites = "0", + .GPS_Latitude = "0", + .GPS_Longitude = "0", + .GPS_Altitude = "0", + .GPS_Speed = "0", + .GPS_Course = "0", + .Battery_Voltage = "0", + .Intrusion_Detected = "0" +}; + +void display_app_firmware_version(void) +{ + PUTS("\r\n\r\nApp Firmware: Release 1.0 - built: "__DATE__" "__TIME__"\r\n\r\n"); +} + +void GenerateModemString(char * modem_string) +{ + switch(iSensorsToReport) + { + case SHIELDTEMP_ACCELEROMETER_BATTERY: + { + sprintf(modem_string, "GET %s%s?serial=%s&temp=%s&humidity=%s&accelX=%s&accelY=%s&accelZ=%s&batt_volt=%s %s%s\r\n\r\n", FLOW_BASE_URL, FLOW_INPUT_NAME, FLOW_DEVICE_NAME, SENSOR_DATA.Temperature, SENSOR_DATA.Humidity, SENSOR_DATA.AccelX,SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ, SENSOR_DATA.Battery_Voltage, FLOW_URL_TYPE, MY_SERVER_URL); + break; + } + case SHIELDTEMP_ACCELEROMETER_BATTERY_INTRUSION: + { + sprintf(modem_string, "GET %s%s?serial=%s&temp=%s&humidity=%s&accelX=%s&accelY=%s&accelZ=%s&batt_volt=%s&intrusion=%s %s%s\r\n\r\n", FLOW_BASE_URL, FLOW_INPUT_NAME, FLOW_DEVICE_NAME, SENSOR_DATA.Temperature, SENSOR_DATA.Humidity, SENSOR_DATA.AccelX,SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ, SENSOR_DATA.Battery_Voltage, SENSOR_DATA.Intrusion_Detected, FLOW_URL_TYPE, MY_SERVER_URL); + break; + } + case SHIELDTEMP_ACCELEROMETER_BATTERY_GPS: + { + sprintf(modem_string, "GET %s%s?serial=%s&temp=%s&humidity=%s&accelX=%s&accelY=%s&accelZ=%s&batt_volt=%s&gps_satellites=%s&latitude=%s&longitude=%s&altitude=%s&speed=%s&course=%s %s%s\r\n\r\n", FLOW_BASE_URL, FLOW_INPUT_NAME, FLOW_DEVICE_NAME, SENSOR_DATA.Temperature, SENSOR_DATA.Humidity, SENSOR_DATA.AccelX,SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ, SENSOR_DATA.Battery_Voltage, SENSOR_DATA.GPS_Satellites,SENSOR_DATA.GPS_Latitude,SENSOR_DATA.GPS_Longitude,SENSOR_DATA.GPS_Altitude,SENSOR_DATA.GPS_Speed,SENSOR_DATA.GPS_Course, FLOW_URL_TYPE, MY_SERVER_URL); + break; + } + case SHIELDTEMP_ACCELEROMETER_BATTERY_EXTERNALTEMP: + { + sprintf(modem_string, "GET %s%s?serial=%s&temp=%s&humidity=%s&accelX=%s&accelY=%s&accelZ=%s&batt_volt=%s&temp2=%s&humidity2=%s %s%s\r\n\r\n", FLOW_BASE_URL, FLOW_INPUT_NAME, FLOW_DEVICE_NAME, SENSOR_DATA.Temperature, SENSOR_DATA.Humidity, SENSOR_DATA.AccelX,SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ, SENSOR_DATA.Battery_Voltage, SENSOR_DATA.Temperature_Si7020, SENSOR_DATA.Humidity_Si7020, FLOW_URL_TYPE, MY_SERVER_URL); + break; + } + case SHIELDTEMP_ACCELEROMETER_BATTERY_EXTERNALTEMP_GPS: + { + sprintf(modem_string, "GET %s%s?serial=%s&temp=%s&humidity=%s&accelX=%s&accelY=%s&accelZ=%s&batt_volt=%s&temp2=%s&humidity2=%s&gps_satellites=%s&latitude=%s&longitude=%s&altitude=%s&speed=%s&course=%s %s%s\r\n\r\n", FLOW_BASE_URL, FLOW_INPUT_NAME, FLOW_DEVICE_NAME, SENSOR_DATA.Temperature, SENSOR_DATA.Humidity, SENSOR_DATA.AccelX,SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ, SENSOR_DATA.Battery_Voltage, SENSOR_DATA.Temperature_Si7020, SENSOR_DATA.Humidity_Si7020, SENSOR_DATA.GPS_Satellites,SENSOR_DATA.GPS_Latitude,SENSOR_DATA.GPS_Longitude,SENSOR_DATA.GPS_Altitude,SENSOR_DATA.GPS_Speed,SENSOR_DATA.GPS_Course, FLOW_URL_TYPE, MY_SERVER_URL); + break; + } + case SHIELDTEMP_ACCELEROMETER_BATTERY_EXTERNALTEMP_GPS_INTRUSION: + { + sprintf(modem_string, "GET %s%s?serial=%s&temp=%s&humidity=%s&accelX=%s&accelY=%s&accelZ=%s&batt_volt=%s&temp2=%s&humidity2=%s&gps_satellites=%s&latitude=%s&longitude=%s&altitude=%s&speed=%s&course=%s&intrusion=%s %s%s\r\n\r\n", FLOW_BASE_URL, FLOW_INPUT_NAME, FLOW_DEVICE_NAME, SENSOR_DATA.Temperature, SENSOR_DATA.Humidity, SENSOR_DATA.AccelX,SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ, SENSOR_DATA.Battery_Voltage, SENSOR_DATA.Temperature_Si7020, SENSOR_DATA.Humidity_Si7020, SENSOR_DATA.GPS_Satellites,SENSOR_DATA.GPS_Latitude,SENSOR_DATA.GPS_Longitude,SENSOR_DATA.GPS_Altitude,SENSOR_DATA.GPS_Speed,SENSOR_DATA.GPS_Course, SENSOR_DATA.Intrusion_Detected, FLOW_URL_TYPE, MY_SERVER_URL); + break; + } + default: + { + sprintf(modem_string, "Invalid sensor selected\r\n\r\n"); + break; + } + } //switch(iSensorsToReport) +} //GenerateModemString + + +//Periodic timer +Ticker OneMsTicker; +volatile bool bTimerExpiredFlag = false; +int OneMsTicks = 0; +int iTimer1Interval_ms = 1000; +//******************************************************************************************************************************************** +//* Periodic 1ms timer tick +//******************************************************************************************************************************************** +void OneMsFunction() +{ + OneMsTicks++; + if ((OneMsTicks % iTimer1Interval_ms) == 0) + { + bTimerExpiredFlag = true; + } +} //OneMsFunction() + +//******************************************************************************************************************************************** +//* Set the RGB LED's Color +//* LED Color 0=Off to 7=White. 3 bits represent BGR (bit0=Red, bit1=Green, bit2=Blue) +//******************************************************************************************************************************************** +void SetLedColor(unsigned char ucColor) +{ + //Note that when an LED is on, you write a 0 to it: + led_red = !(ucColor & 0x1); //bit 0 + led_green = !(ucColor & 0x2); //bit 1 + led_blue = !(ucColor & 0x4); //bit 2 +} //SetLedColor() + +//******************************************************************************************************************************************** +//* Process the JSON response. In this example we are only extracting a LED color. +//******************************************************************************************************************************************** +bool parse_JSON(char* json_string) +{ + char* beginquote; + char token[] = "\"LED\":\""; + beginquote = strstr(json_string, token ); + if ((beginquote != 0)) + { + char cLedColor = beginquote[strlen(token)]; + PRINTF(GRN "LED Found : %c" DEF "\r\n", cLedColor); + switch(cLedColor) + { + case 'O': + { //Off + SetLedColor(0); + break; + } + case 'R': + { //Red + SetLedColor(1); + break; + } + case 'G': + { //Green + SetLedColor(2); + break; + } + case 'Y': + { //Yellow + SetLedColor(3); + break; + } + case 'B': + { //Blue + SetLedColor(4); + break; + } + case 'M': + { //Magenta + SetLedColor(5); + break; + } + case 'T': + { //Turquoise + SetLedColor(6); + break; + } + case 'W': + { //White + SetLedColor(7); + break; + } + default: + { + break; + } + } //switch(cLedColor) + return true; + } + else + { + return false; + } +} //parse_JSON + +int main() { + static unsigned ledOnce = 0; + //delay so that the debug terminal can open after power-on reset: + wait (5.0); + pc.baud(115200); + + display_app_firmware_version(); + + PRINTF(GRN "Hello World from the Cellular IoT Kit!\r\n\r\n"); + + //Initialize the I2C sensors that are present + sensors_init(); + read_sensors(); + + // Set LED to RED until init finishes + SetLedColor(0x1); //Red + // Initialize the modem + PRINTF("\r\n"); + +//TODO: comment out these next two lines for local testing (no modem send) to keep from initializing the modem + cell_modem_init(); + display_wnc_firmware_rev(); + + // Set LED BLUE for partial init + SetLedColor(0x4); //Blue + + //Create a 1ms timer tick function: + iTimer1Interval_ms = SENSOR_UPDATE_INTERVAL_MS; + OneMsTicker.attach(OneMsFunction, 0.001f) ; + + // Send and receive data perpetually + while(1) { + if (bTimerExpiredFlag) + { + bTimerExpiredFlag = false; + PRINTF("Sensor readings... \n\r"); + read_sensors(); //read available external sensors from external and on-board temp and motion sensors + PRINTF("...end sensor readings \n\r\n\r"); + + + + char modem_string[512]; + GenerateModemString(&modem_string[0]); + PRINTF(modem_string); //TODO: check what is being sent +// TODO: comment out to the next "TODO" for local testing to keep from sendng to modem + char myJsonResponse[512]; + if (cell_modem_Sendreceive(&modem_string[0], &myJsonResponse[0])) + { + if (!ledOnce) + { + ledOnce = 1; + SetLedColor(0x2); //Green + } + parse_JSON(&myJsonResponse[0]); + } +// TODO: end testing comment out section + + + } //bTimerExpiredFlag + } //forever loop +}
diff -r 000000000000 -r bd276b1f1249 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/f9eeca106725 \ No newline at end of file
diff -r 000000000000 -r bd276b1f1249 sensors.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors.cpp Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,419 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================= +Modified by Robert Bolling +January 2017 +for the Mobile Life IoT project + - refactored Si7020 to Si7021 sensor + - added voltage and intrusion sensor + - some other clean up including removing unused code + for virtual sensors and the Si1145 +======================================================= + +======================================================================== */ + +#include "mbed.h" +#include "sensors.h" +#include "hardware.h" +#include "config_me.h" +#include "FXOS8700CQ.h" +#include "HTS221.h" +#include "xadow_gps.h" +#include <string> + +#define Si7020_PMOD_I2C_ADDR 0x80 //this is for 7-bit I2C addr 0x4 for the Si7021 external sensor + +// Storage for the data from the motion sensor +SRAWDATA accel_data; +SRAWDATA magn_data; +//InterruptIn fxos_int1(PTC6); // unused, common with SW2 on FRDM-K64F +InterruptIn fxos_int2(PTC13); // should just be the Data-Ready interrupt + +bool fxos_int2_triggered = false; +void trigger_fxos_int2(void) +{ + fxos_int2_triggered = true; + +} + +#define VOLTS_SCALE 18.6 //scale battery voltage measurement based on R1 and R2 +AnalogIn Analog0(PTC0); // Had to use J1-11 for PTC0 to deconflict from wnc shield pins + + +/*------------------------------------------------------------------------------ + * Perform I2C single read. + *------------------------------------------------------------------------------*/ +unsigned char I2C_ReadSingleByte(unsigned char ucDeviceAddress) +{ + char rxbuffer [1]; + i2c.read(ucDeviceAddress, rxbuffer, 1 ); + return (unsigned char)rxbuffer[0]; +} //I2C_ReadSingleByte() + +/*------------------------------------------------------------------------------ + * Perform I2C single read from address. + *------------------------------------------------------------------------------*/ +unsigned char I2C_ReadSingleByteFromAddr(unsigned char ucDeviceAddress, unsigned char Addr) +{ + char txbuffer [1]; + char rxbuffer [1]; + txbuffer[0] = (char)Addr; + i2c.write(ucDeviceAddress, txbuffer, 1 ); + i2c.read(ucDeviceAddress, rxbuffer, 1 ); + return (unsigned char)rxbuffer[0]; +} //I2C_ReadSingleByteFromAddr() + +/*------------------------------------------------------------------------------ + * Perform I2C read of more than 1 byte. + *------------------------------------------------------------------------------*/ +int I2C_ReadMultipleBytes(unsigned char ucDeviceAddress, char *ucData, unsigned char ucLength) +{ + int status; + status = i2c.read(ucDeviceAddress, ucData, ucLength); + return status; +} //I2C_ReadMultipleBytes() + +/*------------------------------------------------------------------------------ + * Perform I2C write of a single byte. + *------------------------------------------------------------------------------*/ +int I2C_WriteSingleByte(unsigned char ucDeviceAddress, unsigned char Data, bool bSendStop) +{ + int status; + char txbuffer [1]; + txbuffer[0] = (char)Data; //data + status = i2c.write(ucDeviceAddress, txbuffer, 1, !bSendStop); //true: do not send stop + return status; +} //I2C_WriteSingleByte() + +/*------------------------------------------------------------------------------ + * Perform I2C write of 1 byte to an address. + *------------------------------------------------------------------------------*/ +int I2C_WriteSingleByteToAddr(unsigned char ucDeviceAddress, unsigned char Addr, unsigned char Data, bool bSendStop) +{ + int status; + char txbuffer [2]; + txbuffer[0] = (char)Addr; //address + txbuffer[1] = (char)Data; //data + //status = i2c.write(ucDeviceAddress, txbuffer, 2, false); //stop at end + status = i2c.write(ucDeviceAddress, txbuffer, 2, !bSendStop); //true: do not send stop + return status; +} //I2C_WriteSingleByteToAddr() + +/*------------------------------------------------------------------------------ + * Perform I2C write of more than 1 byte. + *------------------------------------------------------------------------------*/ +int I2C_WriteMultipleBytes(unsigned char ucDeviceAddress, char *ucData, unsigned char ucLength, bool bSendStop) +{ + int status; + status = i2c.write(ucDeviceAddress, ucData, ucLength, !bSendStop); //true: do not send stop + return status; +} //I2C_WriteMultipleBytes() + +//******************************************************************************************************************************************** +//* Battery Voltage +//******************************************************************************************************************************************** + +void Read_Battery_Volts(void) +{ + float Volts; + Volts = Analog0 * VOLTS_SCALE; + PRINTF("Voltage: %0.3f Volts \r\n", Volts); + sprintf(SENSOR_DATA.Battery_Voltage, "%0.2f", Volts); +} + +//******************************************************************************************************************************************** +//* Si7020/Si7021 temperature & humidity sensor +//******************************************************************************************************************************************** + +bool bSi7020_present = false; +void Init_Si7020(void) +{ + char SN_7020 [8]; + //SN part 1: + I2C_WriteSingleByteToAddr(Si7020_PMOD_I2C_ADDR, 0xFA, 0x0F, false); + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &SN_7020[0], 4); + + //SN part 1: + I2C_WriteSingleByteToAddr(Si7020_PMOD_I2C_ADDR, 0xFC, 0xC9, false); + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &SN_7020[4], 4); + + char Ver_7020 [2]; + //FW version: + I2C_WriteSingleByteToAddr(Si7020_PMOD_I2C_ADDR, 0x84, 0xB8, false); + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Ver_7020[0], 2); + + if (SN_7020[4] != 0x15) //Si7021 this is 0x15, for Si7020 this is 0x14 + { + bSi7020_present = false; + PRINTF("Si7020 sensor not found. SN=0x%02X Si7020addr=0x%02X \r\n", SN_7020[4], Si7020_PMOD_I2C_ADDR ); //TODO: take out SN print + } + else + { + bSi7020_present = true; + PRINTF("Si7020 SN = 0x%02X%02X%02X%02X%02X%02X%02X%02X \r\n", SN_7020[0], SN_7020[1], SN_7020[2], SN_7020[3], SN_7020[4], SN_7020[5], SN_7020[6], SN_7020[7]); + PRINTF("Si7020 Version# = 0x%02X \r\n", Ver_7020[0]); + } //bool bSi7020_present = true + +} //Init_Si7020() + +void Read_Si7020(void) +{ + if (bSi7020_present) + { + char Humidity [2]; + char Temperature [2]; + //Command to measure humidity (temperature also gets measured): + I2C_WriteSingleByte(Si7020_PMOD_I2C_ADDR, 0xF5, false); //no hold, must do dummy read + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Humidity[0], 1); //dummy read, should get an nack until it is done + wait (0.05); //wait for measurement. Can also keep reading until no NACK is received + //I2C_WriteSingleByte(Si7020_PMOD_I2C_ADDR, 0xE5, false); //Hold mod, the device does a clock stretch on the read until it is done (crashes the I2C bus... + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Humidity[0], 2); //read humidity + //PRINTF("Read Si7020 Humidity = 0x%02X%02X\n", Humidity[0], Humidity[1]); + int rh_code = (Humidity[0] << 8) + Humidity[1]; + float fRh = (125.0*rh_code/65536.0) - 6.0; //from datasheet + PRINTF("Si7020 Humidity = %0.1f %% \r\n", fRh); //double % sign for escape //PRINTF("%*.*f\n", myFieldWidth, myPrecision, myFloatValue); + sprintf(SENSOR_DATA.Humidity_Si7020, "%0.1f", fRh); + + //Command to read temperature when humidity is already done: + I2C_WriteSingleByte(Si7020_PMOD_I2C_ADDR, 0xE0, false); + I2C_ReadMultipleBytes(Si7020_PMOD_I2C_ADDR, &Temperature[0], 2); //read temperature + //PRINTF("Read Si7020 Temperature = 0x%02X%02X\n", Temperature[0], Temperature[1]); + int temp_code = (Temperature[0] << 8) + Temperature[1]; + float fTemp = (175.72*temp_code/65536.0) - 46.85; //from datasheet in Celcius + PRINTF("Si7020 Temperature = %0.1f deg F \r\n", CTOF(fTemp)); + sprintf(SENSOR_DATA.Temperature_Si7020, "%0.1f", CTOF(fTemp)); + } //bool bSi7020_present = true + +} //Read_Si7020() + + +//******************************************************************************************************************************************** +//* Read the FXOS8700CQ - 6-axis combo Sensor Accelerometer and Magnetometer +//******************************************************************************************************************************************** +bool bMotionSensor_present = false; +void Init_motion_sensor() +{ + // Note: this class is instantiated here because if it is statically declared, the cellular shield init kills the I2C bus... + // Class instantiation with pin names for the motion sensor on the FRDM-K64F board: + FXOS8700CQ fxos(PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); // SDA, SCL, (addr << 1) + int iWhoAmI = fxos.get_whoami(); + + PRINTF("FXOS8700CQ WhoAmI = %X\r\n", iWhoAmI); + // Iterrupt for active-low interrupt line from FXOS + // Configured with only one interrupt on INT2 signaling Data-Ready + //fxos_int2.fall(&trigger_fxos_int2); + if (iWhoAmI != 0xC7) + { + bMotionSensor_present = false; + PRINTF("FXOS8700CQ motion sensor not found\r\n"); + } + else + { + bMotionSensor_present = true; + fxos.enable(); + } +} //Init_motion_sensor() + +void Read_motion_sensor() +{ + // Note: this class is instantiated here because if it is statically declared, the cellular shield init kills the I2C bus... + // Class instantiation with pin names for the motion sensor on the FRDM-K64F board: + FXOS8700CQ fxos(PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); // SDA, SCL, (addr << 1) + if (bMotionSensor_present) + { + fxos.enable(); + fxos.get_data(&accel_data, &magn_data); + //PRINTF("Roll=%5d, Pitch=%5d, Yaw=%5d;\r\n", magn_data.x, magn_data.y, magn_data.z); + sprintf(SENSOR_DATA.MagnetometerX, "%5d", magn_data.x); + sprintf(SENSOR_DATA.MagnetometerY, "%5d", magn_data.y); + sprintf(SENSOR_DATA.MagnetometerZ, "%5d", magn_data.z); + + //Try to normalize (/2048) the values so they will match the eCompass output: + float fAccelScaled_x, fAccelScaled_y, fAccelScaled_z; + fAccelScaled_x = (accel_data.x/2048.0); + fAccelScaled_y = (accel_data.y/2048.0); + fAccelScaled_z = (accel_data.z/2048.0); + PRINTF("Acc: X=%2.3f Y=%2.3f Z=%2.3f;\r\n", fAccelScaled_x, fAccelScaled_y, fAccelScaled_z); + sprintf(SENSOR_DATA.AccelX, "%2.3f", fAccelScaled_x); + sprintf(SENSOR_DATA.AccelY, "%2.3f", fAccelScaled_y); + sprintf(SENSOR_DATA.AccelZ, "%2.3f", fAccelScaled_z); + } //bMotionSensor_present +} //Read_motion_sensor() + + +//******************************************************************************************************************************************** +//* Read the HTS221 temperature & humidity sensor on the Cellular Shield +//******************************************************************************************************************************************** +// These are to be built on the fly +string my_temp; +string my_humidity; +HTS221 hts221; + +//#define CTOF(x) ((x)*1.8+32) +bool bHTS221_present = false; +void Init_HTS221() +{ + int i; + void hts221_init(void); + i = hts221.begin(); + if (i) + { + bHTS221_present = true; + PRINTF(BLU "HTS221 Detected (0x%02X)\n\r",i); + PRINTF(" Temp is: %0.2f F \n\r",CTOF(hts221.readTemperature())); + PRINTF(" Humid is: %02d %%\n\r",hts221.readHumidity()); + } + else + { + bHTS221_present = false; + PRINTF(RED "HTS221 NOT DETECTED!\n\r"); + } +} //Init_HTS221() + +void Read_HTS221() +{ + if (bHTS221_present) + { + sprintf(SENSOR_DATA.Temperature, "%0.1f", CTOF(hts221.readTemperature())); + PRINTF("HTS221 Temp is: %0.1f F \n\r",CTOF(hts221.readTemperature())); + sprintf(SENSOR_DATA.Humidity, "%02d", hts221.readHumidity()); + PRINTF("HTS221 Humid is: %02d %%\n\r",hts221.readHumidity()); + + } //bHTS221_present +} //Read_HTS221() + +//******************************************************************************************************************************************** +//* Read the xadow gps module connedted to i2c1 +//******************************************************************************************************************************************** + +bool bGPS_present = false; +void Init_GPS(void) +{ + char scan_id[GPS_SCAN_SIZE+2]; //The first two bytes are the response length (0x00, 0x04) + I2C_WriteSingleByte(GPS_DEVICE_ADDR, GPS_SCAN_ID, true); //no hold, must do read + + unsigned char i; + for(i=0;i<(GPS_SCAN_SIZE+2);i++) + { + scan_id[i] = I2C_ReadSingleByte(GPS_DEVICE_ADDR); + } + + if(scan_id[5] != GPS_DEVICE_ID) + { + bGPS_present = false; + PRINTF("Xadow GPS not found \r\n"); + } + else + { + bGPS_present = true; + PRINTF("Xadow GPS Scan ID response = 0x%02X%02X (length), 0x%02X%02X%02X%02X\r\n", scan_id[0], scan_id[1], scan_id[2], scan_id[3], scan_id[4], scan_id[5]); + char status = gps_get_status(); + + + /* rather not wait for valid GPS before reporting sensors + if ((status != 'A') && (iSensorsToReport == TEMP_HUMIDITY_ACCELEROMETER_GPS)) + { //we must wait for GPS to initialize + PRINTF("Waiting for GPS to become ready... "); + while (status != 'A') + { + wait (5.0); + status = gps_get_status(); + unsigned char num_satellites = gps_get_sate_in_veiw(); + PRINTF("%c%d", status, num_satellites); + } + PRINTF("\r\n"); + } //we must wait for GPS to initialize + */ + + PRINTF("gps_check_online is %d\r\n", gps_check_online()); + unsigned char *data; + data = gps_get_utc_date_time(); + PRINTF("gps_get_utc_date_time : %d-%d-%d,%d:%d:%d\r\n", data[0], data[1], data[2], data[3], data[4], data[5]); + PRINTF("gps_get_status : %c ('A' = Valid, 'V' = Invalid)\r\n", gps_get_status()); + PRINTF("gps_get_latitude : %c:%f\r\n", gps_get_ns(), gps_get_latitude()); + PRINTF("gps_get_longitude : %c:%f\r\n", gps_get_ew(), gps_get_longitude()); + PRINTF("gps_get_altitude : %f meters\r\n", gps_get_altitude()); + PRINTF("gps_get_speed : %f knots\r\n", gps_get_speed()); + PRINTF("gps_get_course : %f degrees\r\n", gps_get_course()); + PRINTF("gps_get_position_fix : %c\r\n", gps_get_position_fix()); + PRINTF("gps_get_sate_in_view : %d satellites\r\n", gps_get_sate_in_veiw()); + PRINTF("gps_get_sate_used : %d\r\n", gps_get_sate_used()); + PRINTF("gps_get_mode : %c ('A' = Automatic, 'M' = Manual)\r\n", gps_get_mode()); + PRINTF("gps_get_mode2 : %c ('1' = no fix, '1' = 2D fix, '3' = 3D fix)\r\n", gps_get_mode2()); + } //bool bGPS_present = true +} //Init_GPS() + +void Read_GPS() +{ + unsigned char gps_satellites = 0; //default + int lat_sign; + int long_sign; + if (bGPS_present) + { + if ((gps_get_status() == 'A') && (gps_get_mode2() != '1')) + { + gps_satellites = gps_get_sate_in_veiw(); //show the number of satellites + } + if (gps_get_ns() == 'S') + { + lat_sign = -1; //negative number + } + else + { + lat_sign = 1; + } + if (gps_get_ew() == 'W') + { + long_sign = -1; //negative number + } + else + { + long_sign = 1; + } +#if (1) + PRINTF("gps_satellites : %d\r\n", gps_satellites); + PRINTF("gps_get_latitude : %f\r\n", (lat_sign * gps_get_latitude())); + PRINTF("gps_get_longitude : %f\r\n", (long_sign * gps_get_longitude())); + PRINTF("gps_get_altitude : %f meters\r\n", gps_get_altitude()); + PRINTF("gps_get_speed : %f knots\r\n", gps_get_speed()); + PRINTF("gps_get_course : %f degrees\r\n", gps_get_course()); +#endif + sprintf(SENSOR_DATA.GPS_Satellites, "%d", gps_satellites); + sprintf(SENSOR_DATA.GPS_Latitude, "%f", (lat_sign * gps_get_latitude())); + sprintf(SENSOR_DATA.GPS_Longitude, "%f", (long_sign * gps_get_longitude())); + sprintf(SENSOR_DATA.GPS_Altitude, "%f", gps_get_altitude()); + sprintf(SENSOR_DATA.GPS_Speed, "%f", gps_get_speed()); + sprintf(SENSOR_DATA.GPS_Course, "%f", gps_get_course()); + } //bGPS_present +} //Read_GPS() + + +void sensors_init(void) +{ + Init_HTS221(); + Init_Si7020(); + Init_motion_sensor(); + Init_GPS(); +} //sensors_init + +void read_sensors(void) +{ + Read_Battery_Volts(); + Read_HTS221(); + Read_Si7020(); + Read_motion_sensor(); + Read_GPS(); +} //read_sensors
diff -r 000000000000 -r bd276b1f1249 sensors.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors.h Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,51 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#ifndef __SENSORS_H_ +#define __SENSORS_H_ + +void sensors_init(void); +void read_sensors(void); + +#define CTOF(x) ((x)*1.8+32) + +#define SENSOR_FIELD_LEN_LIMIT 32 +typedef struct +{ + char Temperature[SENSOR_FIELD_LEN_LIMIT]; + char Humidity[SENSOR_FIELD_LEN_LIMIT]; + char AccelX[SENSOR_FIELD_LEN_LIMIT]; + char AccelY[SENSOR_FIELD_LEN_LIMIT]; + char AccelZ[SENSOR_FIELD_LEN_LIMIT]; + char MagnetometerX[SENSOR_FIELD_LEN_LIMIT]; + char MagnetometerY[SENSOR_FIELD_LEN_LIMIT]; + char MagnetometerZ[SENSOR_FIELD_LEN_LIMIT]; + char Temperature_Si7020[SENSOR_FIELD_LEN_LIMIT]; + char Humidity_Si7020[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Satellites[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Latitude[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Longitude[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Altitude[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Speed[SENSOR_FIELD_LEN_LIMIT]; + char GPS_Course[SENSOR_FIELD_LEN_LIMIT]; + char Battery_Voltage [SENSOR_FIELD_LEN_LIMIT]; + char Intrusion_Detected [SENSOR_FIELD_LEN_LIMIT]; +} K64F_Sensors_t ; + +extern K64F_Sensors_t SENSOR_DATA; + +#endif \ No newline at end of file
diff -r 000000000000 -r bd276b1f1249 wnc_control.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wnc_control.cpp Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,683 @@ +/* =================================================================== +Copyright c 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#include "mbed.h" +#include <cctype> +#include <string> +#include "config_me.h" +#include "wnc_control.h" +#include "hardware.h" + +// Outputs detailed WNC command info +#define WNC_CMD_DEBUG_ON + +// Full debug output, longer cmds and extra cellular status checking +#undef WNC_CMD_DEBUG_ON_VERBOSE + +extern string MyServerIpAddress; +extern string MySocketData; + +int reinitialize_mdm(void); + +enum WNC_ERR_e { + WNC_OK =0, + WNC_CMD_ERR = -1, + WNC_NO_RESPONSE = -2, + WNC_CELL_LINK_DOWN = -3, + WNC_EXTERR = -4 +}; + +// Contains result of last call to send_wnc_cmd(..) +WNC_ERR_e WNC_MDM_ERR = WNC_OK; + +// Contains the RAW WNC UART responses +static string wncStr; +static int socketOpen = 0; + +void software_init_mdm(void) +{ + // Temp put here to fix new boards needing init, + // the check for on the cellular network was preventing the PDNSET from happening!!!! + { + PUTS("SET APN STRING!\r\n"); + string * pRespStr; + string cmd_str("AT%PDNSET=1,"); + cmd_str += MY_APN_STR; + cmd_str += ",IP"; + at_send_wnc_cmd(cmd_str.c_str(), &pRespStr, 4*WNC_TIMEOUT_MS); // Set APN, cmd seems to take a little longer sometimes + } + + static bool reportStatus = true; + do + { + PUTS("------------ software_init_mdm! --------->\r\n"); + if (check_wnc_ready() == 0) + { + if (reportStatus == false) + { + PUTS("Re-connected to cellular network!\n\r"); + reportStatus = true; + } + + // WNC has SIM and registered on network + do + { + WNC_MDM_ERR = WNC_OK; + at_init_wnc(); + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + reinitialize_mdm(); + at_init_wnc(true); // Hard reset occurred so make it go through the software init(); + } + } while (WNC_MDM_ERR != WNC_OK); + } + else + { + if (reportStatus == true) + { + PUTS("Not connected to cellular network!\n\r"); + reportStatus = false; + } + // Atempt to re-register +// string * pRespStr; +// PUTS("Force re-register!\r\n"); +// at_send_wnc_cmd("AT+CFUN=0,0", &pRespStr, WNC_TIMEOUT_MS); +// wait_ms(31000); +// at_send_wnc_cmd("AT+CFUN=1,0", &pRespStr, WNC_TIMEOUT_MS); +// wait_ms(31000); + WNC_MDM_ERR = WNC_CELL_LINK_DOWN; + } + } while (WNC_MDM_ERR != WNC_OK); +} + +void display_modem_firmware_version(void) +{ + string * pRespStr; + + PUTS("<-------- WNC Firmware Revision --------\r\n"); + at_send_wnc_cmd("ATI", &pRespStr, WNC_TIMEOUT_MS); + PUTS(pRespStr->c_str()); + PUTS("\r\n"); + PUTS("--------------------------------------->\r\n"); +} + +void resolve_mdm(void) +{ + do + { + WNC_MDM_ERR = WNC_OK; + at_dnsresolve_wnc(MY_SERVER_URL, &MyServerIpAddress); + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + software_init_mdm(); + } + else if (WNC_MDM_ERR == WNC_CMD_ERR) + { + PUTS("Bad URL!!!!!!\r\n"); + } + } while (WNC_MDM_ERR != WNC_OK); + + PRINTF("My Server IP: %s\r\n", MyServerIpAddress.c_str()); +} + +void sockopen_mdm(void) +{ + do + { + WNC_MDM_ERR = WNC_OK; + at_sockopen_wnc(MyServerIpAddress, MY_PORT_STR); + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + software_init_mdm(); + } + else if (WNC_MDM_ERR == WNC_CMD_ERR) + PUTS("Socket open fail!!!!\r\n"); + else + socketOpen = 1; + } while (WNC_MDM_ERR != WNC_OK); +} + +void sockwrite_mdm(const char * s) +{ + if (socketOpen == 1) + { + do + { + WNC_MDM_ERR = WNC_OK; + at_sockwrite_wnc(s); + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + PUTS("Sock write no response!\r\n"); + software_init_mdm(); + } + else if (WNC_MDM_ERR == WNC_CMD_ERR) + { + PUTS("Socket Write fail!!!\r\n"); + software_init_mdm(); + }else if (WNC_MDM_ERR == WNC_EXTERR) + { + PUTS("Socket Disconnected (broken) !!!\r\n"); + sockclose_mdm(); + sockopen_mdm(); + //software_init_mdm(); + } + } while (WNC_MDM_ERR != WNC_OK); + } + else + PUTS("Socket is closed for write!\r\n"); +} + +unsigned sockread_mdm(string * sockData, int len, int retries) +{ + unsigned n = 0; + + if (socketOpen == 1) + { + do + { + WNC_MDM_ERR = WNC_OK; + n = at_sockread_wnc(sockData, len, retries); + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + if (n == 0) + software_init_mdm(); + else + PUTS("Sock read partial data!!!\r\n"); + } + else if (WNC_MDM_ERR == WNC_CMD_ERR) + PUTS("Sock read fail!!!!\r\n"); + } while (WNC_MDM_ERR == WNC_NO_RESPONSE); + } + else + { + PUTS("Socket is closed for read\r\n"); + sockData->erase(); + } + + return (n); +} + +void sockclose_mdm(void) +{ + do + { + WNC_MDM_ERR = WNC_OK; + at_sockclose_wnc(); + // Assume close happened even if it went bad + // going bad will result in a re-init anyways and if close + // fails we're pretty much in bad state and not much can do + socketOpen = 0; + if (WNC_MDM_ERR == WNC_NO_RESPONSE) + { + software_init_mdm(); + } + else if (WNC_MDM_ERR == WNC_CMD_ERR) + PUTS("Sock close fail!!!\r\n"); + } while (WNC_MDM_ERR != WNC_OK); +} + +/** + * C++ version 0.4 char* style "itoa": + * Written by Lukas Chmela + * Released under GPLv3. +*/ + +char* itoa(int value, char* result, int base) +{ + // check that the base if valid + if ( base < 2 || base > 36 ) { + *result = '\0'; + return result; + } + + char* ptr = result, *ptr1 = result, tmp_char; + int tmp_value; + + do { + tmp_value = value; + value /= base; + *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)]; + } while ( value ); + + // Apply negative sign + if ( tmp_value < 0 ) + *ptr++ = '-'; + *ptr-- = '\0'; + + while ( ptr1 < ptr ) { + tmp_char = *ptr; + *ptr-- = *ptr1; + *ptr1++ = tmp_char; + } + + return result; +} + +extern int mdm_sendAtCmdRsp(const char *cmd, const char **rsp_list, int timeout_ms, string * rsp, int * len); + +int check_wnc_ready(void) +{ + string * pRespStr; + size_t pos; + int regSts; + int cmdRes1, cmdRes2; + +#ifdef WNC_CMD_DEBUG_ON_VERBOSE + PUTS("<-------- Begin Cell Status ------------\r\n"); +#endif + cmdRes1 = at_send_wnc_cmd("AT+CSQ", &pRespStr, WNC_TIMEOUT_MS); // Check RSSI,BER + cmdRes2 = at_send_wnc_cmd("AT+CPIN?", &pRespStr, WNC_TIMEOUT_MS); // Check if SIM locked + + if ((cmdRes1 != 0) && (cmdRes2 != 0)) + { +#ifdef WNC_CMD_DEBUG_ON_VERBOSE + PUTS("------------ WNC No Response! --------->\r\n"); +#endif + return (-2); + } + + // If SIM Card not ready don't bother with commands! + if (pRespStr->find("CPIN: READY") == string::npos) + { +#ifdef WNC_CMD_DEBUG_ON_VERBOSE + PUTS("------------ WNC SIM Problem! --------->\r\n"); +#endif + return (-1); + } + + // SIM card OK, now check for signal and cellular network registration + cmdRes1 = at_send_wnc_cmd("AT+CREG?", &pRespStr, WNC_TIMEOUT_MS); // Check if registered on network + if (pRespStr->size() > 0) + { + pos = pRespStr->find("CREG: "); + if (pos != string::npos) + { + // The registration is the 2nd arg in the comma separated list + *pRespStr = pRespStr->substr(pos+8, 1); + regSts = atoi(pRespStr->c_str()); + // 1 - registered home, 5 - registered roaming + if ((regSts != 1) && (regSts != 5)) + { +#ifdef WNC_CMD_DEBUG_ON_VERBOSE + PUTS("------------ WNC Cell Link Down! ------>\r\n"); +#endif + return (-2); + } + } + +#ifdef WNC_CMD_DEBUG_ON_VERBOSE + PUTS("------------ WNC Ready ---------------->\r\n"); +#endif + } + else + { +#ifdef WNC_CMD_DEBUG_ON_VERBOSE + PUTS("------------ CREG No Reply !----------->\r\n"); +#endif + return (-2); + } + + return (0); +} + +// Sets a global with failure or success, assumes 1 thread all the time +int send_wnc_cmd(const char * s, string ** r, int ms_timeout) +{ + int cmdRes; + + if (check_wnc_ready() < 0) + { + static string noRespStr; + +#ifdef WNC_CMD_DEBUG_ON + PUTS("FAIL send cmd: "); + #ifdef WNC_CMD_DEBUG_ON_VERBOSE + PUTS(s); + PUTS("\r\n"); + #else + string truncStr(s, 50); + truncStr += "\r\n"; + PUTS(truncStr.c_str()); + #endif +#else + PUTS("FAIL send cmd!\r\n"); +#endif + + WNC_MDM_ERR = WNC_CELL_LINK_DOWN; + noRespStr.erase(); + *r = &noRespStr; + return (-3); + } + +#ifdef WNC_CMD_DEBUG_ON + #ifdef WNC_CMD_DEBUG_ON_VERBOSE + PUTS("[---------- Network Status -------------\r\n"); + #endif + string * pRespStr; + at_send_wnc_cmd("AT@SOCKDIAL?", &pRespStr, 5000); + #ifdef WNC_CMD_DEBUG_ON_VERBOSE + PUTS("---------------------------------------]\r\n"); + #endif +#endif + + // If WNC ready, send user command + cmdRes = at_send_wnc_cmd(s, r, ms_timeout); + + if (cmdRes == -1) + WNC_MDM_ERR = WNC_CMD_ERR; + + if (cmdRes == -2) + WNC_MDM_ERR = WNC_NO_RESPONSE; + + if (cmdRes == -3) { + WNC_MDM_ERR = WNC_EXTERR; + PRINTF("[[WNC_MDM_ERR = WNC_EXTERR]] \r\n"); + } + + if (cmdRes == 0) + WNC_MDM_ERR = WNC_OK; + + return (cmdRes); +} + +int at_send_wnc_cmd(const char * s, string ** r, int ms_timeout) +{ + //Eaddy + static const char * rsp_lst[] = { "OK", "ERROR","@EXTERR", "+CME", NULL }; + int len; + +#ifdef WNC_CMD_DEBUG_ON + #ifdef WNC_CMD_DEBUG_ON_VERBOSE + + #else + if (strlen(s) > 60) + { + string truncStr(s,57); + truncStr += "..."; + PRINTF("Send: <<%s>>\r\n",truncStr.c_str()); + } + else + #endif + PRINTF("Send: <<%s>>\r\n",s); +#endif + + int res = mdm_sendAtCmdRsp(s, rsp_lst, ms_timeout, &wncStr, &len); + *r = &wncStr; // Return a pointer to the static string + + if (res >= 0) + { + +#ifdef WNC_CMD_DEBUG_ON + PUTS("["); + #ifdef WNC_CMD_DEBUG_ON_VERBOSE + PUTS(wncStr.c_str()); + PUTS("]\r\n"); + #else + if (wncStr.size() < 51) + PUTS(wncStr.c_str()); + else + { + string truncStr = wncStr.substr(0,50) + "..."; + PUTS(truncStr.c_str()); + } + PUTS("]\r\n"); + #endif +#endif + +#if 0 + if (res > 0) + return -1; + else + return 0; +#else + //Eaddy added + if (res == 0) { + /* OK */ + return 0; + } else if (res == 2) { + /* @EXTERR */ + PRINTF("@EXTERR and res = %d \r\n", res); + return -3; + } else + return -1; +#endif + } + else + { + PUTS("No response from WNC!\n\r"); + return -2; + } +} + + +void at_at_wnc(void) +{ + string * pRespStr; + send_wnc_cmd("AT", &pRespStr, WNC_TIMEOUT_MS); // Heartbeat? +} + +void at_init_wnc(bool hardReset) +{ + static bool pdnSet = false; + static bool intSet = false; + static bool sockDialSet = false; + string * pRespStr; + int cmdRes; + + if (hardReset == true) + { + PUTS("Hard Reset!\r\n"); + pdnSet = false; + intSet = false; + sockDialSet = false; + } + + PUTS("Start AT init of WNC:\r\n"); + // Quick commands below do not need to check cellular connectivity + cmdRes = at_send_wnc_cmd("AT", &pRespStr, WNC_TIMEOUT_MS); // Heartbeat? + cmdRes += at_send_wnc_cmd("ATE0", &pRespStr, WNC_TIMEOUT_MS); // Echo Off + cmdRes += at_send_wnc_cmd("AT+CMEE=2", &pRespStr, WNC_TIMEOUT_MS); // 2 - verbose error, 1 - numeric error, 0 - just ERROR + + // If the simple commands are not working no chance of more complex. + // I have seen re-trying commands make it worse. + if (cmdRes < 0) + { + // Since I used the at_send_wnc_cmd I am setting the error state based upon + // the responses. And since these are simple commands, even if the WNC + // is saying ERROR, treat it like a no response. + WNC_MDM_ERR = WNC_NO_RESPONSE; + return ; + } + + if (intSet == false) + cmdRes = send_wnc_cmd("AT@INTERNET=1", &pRespStr, WNC_TIMEOUT_MS); + + if (cmdRes == 0) + intSet = true; + else + return ; + + if (pdnSet == false) + { + string cmd_str("AT%PDNSET=1,"); + cmd_str += MY_APN_STR; + cmd_str += ",IP"; + cmdRes = send_wnc_cmd(cmd_str.c_str(), &pRespStr, 4*WNC_TIMEOUT_MS); // Set APN, cmd seems to take a little longer sometimes + } + + if (cmdRes == 0) + pdnSet = true; + else + return ; + + if (sockDialSet == false) + cmdRes = send_wnc_cmd("AT@SOCKDIAL=1", &pRespStr, WNC_TIMEOUT_MS); + + if (cmdRes == 0) + sockDialSet = true; + else + return ; + + PUTS("SUCCESS: AT init of WNC!\r\n"); +} + +void at_sockopen_wnc(const string & ipStr, const char * port ) +{ + string * pRespStr; + send_wnc_cmd("AT@SOCKCREAT=1", &pRespStr, WNC_TIMEOUT_MS); + string cmd_str("AT@SOCKCONN=1,\""); + cmd_str += ipStr; + cmd_str += "\","; + cmd_str += port; + cmd_str += ",30"; + int cmd = send_wnc_cmd(cmd_str.c_str(), &pRespStr, 31000); + if (cmd != WNC_OK) { + // Per WNC: re-close even if open fails! + at_sockclose_wnc(); + } +} + +void at_sockclose_wnc(void) +{ + string * pRespStr; + send_wnc_cmd("AT@SOCKCLOSE=1", &pRespStr, WNC_TIMEOUT_MS); +} + +int at_dnsresolve_wnc(const char * s, string * ipStr) +{ + string * pRespStr; + string str(s); + str = "AT@DNSRESVDON=\"" + str + "\""; + if (send_wnc_cmd(str.c_str(), &pRespStr, 60000) == 0) + { + size_t pos_start = pRespStr->find(":\"") + 2; + size_t pos_end = pRespStr->find("\"", pos_start) - 1; + if ((pos_start != string::npos) && (pos_end != string::npos)) + { + if (pos_end > pos_start) + { + // Make a copy for use later (the source string is re-used) + *ipStr = pRespStr->substr(pos_start, pos_end - pos_start + 1); + return 1; + } + else + PUTS("URL Resolve fail, substr Err\r\n"); + } + else + PUTS("URL Resolve fail, no quotes\r\n"); + } + else + PUTS("URL Resolve fail, WNC cmd fail\r\n"); + + *ipStr = "192.168.0.1"; + + return -1; +} + +void at_sockwrite_wnc(const char * s) +{ + string * pRespStr; + char num2str[6]; + size_t sLen = strlen(s); + int res; + if (sLen <= 1500) + { + string cmd_str("AT@SOCKWRITE=1,"); + itoa(sLen, num2str, 10); + cmd_str += num2str; + cmd_str += ",\""; + while(*s != '\0') + { + itoa((int)*s++, num2str, 16); + // Always 2-digit ascii hex: + if (strlen(num2str) == 1) + { + num2str[2] = '\0'; + num2str[1] = num2str[0]; + num2str[0] = '0'; + } + cmd_str += num2str; + } + cmd_str += "\""; + res = send_wnc_cmd(cmd_str.c_str(), &pRespStr, 120000); + if (res == -3) + PUTS("sockwrite is disconnect \r\n"); + } + else + PUTS("sockwrite Err, string to long\r\n"); +} + +unsigned at_sockread_wnc(string * pS, unsigned n, unsigned retries = 0) +{ + unsigned i, numBytes = 0; + string * pRespStr; + string cmd_str("AT@SOCKREAD=1,"); + + // Clean slate + pS->erase(); + + if (n <= 1500) + { + char num2str[6]; + + itoa(n, num2str, 10); + cmd_str += num2str; + retries += 1; + while (retries--) + { + // Assuming someone is sending then calling this to receive response, invoke + // a pause to give the response some time to come back and then also + // between each retry. + wait_ms(10); + + if (send_wnc_cmd(cmd_str.c_str(), &pRespStr, WNC_TIMEOUT_MS) == 0) + { + size_t pos_start = pRespStr->find("\"") + 1; + size_t pos_end = pRespStr->rfind("\"") - 1; + + // Make sure search finds what it's looking for! + if (pos_start != string::npos && pos_end != string::npos) + i = (pos_end - pos_start + 1); // Num hex chars, 2 per byte + else + i = 0; + + if (i > 0) + { + retries = 1; // If any data found retry 1 more time to catch data that might be in another + // WNC payload + string byte; + while (pos_start < pos_end) + { + byte = pRespStr->substr(pos_start, 2); + *pS += (char)strtol(byte.c_str(), NULL, 16); + pos_start += 2; + } + numBytes += i/2; + } + } + else + { + PUTS("no readsock reply!\r\n"); + return (0); + } + } + } + else + PUTS("sockread Err, to many to read\r\n"); + + return (numBytes); +}
diff -r 000000000000 -r bd276b1f1249 wnc_control.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wnc_control.h Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,48 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#ifndef __WNC_CONTROL_H_ +#define __WNC_CONTROL_H_ + +static const unsigned WNC_TIMEOUT_MS = 10000; + +// Core function that sends data to the WNC UART +extern int send_wnc_cmd(const char * s, string ** r, int ms_timeout); + +// Low level command functions +extern void at_init_wnc(bool hardReset = false); +extern void at_sockopen_wnc(const string & ipStr, const char * port ); +extern void at_sockclose_wnc(void); +extern int at_dnsresolve_wnc(const char * s, string * ipStr); +extern void at_sockwrite_wnc(const char * s); +extern unsigned at_sockread_wnc(string * pS, unsigned n, unsigned retries); +extern void at_at_wnc(void); +extern int at_send_wnc_cmd(const char * s, string ** r, int ms_timeout); +extern int check_wnc_ready(void); + +// High level functions that attempt to correct for things going bad with the WNC +extern void software_init_mdm(void); +extern void resolve_mdm(void); +extern void sockopen_mdm(void); +extern void sockwrite_mdm(const char * s); +extern unsigned sockread_mdm(string * sockData, int len, int retries); +extern void sockclose_mdm(void); +extern void display_modem_firmware_version(void); + +#endif + +
diff -r 000000000000 -r bd276b1f1249 xadow_gps.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xadow_gps.cpp Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,303 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#include "mbed.h" +#include "xadow_gps.h" +#include "hardware.h" + +// Xadow code based on Eclipse test project at +// https://github.com/WayenWeng/Xadow_GPS_v2_test/ + +// These first 3 routines are to allow the mbed I2C to be used instead of what was in the Eclipse test code +void dlc_i2c_configure(int slave_addr, int speed) +{ +} //dlc_i2c_configure + +unsigned char dlc_i2c_receive_byte(void) +{ + char rxbuffer [1]; + i2c.read(GPS_DEVICE_ADDR, rxbuffer, 1 ); + return (unsigned char)rxbuffer[0]; +} //dlc_i2c_receive_byte() + +unsigned char dlc_i2c_send_byte(unsigned char ucData) +{ + int status; + char txbuffer [1]; + txbuffer[0] = (char)ucData; + status = i2c.write(GPS_DEVICE_ADDR, txbuffer, 1, false); //true: do not send stop + return status; +} //dlc_i2c_send_byte() + + +unsigned char gps_check_online(void) +{ + unsigned char data[GPS_SCAN_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_SCAN_ID); + + for(i=0;i<(GPS_SCAN_SIZE+2);i++) + { + data[i] = dlc_i2c_receive_byte(); + } + + if(data[5] == GPS_DEVICE_ID) + return 1; + else return 0; +} + +unsigned char gps_utc_date_time[GPS_UTC_DATE_TIME_SIZE] = {0}; + +unsigned char* gps_get_utc_date_time(void) +{ + unsigned char data[GPS_UTC_DATE_TIME_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_UTC_DATE_TIME_ID); + + for(i=0;i<(GPS_UTC_DATE_TIME_SIZE+2);i++) + { + data[i] = dlc_i2c_receive_byte(); + } + + for(i=0;i<GPS_UTC_DATE_TIME_SIZE;i++) + gps_utc_date_time[i] = data[i+2]; + + return gps_utc_date_time; +} + +unsigned char gps_get_status(void) +{ + unsigned char data[GPS_STATUS_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_STATUS_ID); + for(i=0;i<(GPS_STATUS_SIZE+2);i++) + { + data[i] = dlc_i2c_receive_byte(); + } + + return data[2]; +} + +float gps_get_latitude(void) +{ + char data[GPS_LATITUDE_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_LATITUDE_ID); + for(i=0;i<(GPS_LATITUDE_SIZE+2);i++) + { + data[i] = (char)dlc_i2c_receive_byte(); + } + + return atof(&data[2]); +} + +unsigned char gps_get_ns(void) +{ + unsigned char data[GPS_NS_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_NS_ID); + for(i=0;i<(GPS_NS_SIZE+2);i++) + { + data[i] = dlc_i2c_receive_byte(); + } + + if(data[2] == 'N' || data[2] == 'S')return data[2]; + else return data[2] = '-'; + +} + +float gps_get_longitude(void) +{ + char data[GPS_LONGITUDE_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_LONGITUDE_ID); + for(i=0;i<(GPS_LONGITUDE_SIZE+2);i++) + { + data[i] = (char)dlc_i2c_receive_byte(); + } + + return atof(&data[2]); +} + +unsigned char gps_get_ew(void) +{ + unsigned char data[GPS_EW_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_EW_ID); + for(i=0;i<(GPS_EW_SIZE+2);i++) + { + data[i] = dlc_i2c_receive_byte(); + } + + if(data[2] == 'E' || data[2] == 'W')return data[2]; + else return data[2] = '-'; +} + +float gps_get_speed(void) +{ + char data[GPS_SPEED_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_SPEED_ID); + for(i=0;i<(GPS_SPEED_SIZE+2);i++) + { + data[i] = (char)dlc_i2c_receive_byte(); + } + + return atof(&data[2]); +} + +float gps_get_course(void) +{ + char data[GPS_COURSE_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_COURSE_ID); + for(i=0;i<(GPS_COURSE_SIZE+2);i++) + { + data[i] = (char)dlc_i2c_receive_byte(); + } + + return atof(&data[2]); +} + +unsigned char gps_get_position_fix(void) +{ + unsigned char data[GPS_POSITION_FIX_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_POSITION_FIX_ID); + for(i=0;i<(GPS_POSITION_FIX_SIZE+2);i++) + { + data[i] = dlc_i2c_receive_byte(); + } + + return data[2]; +} + +unsigned char gps_get_sate_used(void) +{ + unsigned char data[GPS_SATE_USED_SIZE+2]; + unsigned char i; + unsigned char value; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_SATE_USED_ID); + for(i=0;i<(GPS_SATE_USED_SIZE+2);i++) + { + data[i] = dlc_i2c_receive_byte(); + } + + if(data[3] >= '0' && data[3] <= '9')value = (data[3] - '0') * 10; + else value = 0; + if(data[2] >= '0' && data[2] <= '9')value += (data[2] - '0'); + else value += 0; + + return value; +} + +float gps_get_altitude(void) +{ + char data[GPS_ALTITUDE_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_ALTITUDE_ID); + for(i=0;i<(GPS_ALTITUDE_SIZE+2);i++) + { + data[i] = (char)dlc_i2c_receive_byte(); + } + + return atof(&data[2]); +} + +unsigned char gps_get_mode(void) +{ + unsigned char data[GPS_MODE_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_MODE_ID); + for(i=0;i<(GPS_MODE_SIZE+2);i++) + { + data[i] = dlc_i2c_receive_byte(); + } + + return data[2]; +} + +unsigned char gps_get_mode2(void) +{ + unsigned char data[GPS_MODE2_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_MODE2_ID); + for(i=0;i<(GPS_MODE2_SIZE+2);i++) + { + data[i] = dlc_i2c_receive_byte(); + } + + return data[2]; +} + +unsigned char gps_get_sate_in_veiw(void) +{ + unsigned char data[GPS_SATE_IN_VIEW_SIZE+2]; + unsigned char i; + + dlc_i2c_configure(GPS_DEVICE_ADDR, 100); + + dlc_i2c_send_byte(GPS_SATE_IN_VIEW_ID); + for(i=0;i<(GPS_SATE_IN_VIEW_SIZE+2);i++) + { + data[i] = dlc_i2c_receive_byte(); + } + + return data[2]; +}
diff -r 000000000000 -r bd276b1f1249 xadow_gps.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xadow_gps.h Sun Apr 02 12:28:21 2017 +0000 @@ -0,0 +1,280 @@ +/* =================================================================== +Copyright © 2016, AVNET Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the License for the specific +language governing permissions and limitations under the License. + +======================================================================== */ + +#ifndef __XADOW_GPS_H_ +#define __XADOW_GPS_H_ + +/*! + \def GPS_DEVICE_ADDR + The I2C address GPS + + \def GPS_SCAN_ID + The id of scan data, the format is 0,0,0,Device address + \def GPS_SCAN_SIZE + The length of scan data + + \def GPS_UTC_DATE_TIME_ID + The id of utc date and time, the format is YMDHMS + \def GPS_UTC_DATE_TIME_SIZE + The length of utc date and time data + + \def GPS_STATUS_ID + The id of GPS status, the format is A/V + \def GPS_STATUS_SIZE + The length of GPS status data + + \def GPS_LATITUDE_ID + The id of latitude, the format is dd.dddddd + \def GPS_LATITUDE_SIZE + The length of latitude data + + \def GPS_NS_ID + The id of latitude direction, the format is N/S + \def GPS_NS_SIZE + The length of latitude direction data + + \def GPS_LONGITUDE_ID + The id of longitude, the format is ddd.dddddd + \def GPS_LONGITUDE_SIZE + The length of longitude data + + \def GPS_EW_ID + The id of longitude direction, the format is E/W + \def GPS_EW_SIZE + The length of longitude direction data + + \def GPS_SPEED_ID + The id of speed, the format is 000.0~999.9 Knots + \def GPS_SPEED_SIZE + The length of speed data + + \def GPS_COURSE_ID + The id of course, the format is 000.0~359.9 + \def GPS_COURSE_SIZE + The length of course data + + \def GPS_POSITION_FIX_ID + The id of position fix status, the format is 0,1,2,6 + \def GPS_POSITION_FIX_SIZE + The length of position fix status data + + \def GPS_SATE_USED_ID + The id of state used, the format is 00~12 + \def GPS_SATE_USED_SIZE + The length of sate used data + + \def GPS_ALTITUDE_ID + The id of altitude, the format is -9999.9~99999.9 + \def GPS_ALTITUDE_SIZE + The length of altitude data + + \def GPS_MODE_ID + The id of locate mode, the format is A/M + \def GPS_MODE_SIZE + The length of locate mode data + + \def GPS_MODE2_ID + The id of current status, the format is 1,2,3 + \def GPS_MODE2_SIZE + The length of current status data + + \def GPS_SATE_IN_VIEW_ID + The id of sate in view + \def GPS_SATE_IN_VIEW_SIZE + The length of sate in view data +*/ + +/* Data format: + * ID(1 byte), Data length(1 byte), Data 1, Data 2, ... Data n (n bytes, n = data length) + * For example, get the scan data. + * First, Send GPS_SCAN_ID(1 byte) to device. + * Second, Receive scan data(ID + Data length + GPS_SCAN_SIZE = 6 bytes). + * Third, The scan data begin from the third data of received. + * End + */ + +#define GPS_DEVICE_ID 0x05 +//#define GPS_DEVICE_ADDR 0x05 +#define GPS_DEVICE_ADDR 0x0A //For mbed, the address has to be << 1 + +#define GPS_SCAN_ID 0 // 4 bytes +#define GPS_SCAN_SIZE 4 // 0,0,0,Device address + +#define GPS_UTC_DATE_TIME_ID 1 // YMDHMS +#define GPS_UTC_DATE_TIME_SIZE 6 // 6 bytes + +#define GPS_STATUS_ID 2 // A/V +#define GPS_STATUS_SIZE 1 // 1 byte + +#define GPS_LATITUDE_ID 3 // dd.dddddd +#define GPS_LATITUDE_SIZE 9 // 9 bytes + +#define GPS_NS_ID 4 // N/S +#define GPS_NS_SIZE 1 // 1 byte + +#define GPS_LONGITUDE_ID 5 // ddd.dddddd +#define GPS_LONGITUDE_SIZE 10 // 10 bytes + +#define GPS_EW_ID 6 // E/W +#define GPS_EW_SIZE 1 // 1 byte + +#define GPS_SPEED_ID 7 // 000.0~999.9 Knots +#define GPS_SPEED_SIZE 5 // 5 bytes + +#define GPS_COURSE_ID 8 // 000.0~359.9 +#define GPS_COURSE_SIZE 5 // 5 bytes + +#define GPS_POSITION_FIX_ID 9 // 0,1,2,6 +#define GPS_POSITION_FIX_SIZE 1 // 1 byte + +#define GPS_SATE_USED_ID 10 // 00~12 +#define GPS_SATE_USED_SIZE 2 // 2 bytes + +#define GPS_ALTITUDE_ID 11 // -9999.9~99999.9 +#define GPS_ALTITUDE_SIZE 7 // 7 bytes + +#define GPS_MODE_ID 12 // A/M +#define GPS_MODE_SIZE 1 // 1 byte + +#define GPS_MODE2_ID 13 // 1,2,3 +#define GPS_MODE2_SIZE 1 // 1 byte + +#define GPS_SATE_IN_VIEW_ID 14 // 0~12 +#define GPS_SATE_IN_VIEW_SIZE 1 // 1 byte + + +/** + * \brief Get the status of the device. + * + * \return Return TRUE or FALSE. TRUE is on line, FALSE is off line. + * + */ +unsigned char gps_check_online(void); + +/** + * \brief Get the utc date and time. + * + * \return Return the pointer of utc date sand time, the format is YMDHMS. + * + */ +unsigned char* gps_get_utc_date_time(void); + +/** + * \brief Get the status of GPS. + * + * \return Return A or V. A is orientation, V is navigation. + * + */ +unsigned char gps_get_status(void); + +/** + * \brief Get the altitude. + * + * \return Return altitude data. The format is dd.dddddd. + * + */ +float gps_get_latitude(void); + +/** + * \brief Get the lattitude direction. + * + * \return Return lattitude direction data. The format is N/S. N is north, S is south. + * + */ +unsigned char gps_get_ns(void); + +/** + * \brief Get the longitude. + * + * \return Return longitude data. The format is ddd.dddddd. + * + */ +float gps_get_longitude(void); + +/** + * \brief Get the longitude direction. + * + * \return Return longitude direction data. The format is E/W. E is east, W is west. + * + */ +unsigned char gps_get_ew(void); + +/** + * \brief Get the speed. + * + * \return Return speed data. The format is 000.0~999.9 Knots. + * + */ +float gps_get_speed(void); + +/** + * \brief Get the course. + * + * \return Return course data. The format is 000.0~359.9. + * + */ +float gps_get_course(void); + +/** + * \brief Get the status of position fix. + * + * \return Return position fix data. The format is 0,1,2,6. + * + */ +unsigned char gps_get_position_fix(void); + +/** + * \brief Get the number of state used¡£ + * + * \return Return number of state used. The format is 0-12. + * + */ +unsigned char gps_get_sate_used(void); + +/** + * \brief Get the altitude¡£ the format is -9999.9~99999.9 + * + * \return Return altitude data. The format is -9999.9~99999.9. + * + */ +float gps_get_altitude(void); + +/** + * \brief Get the mode of location. + * + * \return Return mode of location. The format is A/M. A:automatic, M:manual. + * + */ +unsigned char gps_get_mode(void); + +/** + * \brief Get the current status of GPS. + * + * \return Return current status. The format is 1,2,3. 1:null, 2:2D, 3:3D. + * + */ +unsigned char gps_get_mode2(void); + +/** + * \brief Get the number of sate in view. + * + * \return Return the number of sate in view. + * + */ +unsigned char gps_get_sate_in_veiw(void); + +#endif \ No newline at end of file