Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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;
+}
--- /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;
+}
+
--- /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
--- /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
+}
--- /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
--- /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
--- /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
--- /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);
+}
--- /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 + +
--- /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];
+}
--- /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