Added a GPIO to power on/off for external I2C sensor(s) (with LEDs)

Dependencies:   UniGraphic mbed vt100

18-Jun-2018 外部センサの電源オン・オフ機能は下位互換の為に無効になっていました。 この版で再度有効にしました。

Files at this revision

API Documentation at this revision

Comitter:
Rhyme
Date:
Fri Apr 13 04:19:23 2018 +0000
Child:
1:8d65cfc3a2e2
Commit message:
power to color sensor on/off test OK. Currently the function is disabled.

Changed in this revision

UniGraphic.lib Show annotated file Show diff for this revision Revisions of this file
afLib/Command.cpp Show annotated file Show diff for this revision Revisions of this file
afLib/Command.h Show annotated file Show diff for this revision Revisions of this file
afLib/StatusCommand.cpp Show annotated file Show diff for this revision Revisions of this file
afLib/StatusCommand.h Show annotated file Show diff for this revision Revisions of this file
afLib/afErrors.h Show annotated file Show diff for this revision Revisions of this file
afLib/afLib.cpp Show annotated file Show diff for this revision Revisions of this file
afLib/afLib.h Show annotated file Show diff for this revision Revisions of this file
afLib/afSPI.h Show annotated file Show diff for this revision Revisions of this file
afLib/iafLib.h Show annotated file Show diff for this revision Revisions of this file
afLib/msg_types.h Show annotated file Show diff for this revision Revisions of this file
af_utils/af_attriburtes.cpp Show annotated file Show diff for this revision Revisions of this file
af_utils/af_attributes.h Show annotated file Show diff for this revision Revisions of this file
af_utils/af_mgr.cpp Show annotated file Show diff for this revision Revisions of this file
af_utils/af_mgr.h Show annotated file Show diff for this revision Revisions of this file
af_utils/mbedSPI.cpp Show annotated file Show diff for this revision Revisions of this file
af_utils/mbedSPI.h Show annotated file Show diff for this revision Revisions of this file
af_utils/pending.cpp Show annotated file Show diff for this revision Revisions of this file
af_utils/pending.h Show annotated file Show diff for this revision Revisions of this file
edge_sensor/edge_accel.cpp Show annotated file Show diff for this revision Revisions of this file
edge_sensor/edge_accel.h Show annotated file Show diff for this revision Revisions of this file
edge_sensor/edge_color.cpp Show annotated file Show diff for this revision Revisions of this file
edge_sensor/edge_color.h Show annotated file Show diff for this revision Revisions of this file
edge_sensor/edge_pressure.cpp Show annotated file Show diff for this revision Revisions of this file
edge_sensor/edge_pressure.h Show annotated file Show diff for this revision Revisions of this file
edge_sensor/edge_sensor.cpp Show annotated file Show diff for this revision Revisions of this file
edge_sensor/edge_sensor.h Show annotated file Show diff for this revision Revisions of this file
edge_sensor/edge_temp.cpp Show annotated file Show diff for this revision Revisions of this file
edge_sensor/edge_temp.h Show annotated file Show diff for this revision Revisions of this file
edge_utils/KL25Z_SystemInit.c Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_chart.cpp Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_chart.h Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_mgr.cpp Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_mgr.h Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_pin.h Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_reset_mgr.cpp Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_reset_mgr.h Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_time.cpp Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_time.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
sensors/LM75B.cpp Show annotated file Show diff for this revision Revisions of this file
sensors/LM75B.h Show annotated file Show diff for this revision Revisions of this file
sensors/MMA8451Q.cpp Show annotated file Show diff for this revision Revisions of this file
sensors/MMA8451Q.h Show annotated file Show diff for this revision Revisions of this file
sensors/PSE530.cpp Show annotated file Show diff for this revision Revisions of this file
sensors/PSE530.h Show annotated file Show diff for this revision Revisions of this file
sensors/SMTC502AT.cpp Show annotated file Show diff for this revision Revisions of this file
sensors/SMTC502AT.h Show annotated file Show diff for this revision Revisions of this file
sensors/VEML6040.cpp Show annotated file Show diff for this revision Revisions of this file
sensors/VEML6040.h Show annotated file Show diff for this revision Revisions of this file
vt100.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UniGraphic.lib	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/La-Suno/code/UniGraphic/#1a148973febe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib/Command.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,269 @@
+/**
+ * Copyright 2015 Afero, 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.
+ */
+
+//wsugi #include "Arduino.h"
+#include "mbed.h"
+#include <stdio.h>
+#include "Command.h"
+#include "msg_types.h"
+
+#define SERIAL_PRINT_DBG_ASR_ON 0
+
+#define CMD_HDR_LEN  4    // 4 byte header on all commands
+#define CMD_VAL_LEN  2    // 2 byte value length for commands that have a value
+
+const char *CMD_NAMES[] = {"SET   ", "GET   ", "UPDATE"};
+
+
+Command::Command(uint16_t len, uint8_t *bytes) {
+    int index = 0;
+
+    _cmd = bytes[index++];
+    _requestId = bytes[index++];
+    _attrId = bytes[index + 0] | bytes[index + 1] << 8;
+    index += 2;
+
+    if (_cmd == MSG_TYPE_GET) {
+        return;
+    }
+    if (_cmd == MSG_TYPE_UPDATE) {
+        _status = bytes[index++];
+        _reason = bytes[index++];
+    }
+
+    _valueLen = bytes[index + 0] | bytes[index + 1] << 8;
+    index += 2;
+    _value = new uint8_t[_valueLen];
+    for (int i = 0; i < _valueLen; i++) {
+        _value[i] = bytes[index + i];
+    }
+}
+
+Command::Command(uint8_t requestId, const char *str) {
+    _requestId = requestId & 0xff;
+
+    char *cp; //wsugi = strdup(str);
+//wsugi 00 start    
+    {
+        int length = strlen(str)+1;
+        cp = (char*)malloc(length);
+        strcpy(cp,str);
+    }
+//wsugi 00 end
+    char *tok = strtok(cp, " ");
+    _cmd = strToCmd(tok);
+
+    tok = strtok(NULL, " ");
+    _attrId = strToAttrId(tok);
+
+    if (_cmd == MSG_TYPE_GET) {
+        _valueLen = 0;
+        _value = NULL;
+    } else {
+        tok = strtok(NULL, " ");
+        _valueLen = strlen(tok) / 2;
+        _value = new uint8_t[_valueLen];
+        strToValue(tok, _value);
+    }
+
+    free(cp);
+}
+
+Command::Command(uint8_t requestId, uint8_t cmd, uint16_t attrId) {
+    _requestId = requestId;
+    _cmd = cmd;
+    _attrId = attrId;
+    _valueLen = 0;
+    _value = NULL;
+}
+
+Command::Command(uint8_t requestId, uint8_t cmd, uint16_t attrId, uint16_t valueLen, uint8_t *value) {
+    _requestId = requestId;
+    _cmd = cmd;
+    _attrId = attrId;
+    _valueLen = valueLen;
+    _value = new uint8_t[_valueLen];
+    memcpy(_value, value, valueLen);
+}
+
+Command::Command(uint8_t requestId, uint8_t cmd, uint16_t attrId, uint8_t status, uint8_t reason, uint16_t valueLen,
+                 uint8_t *value) {
+    _requestId = requestId;
+    _cmd = cmd;
+    _attrId = attrId;
+    _status = status;
+    _reason = reason;
+    _valueLen = valueLen;
+    _value = new uint8_t[_valueLen];
+    memcpy(_value, value, valueLen);
+}
+
+Command::Command() {
+}
+
+Command::~Command() {
+    if (_value != NULL) {
+        delete[] _value; //wsugi delete (_value);
+    }
+}
+
+int Command::strToValue(char *valueStr, uint8_t *value) {
+    for (int i = 0; i < (int) (strlen(valueStr) / 2); i++) {
+        int j = i * 2;
+        value[i] = getVal(valueStr[j + 1]) + (getVal(valueStr[j]) << 4);
+    }
+
+    return 0;
+}
+
+uint16_t Command::strToAttrId(char *attrIdStr) {
+    return atoi(attrIdStr);
+    //return String(attrIdStr).toInt();
+}
+
+uint8_t Command::strToCmd(char *cmdStr) {
+    char c = cmdStr[0];
+    if (c == 'g' || c == 'G') {
+        return MSG_TYPE_GET;
+    } else if (c == 's' || c == 'S') {
+        return MSG_TYPE_SET;
+    } else if (c == 'u' || c == 'U') {
+        return MSG_TYPE_UPDATE;
+    }
+
+    return 0xFF ;
+}
+
+uint8_t Command::getCommand() {
+    return _cmd;
+}
+
+uint8_t Command::getReqId() {
+    return _requestId;
+}
+
+uint16_t Command::getAttrId() {
+    return _attrId;
+}
+
+uint16_t Command::getValueLen() {
+    return _valueLen;
+}
+
+void Command::getValue(uint8_t *value) {
+    for (int i = 0; i < _valueLen; i++) {
+        value[i] = _value[i];
+    }
+}
+
+uint8_t *Command::getValueP() {
+    return _value;
+}
+
+uint16_t Command::getSize() {
+    uint16_t len = CMD_HDR_LEN;
+
+    if (_cmd != MSG_TYPE_GET) {
+        len += CMD_VAL_LEN + _valueLen;
+    }
+
+    if (_cmd == MSG_TYPE_UPDATE) {
+        len += 2; // status byte + reason byte
+    }
+
+    return len;
+}
+
+uint16_t Command::getBytes(uint8_t *bytes) {
+    uint16_t len = getSize();
+
+    int index = 0;
+
+    bytes[index++] = (_cmd);
+
+    bytes[index++] = (_requestId);
+
+    bytes[index++] = (_attrId & 0xff);
+    bytes[index++] = ((_attrId >> 8) & 0xff);
+
+    if (_cmd == MSG_TYPE_GET) {
+        return len;
+    }
+
+    if (_cmd == MSG_TYPE_UPDATE) {
+        bytes[index++] = (_status);
+        bytes[index++] = (_reason);
+    }
+
+    bytes[index++] = (_valueLen & 0xff);
+    bytes[index++] = ((_valueLen >> 8) & 0xff);
+
+    for (int i = 0; i < _valueLen; i++) {
+        bytes[index++] = (_value[i]);
+    }
+
+    return len;
+}
+
+bool Command::isValid() {
+    return (_cmd == MSG_TYPE_SET) || (_cmd == MSG_TYPE_GET) || (_cmd == MSG_TYPE_UPDATE);
+}
+
+void Command::dumpBytes() {
+#if SERIAL_PRINT_DBG_ASR_ON
+    uint16_t len = getSize();
+    uint8_t bytes[len];
+    getBytes(bytes);
+
+    _printBuf[0] = 0;
+    sprintf(_printBuf, "len: %d value: ", len);
+    for (int i = 0; i < len; i++) {
+        int b = bytes[i] & 0xff;
+        sprintf(&_printBuf[strlen(_printBuf)], "%02x", b);
+    }
+    printf("%s\n",_printBuf);
+#endif
+}
+
+void Command::dump() {
+#if SERIAL_PRINT_DBG_ASR_ON
+    _printBuf[0] = 0;
+    sprintf(_printBuf, "cmd: %s attr: %d value: ",
+            CMD_NAMES[_cmd - MESSAGE_CHANNEL_BASE - 1],
+            _attrId
+    );
+    if (_cmd != MSG_TYPE_GET) {
+        for (int i = 0; i < _valueLen; i++) {
+            int b = _value[i] & 0xff;
+            sprintf(&_printBuf[strlen(_printBuf)], "%02x", b);
+        }
+    }
+    printf("%s\n",_printBuf);
+#endif
+}
+
+uint8_t Command::getVal(char c) {
+    if (c >= '0' && c <= '9')
+        return (uint8_t)(c - '0');
+    else if (c >= 'A' && c <= 'F')
+        return (uint8_t)(c - 'A' + 10);
+    else if (c >= 'a' && c <= 'f')
+        return (uint8_t)(c - 'a' + 10);
+
+    printf("bad hex char: %c\n",c);
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib/Command.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,94 @@
+/**
+ * Copyright 2015 Afero, 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 COMMAND_H__
+#define COMMAND_H__
+
+#include "mbed.h" //wsugi
+#include <string> //wsugi
+
+using namespace std; //wsugi
+
+#define SPI_CMD_MAX_LEN  256
+
+#define UPDATE_REASON_UNKNOWN               0
+#define UPDATE_REASON_LOCAL_UPDATE          1
+#define UPDATE_REASON_SERVICE_SET           2
+#define UPDATE_REASON_MCU_SET               3
+#define UPDATE_REASON_RELINK                4
+#define UPDATE_REASON_REBOOT                5
+
+class Command {
+public:
+    Command(uint16_t len, uint8_t *bytes);
+
+    Command(uint8_t requestId, const char *str);
+
+    Command(uint8_t requestId, uint8_t cmd, uint16_t attrId);
+
+    Command(uint8_t requestId, uint8_t cmd, uint16_t attrId, uint16_t valueLen, uint8_t *value);
+
+    Command(uint8_t requestId, uint8_t cmd, uint16_t attrId, uint8_t status, uint8_t reason, uint16_t valueLen,
+            uint8_t *value);
+
+    Command();
+
+    ~Command();
+
+    uint8_t getCommand();
+
+    uint8_t getReqId();
+
+    uint16_t getAttrId();
+
+    uint16_t getValueLen();
+
+    void getValue(uint8_t *value);
+
+    uint8_t *getValueP();
+
+    uint16_t getSize();
+
+    uint16_t getBytes(uint8_t *bytes);
+
+    bool isValid();
+
+    void dump();
+
+    void dumpBytes();
+
+private:
+    uint8_t getVal(char c);
+    int strToValue(char *valueStr, uint8_t *value);
+
+    uint8_t strToCmd(char *cmdStr);
+
+    uint16_t strToAttrId(char *attrIdStr);
+
+    uint16_t _len;
+    uint8_t _cmd;
+    uint8_t _requestId;
+    uint16_t _attrId;
+    uint8_t _status;
+    uint8_t _reason;
+    uint16_t _valueLen;
+    uint8_t *_value;
+
+    char _printBuf[256];
+
+};
+
+#endif // COMMAND_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib/StatusCommand.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,135 @@
+/**
+ * Copyright 2015 Afero, 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 "StatusCommand.h"
+
+#define SERIAL_PRINT_DBG_ASR_ON 0
+
+StatusCommand::StatusCommand(uint16_t bytesToSend) {
+    _cmd = 0x30;
+    _bytesToSend = bytesToSend;
+    _bytesToRecv = 0;
+}
+
+StatusCommand::StatusCommand() {
+    _cmd = 0x30;
+    _bytesToSend = 0;
+    _bytesToRecv = 0;
+}
+
+StatusCommand::~StatusCommand() {
+}
+
+uint16_t StatusCommand::getSize() {
+    return sizeof(_cmd) + sizeof(_bytesToSend) + sizeof(_bytesToRecv);
+}
+
+uint16_t StatusCommand::getBytes(int *bytes) {
+    int index = 0;
+
+    bytes[index++] = (_cmd);
+    bytes[index++] = (_bytesToSend & 0xff);
+    bytes[index++] = ((_bytesToSend >> 8) & 0xff);
+    bytes[index++] = (_bytesToRecv & 0xff);
+    bytes[index++] = ((_bytesToRecv >> 8) & 0xff);
+
+    return index;
+}
+
+uint8_t StatusCommand::calcChecksum() {
+    uint8_t result = 0;
+
+    result += (_cmd);
+    result += (_bytesToSend & 0xff);
+    result += ((_bytesToSend >> 8) & 0xff);
+    result += (_bytesToRecv & 0xff);
+    result += ((_bytesToRecv >> 8) & 0xff);
+
+    return result;
+}
+
+void StatusCommand::setChecksum(uint8_t checksum) {
+    _checksum = checksum;
+}
+
+uint8_t StatusCommand::getChecksum() {
+    uint8_t result = 0;
+
+    result += (_cmd);
+    result += (_bytesToSend & 0xff);
+    result += ((_bytesToSend >> 8) & 0xff);
+    result += (_bytesToRecv & 0xff);
+    result += ((_bytesToRecv >> 8) & 0xff);
+
+    return result;
+}
+
+void StatusCommand::setAck(bool ack) {
+    _cmd = ack ? 0x31 : 0x30;
+}
+
+void StatusCommand::setBytesToSend(uint16_t bytesToSend) {
+    _bytesToSend = bytesToSend;
+}
+
+uint16_t StatusCommand::getBytesToSend() {
+    return _bytesToSend;
+}
+
+void StatusCommand::setBytesToRecv(uint16_t bytesToRecv) {
+    _bytesToRecv = bytesToRecv;
+}
+
+uint16_t StatusCommand::getBytesToRecv() {
+    return _bytesToRecv;
+}
+
+bool StatusCommand::equals(StatusCommand *statusCommand) {
+    return (_cmd == statusCommand->_cmd && _bytesToSend == statusCommand->_bytesToSend &&
+            _bytesToRecv == statusCommand->_bytesToRecv);
+}
+
+bool StatusCommand::isValid() {
+    return (_checksum == calcChecksum()) && (_cmd == 0x30 || _cmd == 0x31);
+}
+
+void StatusCommand::dumpBytes() {
+#if SERIAL_PRINT_DBG_ASR_ON
+    int len = getSize();
+    int bytes[len];
+    getBytes(bytes);
+
+    printf("len  : %d\n",len);
+    printf("data : ");
+    for (int i = 0; i < len; i++) {
+        if (i > 0) {
+            printf(", ");
+        }
+        int b = bytes[i] & 0xff;
+        printf("0x%02x", b) ;
+    }
+    printf("\n") ;
+#endif
+}
+
+void StatusCommand::dump() {
+#if SERIAL_PRINT_DBG_ASR_ON
+    printf("cmd              : %s\n",_cmd == 0x30 ? "STATUS" : "STATUS_ACK");
+    printf("bytes to send    : %d\n",_bytesToSend);
+    printf("bytes to receive : %d\n",_bytesToRecv);
+#endif
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib/StatusCommand.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,67 @@
+/**
+ * Copyright 2015 Afero, 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 STATUS_COMMAND_H__
+#define STATUS_COMMAND_H__
+
+#include "mbed.h"
+
+class StatusCommand {
+public:
+
+    StatusCommand();
+
+    StatusCommand(uint16_t bytesToSend);
+
+    ~StatusCommand();
+
+    uint16_t getSize();
+
+    uint16_t getBytes(int *bytes);
+
+    uint8_t calcChecksum();
+
+    void setChecksum(uint8_t checksum);
+
+    uint8_t getChecksum();
+
+    void setAck(bool ack);
+
+    void setBytesToSend(uint16_t bytesToSend);
+
+    uint16_t getBytesToSend();
+
+    void setBytesToRecv(uint16_t bytesToRecv);
+
+    uint16_t getBytesToRecv();
+
+    bool equals(StatusCommand *statusCommand);
+
+    bool isValid();
+
+    void dump();
+
+    void dumpBytes();
+
+private:
+
+    uint8_t     _cmd;
+    uint16_t    _bytesToSend;
+    uint16_t    _bytesToRecv;
+    uint8_t     _checksum;
+};
+
+#endif // STATUS_COMMAND_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib/afErrors.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2015 Afero, 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 AF_ERRORS_H__
+#define AF_ERRORS_H__
+
+#define afSUCCESS                    0    // Operation completed successfully
+#define afERROR_NO_SUCH_ATTRIBUTE   -1    // Request was made for unknown attribute id
+#define afERROR_BUSY                -2    // Request already in progress, try again
+#define afERROR_INVALID_COMMAND     -3    // Command could not be parsed
+#define afERROR_QUEUE_OVERFLOW      -4    // Queue is full
+#define afERROR_QUEUE_UNDERFLOW     -5    // Queue is empty
+#define afERROR_INVALID_PARAM       -6    // Bad input parameter
+
+#endif // AF_ERRORS_H__
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib/afLib.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,958 @@
+/**
+ * Copyright 2015 Afero, 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 "afLib.h"
+#include "afErrors.h"
+#include "msg_types.h"
+/* added by Motoo Tanaka on 26-Dec-2017 for watchdog */
+#include "edge_reset_mgr.h" 
+
+#define IS_MCU_ATTR(x) (x >= 0 && x < 1024)
+
+static iafLib *_iaflib = NULL;
+
+#define MAX_SYNC_RETRIES    10
+static long lastSync = 0;
+static int syncRetries = 0;
+
+/**
+ * create
+ *
+ * The public constructor for the afLib. This allows us to create the afLib object once and hold a reference to it.
+ */
+iafLib *iafLib::create(PinName mcuInterrupt, isr isrWrapper,
+        onAttributeSet attrSet, onAttributeSetComplete attrSetComplete, afSPI *theSPI)
+{
+    if (_iaflib == NULL) {
+        _iaflib = new afLib( mcuInterrupt, isrWrapper, attrSet, attrSetComplete, theSPI);
+    }
+
+    return _iaflib;
+}
+
+void iafLib::destroy()
+{
+    afLib *p = (afLib*)_iaflib;
+    delete p;
+    _iaflib = NULL;
+}
+
+/**
+ * getRequestId 
+ * by Motoo Tanaka on 16-Nov-2017
+ */
+int afLib::getRequestId(void) 
+{
+    return( _requestId ) ;
+}
+
+/**
+ * afLib
+ *
+ * The private constructor for the afLib. This one actually initializes the afLib and prepares it for use.
+ */
+afLib::afLib(PinName mcuInterrupt, isr isrWrapper,
+    onAttributeSet attrSet, onAttributeSetComplete attrSetComplete, afSPI *theSPI) : fco(mcuInterrupt)
+{
+    checkLastSync = new Timer();
+    checkLastSync->start();
+    queueInit();
+    _theSPI= theSPI;
+    _request.p_value = NULL;
+
+    //_spiSettings = SPISettings(1000000, LSBFIRST, SPI_MODE0);
+    _interrupts_pending = 0;
+    _state = STATE_IDLE;
+
+    _writeCmd = NULL;
+    _writeCmdOffset = 0;
+
+    _outstandingSetGetAttrId = 0;
+
+    _readCmd = NULL;
+    _readCmdOffset = 0;
+    _readBufferLen = 0;
+
+    _txStatus = new StatusCommand();
+    _rxStatus = new StatusCommand();
+
+    _onAttrSet = attrSet;
+    _onAttrSetComplete = attrSetComplete;
+    _theSPI->begin();
+
+    // AJS where does this get moved to??
+    #ifdef ARDUINO
+    pinMode(mcuInterrupt, INPUT);
+    attachInterrupt(mcuInterrupt, isrWrapper, FALLING);
+    #endif
+    fco.fall(isrWrapper);
+    printf("afLib init done!!\n");
+}
+//wsugi 20161128
+afLib::~afLib()
+{
+    printf("deleted\n");
+    if(_readBuffer != NULL)
+    {
+        delete[] (_readBuffer);
+        _readBuffer = NULL;
+    }
+    
+    if(_writeBuffer != NULL)
+    {
+        delete[] (_writeBuffer);
+        _writeBuffer = NULL;
+    }
+    
+    if(_readCmd != NULL)
+    {
+        delete (_readCmd);
+        _readCmd = NULL;
+    }
+    
+    if(_writeCmd != NULL)
+    {
+        delete (_writeCmd);
+        _writeCmd = NULL;
+    }
+    
+    if(_txStatus != NULL)
+    {
+        delete (_txStatus);
+        _txStatus = NULL;
+    }
+    
+    if(_rxStatus != NULL)
+    {
+        delete (_rxStatus);
+        _rxStatus = NULL;
+    }
+    
+    for (int i = 0; i < REQUEST_QUEUE_SIZE; i++)
+    {
+        if (_requestQueue[i].p_value != NULL)
+        {
+            delete[] (_requestQueue[i].p_value);
+            _requestQueue[i].p_value = NULL;
+        }
+    }
+    
+    if(checkLastSync != NULL)
+    {
+        delete (checkLastSync);
+        checkLastSync = NULL;
+    }
+    
+    _iaflib = NULL;
+}
+//wsugi 20161128
+/**
+ * loop
+ *
+ * This is how the afLib gets time to run its state machine. This method should be called periodically from the
+ * loop() function of the Arduino sketch.
+ * This function pulls pending attribute operations from the queue. It takes approximately 4 calls to loop() to
+ * complete one attribute operation.
+ */
+void afLib::loop(void) {
+    reset_watch_dog() ; /* 26-Dec-2017 by Motoo Tanaka */
+    if (isIdle() && (queueGet(&_request.messageType, &_request.requestId, &_request.attrId, &_request.valueLen,
+                              &_request.p_value) == afSUCCESS)) {
+        switch (_request.messageType) {
+            case MSG_TYPE_GET:
+                doGetAttribute(_request.requestId, _request.attrId);
+                break;
+
+            case MSG_TYPE_SET:
+                doSetAttribute(_request.requestId, _request.attrId, _request.valueLen, _request.p_value);
+                break;
+
+            case MSG_TYPE_UPDATE:
+                doUpdateAttribute(_request.requestId, _request.attrId, 0, _request.valueLen, _request.p_value);
+                break;
+
+            default:
+                printf("%s\n","loop: request type!");
+        }
+    }
+
+    if (_request.p_value != NULL) {
+        delete[] (_request.p_value); //wsugi delete (_request.p_value);
+        _request.p_value = NULL;
+    }
+    runStateMachine();
+}
+
+/**
+ * updateIntsPending
+ *
+ * Interrupt-safe method for updating the interrupt count. This is called to increment and decrement the interrupt count
+ * as interrupts are received and handled.
+ */
+void afLib::updateIntsPending(int amount) {
+//    fco.disable_irq();
+    __disable_irq() ; // Disable Interrupts
+    _interrupts_pending += amount;
+    __enable_irq() ; // Enable Interrupts
+//    fco.enable_irq();
+}
+
+/**
+ * sendCommand
+ *
+ * This increments the interrupt count to kick off the state machine in the next call to loop().
+ */
+/**
+ * In this fucntion, only disable/enable fco irq is enough
+ */
+void afLib::sendCommand(void) {
+    fco.disable_irq(); 
+    if (_interrupts_pending == 0 && _state == STATE_IDLE) {
+        updateIntsPending(1);
+    }
+    fco.enable_irq();
+}
+
+/**
+ * getAttribute
+ *
+ * The public getAttribute method. This method queues the operation and returns immediately. Applications must call
+ * loop() for the operation to complete.
+ */
+int afLib::getAttribute(const uint16_t attrId) {
+    _requestId++;
+    uint8_t dummy; // This value isn't actually used.
+//    return queuePut(MSG_TYPE_GET, _requestId++, attrId, 0, &dummy);
+    return queuePut(MSG_TYPE_GET, _requestId, attrId, 0, &dummy); /* by moto on 17-Nov-2017 */
+}
+
+/**
+ * The many moods of setAttribute
+ *
+ * These are the public versions of the setAttribute method.
+ * These methods queue the operation and return immediately. Applications must call loop() for the operation to complete.
+ */
+int afLib::setAttributeBool(const uint16_t attrId, const bool value) {
+    _requestId++;
+    uint8_t val = value ? 1 : 0;
+    return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(val),
+                    (uint8_t *)&val);
+}
+
+int afLib::setAttribute8(const uint16_t attrId, const int8_t value) {
+    _requestId++;
+    return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value),
+                    (uint8_t *)&value);
+}
+
+int afLib::setAttribute16(const uint16_t attrId, const int16_t value) {
+    _requestId++;
+    return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value),
+                    (uint8_t *) &value);
+}
+
+int afLib::setAttribute32(const uint16_t attrId, const int32_t value) {
+    _requestId++;
+    return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value),
+                    (uint8_t *) &value);
+}
+
+int afLib::setAttribute64(const uint16_t attrId, const int64_t value) {
+    _requestId++;
+    return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value),
+                    (uint8_t *) &value);
+}
+
+int afLib::setAttribute(const uint16_t attrId, const string &value) {
+    _requestId++;
+    return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, value.length(),
+                    (uint8_t *) value.c_str());
+}
+
+int afLib::setAttribute(const uint16_t attrId, const uint16_t valueLen, const char *value) {
+    if (valueLen > MAX_ATTRIBUTE_SIZE) {
+        return afERROR_INVALID_PARAM;
+    }
+
+    if (value == NULL) {
+        return afERROR_INVALID_PARAM;
+    }
+
+    _requestId++;
+    return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, valueLen,
+                    (const uint8_t *) value);
+}
+
+int afLib::setAttribute(const uint16_t attrId, const uint16_t valueLen, const uint8_t *value) {
+    if (valueLen > MAX_ATTRIBUTE_SIZE) {
+        return afERROR_INVALID_PARAM;
+    }
+
+    if (value == NULL) {
+        return afERROR_INVALID_PARAM;
+    }
+
+    _requestId++;
+    return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, valueLen, value);
+}
+
+int afLib::setAttributeComplete(uint8_t requestId, const uint16_t attrId, const uint16_t valueLen, const uint8_t *value) {
+    if (valueLen > MAX_ATTRIBUTE_SIZE) {
+        return afERROR_INVALID_PARAM;
+    }
+
+    if (value == NULL) {
+        return afERROR_INVALID_PARAM;
+    }
+
+    return queuePut(MSG_TYPE_UPDATE, requestId, attrId, valueLen, value);
+}
+
+/**
+ * doGetAttribute
+ *
+ * The private version of getAttribute. This version actually calls sendCommand() to kick off the state machine and
+ * execute the operation.
+ */
+int afLib::doGetAttribute(uint8_t requestId, uint16_t attrId) {
+    if (_interrupts_pending > 0 || _writeCmd != NULL) {
+        return afERROR_BUSY;
+    }
+
+    _writeCmd = new Command(requestId, MSG_TYPE_GET, attrId);
+    if (!_writeCmd->isValid()) {
+        printf("getAttribute invalid command:");
+        _writeCmd->dumpBytes();
+        _writeCmd->dump();
+        delete (_writeCmd);
+        _writeCmd = NULL;
+        return afERROR_INVALID_COMMAND;
+    }
+
+    _outstandingSetGetAttrId = attrId;
+
+    // Start the transmission.
+    sendCommand();
+
+    return afSUCCESS;
+}
+
+/**
+ * doSetAttribute
+ *
+ * The private version of setAttribute. This version actually calls sendCommand() to kick off the state machine and
+ * execute the operation.
+ */
+int afLib::doSetAttribute(uint8_t requestId, uint16_t attrId, uint16_t valueLen, uint8_t *value) {
+    if (_interrupts_pending > 0 || _writeCmd != NULL) {
+        return afERROR_BUSY;
+    }
+    _writeCmd = new Command(requestId, MSG_TYPE_SET, attrId, valueLen, value);
+    if (!_writeCmd->isValid()) {
+        printf("setAttributeComplete invalid command:");
+        _writeCmd->dumpBytes();
+        _writeCmd->dump();
+        delete (_writeCmd);
+        _writeCmd = NULL;
+        return afERROR_INVALID_COMMAND;
+    }
+
+    _outstandingSetGetAttrId = attrId;
+
+    // Start the transmission.
+    sendCommand();
+
+    return afSUCCESS;
+}
+
+/**
+ * doUpdateAttribute
+ *
+ * setAttribute calls on MCU attributes turn into updateAttribute calls. See documentation on the SPI protocol for
+ * more information. This method calls sendCommand() to kick off the state machine and execute the operation.
+ */
+int afLib::doUpdateAttribute(uint8_t requestId, uint16_t attrId, uint8_t status, uint16_t valueLen, uint8_t *value) {
+    if (_interrupts_pending > 0 || _writeCmd != NULL) {
+        return afERROR_BUSY;
+    }
+
+    _writeCmd = new Command(requestId, MSG_TYPE_UPDATE, attrId, status, 3 /* MCU Set it */, valueLen, value);
+    if (!_writeCmd->isValid()) {
+        printf("updateAttribute invalid command:");
+        _writeCmd->dumpBytes();
+        _writeCmd->dump();
+        delete (_writeCmd);
+        return afERROR_INVALID_COMMAND;
+    }
+
+    // Start the transmission.
+    sendCommand();
+
+    return afSUCCESS;
+}
+
+/**
+ * parseCommand
+ *
+ * A debug method for parsing a string into a command. This is not required for library operation and is only supplied
+ * as an example of how to execute attribute operations from a command line interface.
+ */
+#ifdef ATTRIBUTE_CLI
+int afLib::parseCommand(const char *cmd) {
+    if (_interrupts_pending > 0 || _writeCmd != NULL) {
+        _theLog->print("Busy: ");
+        _theLog->print(_interrupts_pending);
+        _theLog->print(", ");
+        _theLog->println(_writeCmd != NULL);
+        return afERROR_BUSY;
+    }
+
+    int reqId = _requestId++;
+    _writeCmd = new Command(_theLog,reqId, cmd);
+    if (!_writeCmd->isValid()) {
+        _theLog->print("BAD: ");
+        _theLog->println(cmd);
+        _writeCmd->dumpBytes();
+        _writeCmd->dump();
+        delete (_writeCmd);
+        _writeCmd = NULL;
+        return afERROR_INVALID_COMMAND;
+    }
+
+    // Start the transmission.
+    sendCommand();
+
+    return afSUCCESS;
+}
+#endif
+
+/**
+ * runStateMachine
+ *
+ * The state machine for afLib. This state machine is responsible for implementing the KSP SPI protocol and executing
+ * attribute operations.
+ * This method is run:
+ *      1. In response to receiving an interrupt from the ASR-1.
+ *      2. When an attribute operation is pulled out of the queue and executed.
+ */
+void afLib::runStateMachine(void) {
+    if (_interrupts_pending > 0) {
+        switch (_state) {
+            case STATE_IDLE:
+                //deathWish.attach(&afLib::kick_the_bucket,10);
+                onStateIdle();
+                return;
+
+            case STATE_STATUS_SYNC:
+                onStateSync();
+                break;
+
+            case STATE_STATUS_ACK:
+                onStateAck();
+                break;
+
+            case STATE_SEND_BYTES:
+                onStateSendBytes();
+                break;
+
+            case STATE_RECV_BYTES:
+                onStateRecvBytes();
+                break;
+
+            case STATE_CMD_COMPLETE:
+                onStateCmdComplete();
+                break;
+        }
+
+        updateIntsPending(-1);
+    } else {
+        if (syncRetries > 0 && syncRetries < MAX_SYNC_RETRIES && checkLastSync->read_ms() - lastSync > 1000) {
+            updateIntsPending(1);
+        } else if (syncRetries >= MAX_SYNC_RETRIES) {
+            printf("No response from ASR-1 - does profile have MCU enabled?\n");
+#if defined(TARGET_KL25Z)
+//            WatchDogWrapper::getSelf()->kick_the_bucket();
+#endif //TARGET_KL25Z
+            syncRetries = 0;
+            _state = STATE_IDLE;
+        }
+    }
+}
+
+/**
+ * onStateIdle
+ *
+ * If there is a command to be written, update the bytes to send. Otherwise we're sending a zero-sync message.
+ * Either way advance the state to send a sync message.
+ */
+void afLib::onStateIdle(void) {
+    if (_writeCmd != NULL) {
+        // Include 2 bytes for length
+        _bytesToSend = _writeCmd->getSize() + 2;
+    } else {
+        _bytesToSend = 0;
+    }
+    _state = STATE_STATUS_SYNC;
+    printState(_state);
+}
+
+/**
+ * onStateSync
+ *
+ * Write a sync message over SPI to let the ASR-1 know that we want to send some data.
+ * Check for a "collision" which occurs if the ASR-1 is trying to send us data at the same time.
+ */
+void afLib::onStateSync(void) {
+    int result;
+
+    _txStatus->setAck(false);
+    _txStatus->setBytesToSend(_bytesToSend);
+    _txStatus->setBytesToRecv(0);
+
+    result = exchangeStatus(_txStatus, _rxStatus);
+    
+    if (result == afSUCCESS && _rxStatus->isValid() && inSync(_txStatus, _rxStatus)) {
+        syncRetries = 0;   // Flag that sync completed.
+        _state = STATE_STATUS_ACK;
+        if (_txStatus->getBytesToSend() == 0 && _rxStatus->getBytesToRecv() > 0) {
+            _bytesToRecv = _rxStatus->getBytesToRecv();
+        }
+    } else {
+        // Try resending the preamble
+        _state = STATE_STATUS_SYNC;
+        lastSync = checkLastSync->read_ms();
+        syncRetries++;
+//          _txStatus->dumpBytes();
+//          _rxStatus->dumpBytes();
+    }
+    printState(_state);
+}
+
+/**
+ * onStateAck
+ *
+ * Acknowledge the previous sync message and advance the state.
+ * If there are bytes to send, advance to send bytes state.
+ * If there are bytes to receive, advance to receive bytes state.
+ * Otherwise it was a zero-sync so advance to command complete.
+ */
+void afLib::onStateAck(void) {
+    int result;
+
+    _txStatus->setAck(true);
+    _txStatus->setBytesToRecv(_rxStatus->getBytesToRecv());
+    _bytesToRecv = _rxStatus->getBytesToRecv();
+    result = writeStatus(_txStatus);
+    if (result != afSUCCESS) {
+        _state = STATE_STATUS_SYNC;
+        printState(_state);
+        return;
+    }
+    if (_bytesToSend > 0) {
+        _writeBufferLen = (uint16_t) _writeCmd->getSize();
+        _writeBuffer = new uint8_t[_bytesToSend];
+        memcpy(_writeBuffer, (uint8_t * ) & _writeBufferLen, 2);
+        _writeCmd->getBytes(&_writeBuffer[2]);
+        _state = STATE_SEND_BYTES;
+    } else if (_bytesToRecv > 0) {
+        _state = STATE_RECV_BYTES;
+    } else {
+        _state = STATE_CMD_COMPLETE;
+    }
+    printState(_state);
+}
+
+/**
+ * onStateSendBytes
+ *
+ * Send the required number of bytes to the ASR-1 and then advance to command complete.
+ */
+void afLib::onStateSendBytes(void) {
+//        _theLog->print("send bytes: "); _theLog->println(_bytesToSend);
+    sendBytes();
+
+    if (_bytesToSend == 0) {
+        _writeBufferLen = 0;
+        delete[] (_writeBuffer); //wsugi delete (_writeBuffer);
+        _writeBuffer = NULL;
+        _state = STATE_CMD_COMPLETE;
+        printState(_state);
+    }
+}
+
+/**
+ * onStateRecvBytes
+ *
+ * Receive the required number of bytes from the ASR-1 and then advance to command complete.
+ */
+void afLib::onStateRecvBytes(void) {
+//        _theLog->print("receive bytes: "); _theLog->println(_bytesToRecv);
+    recvBytes();
+    if (_bytesToRecv == 0) {
+        _state = STATE_CMD_COMPLETE;
+        printState(_state);
+        _readCmd = new Command(_readBufferLen, &_readBuffer[2]);
+        delete[] (_readBuffer); //wsugi delete (_readBuffer);
+        _readBuffer = NULL;
+    }
+}
+
+/**
+ * onStateCmdComplete
+ *
+ * Call the appropriate sketch callback to report the result of the command.
+ * Clear the command object and go back to waiting for the next interrupt or command.
+ */
+void afLib::onStateCmdComplete(void) {
+    _state = STATE_IDLE;
+    printState(_state);
+    if (_readCmd != NULL) {
+        uint8_t *val = new uint8_t[_readCmd->getValueLen()];
+        _readCmd->getValue(val);
+
+        switch (_readCmd->getCommand()) {
+            case MSG_TYPE_SET:
+                _onAttrSet(_readCmd->getReqId(), _readCmd->getAttrId(), _readCmd->getValueLen(), val);
+                break;
+
+            case MSG_TYPE_UPDATE:
+                if (_readCmd->getAttrId() == _outstandingSetGetAttrId) {
+                    _outstandingSetGetAttrId = 0;
+                }
+                _onAttrSetComplete(_readCmd->getReqId(), _readCmd->getAttrId(), _readCmd->getValueLen(), val);
+                break;
+
+            default:
+                break;
+        }
+        delete[] (val); //wsugi delete (val);
+        delete (_readCmd);
+        _readCmdOffset = 0;
+        _readCmd = NULL;
+    }
+
+    if (_writeCmd != NULL) {
+        // Fake a callback here for MCU attributes as we don't get one from the module.
+        if (_writeCmd->getCommand() == MSG_TYPE_UPDATE && IS_MCU_ATTR(_writeCmd->getAttrId())) {
+            _onAttrSetComplete(_writeCmd->getReqId(), _writeCmd->getAttrId(), _writeCmd->getValueLen(), _writeCmd->getValueP());
+        }
+        delete (_writeCmd);
+        _writeCmdOffset = 0;
+        _writeCmd = NULL;
+    }
+}
+
+/**
+ * exchangeStatus
+ *
+ * Write a status command object to the ASR-1 and clock in a status object from the ASR-1 at the same time.
+ */
+int afLib::exchangeStatus(StatusCommand *tx, StatusCommand *rx) {
+    int result = afSUCCESS;
+    uint16_t len = tx->getSize();
+    int bytes[len];
+    char rbytes[len+1];
+    int index = 0;
+    tx->getBytes(bytes);
+
+//    _theSPI->beginSPI();
+
+    for (int i=0;i<len;i++)
+    {
+      rbytes[i]=bytes[i];
+    }
+    rbytes[len]=tx->getChecksum();
+    
+    printTransaction((uint8_t*)rbytes,len+1);
+
+    _theSPI->beginSPI();
+    _theSPI->transfer(rbytes,len+1);
+    _theSPI->endSPI();
+    
+    printTransaction((uint8_t*)rbytes,len+1);
+
+    uint8_t cmd = bytes[index++];
+    if (cmd != 0x30 && cmd != 0x31) {
+        printf("exchangeStatus bad cmd: 0x%02x\n",cmd);
+        result = afERROR_INVALID_COMMAND;
+    }
+
+    rx->setBytesToSend(rbytes[index + 0] | (rbytes[index + 1] << 8));
+    rx->setBytesToRecv(rbytes[index + 2] | (rbytes[index + 3] << 8));
+    rx->setChecksum(rbytes[index+4]);
+    //_theSPI->endSPI();
+    return result;
+}
+
+/**
+ * inSync
+ *
+ * Check to make sure the Arduino and the ASR-1 aren't trying to send data at the same time.
+ * Return true only if there is no collision.
+ */
+bool afLib::inSync(StatusCommand *tx, StatusCommand *rx) {
+    return (tx->getBytesToSend() == 0 && rx->getBytesToRecv() == 0) ||
+           (tx->getBytesToSend() > 0 && rx->getBytesToRecv() == 0) ||
+           (tx->getBytesToSend() == 0 && rx->getBytesToRecv() > 0);
+}
+
+/**
+ * writeStatus
+ *
+ * Write a status command to the ASR-1 and ignore the result. If you want to read bytes at the same time, use
+ * exchangeStatus instead.
+ */
+int afLib::writeStatus(StatusCommand *c) {
+    int result = afSUCCESS;
+    uint16_t len = c->getSize();
+    int bytes[len];
+    char rbytes[len+1];
+    int index = 0;
+    c->getBytes(bytes);
+
+    _theSPI->beginSPI();
+
+    for (int i=0;i<len;i++)
+    {
+      rbytes[i]=bytes[i];
+    }
+    rbytes[len]=c->getChecksum();
+    printTransaction((uint8_t*)rbytes,len+1);
+    _theSPI->transfer(rbytes,len+1);
+    printTransaction((uint8_t*)rbytes,len+1);
+    uint8_t cmd = rbytes[index++];
+    if (cmd != 0x30 && cmd != 0x31) {
+        printf("writeStatus bad cmd: 0x%02x\n",cmd);
+        result = afERROR_INVALID_COMMAND;
+    }
+
+
+    _theSPI->endSPI();
+
+//  c->dump();
+//  c->dumpBytes();
+
+    return result;
+}
+
+/**
+ * sendBytes
+ *
+ * Send the specified number of data bytes to the ASR-1. Do this in chunks of SPI_FRAME_LEN bytes.
+ */
+void afLib::sendBytes() {
+    uint16_t len = _bytesToSend > SPI_FRAME_LEN ? SPI_FRAME_LEN : _bytesToSend;
+    uint8_t bytes[SPI_FRAME_LEN];
+    memset(bytes, 0xff, sizeof(bytes));
+
+    memcpy(bytes, &_writeBuffer[_writeCmdOffset], len);
+
+    _theSPI->beginSPI();
+    printTransaction(bytes,len+1);
+    _theSPI->transfer((char *)bytes,len);
+    printTransaction(bytes,len+1);
+    _theSPI->endSPI();
+
+//  dumpBytes("Sending:", len, bytes);
+
+    _writeCmdOffset += len;
+    _bytesToSend -= len;
+}
+
+/**
+ * recvBytes
+ *
+ * Receive the specified number of data bytes from the ASR-1. Do this in chunks of SPI_FRAME_LEN bytes.
+ */
+void afLib::recvBytes() {
+    uint16_t len = _bytesToRecv > SPI_FRAME_LEN ? SPI_FRAME_LEN : _bytesToRecv;
+
+    if (_readCmdOffset == 0) {
+        _readBufferLen = _bytesToRecv;
+        _readBuffer = new uint8_t[_readBufferLen];
+    }
+
+    _theSPI->beginSPI();
+
+
+    char * start =(char*)_readBuffer + _readCmdOffset;
+    printTransaction((uint8_t*)start,len+1);
+    _theSPI->transfer(start,len);
+    printTransaction((uint8_t*)start,len+1);
+
+    _theSPI->endSPI();
+
+//  dumpBytes("Receiving:", len, _readBuffer);
+
+    _readCmdOffset += len;
+    _bytesToRecv -= len;
+}
+
+/**
+ * isIdle
+ *
+ * Provide a way for the sketch to know if we're idle. Returns true if there are no attribute operations in progress.
+ */
+bool afLib::isIdle() {
+    return _interrupts_pending == 0 && _state == STATE_IDLE && _outstandingSetGetAttrId == 0;
+}
+
+/**
+ * These methods are required to disable/enable interrupts for the Linux version of afLib.
+ * They are no-ops on Arduino.
+ */
+#ifndef ARDUINO
+void noInterrupts(){}
+    void interrupts(){}
+#endif
+
+void afLib::mcuISR() {
+//  _theLog->println("mcu");
+    updateIntsPending(1);
+}
+
+/****************************************************************************
+ *                              Queue Methods                               *
+ ****************************************************************************/
+/**
+ * queueInit
+ *
+ * Create a small queue to prevent flooding the ASR-1 with attribute operations.
+ * The initial size is small to allow running on small boards like UNO.
+ * Size can be increased on larger boards.
+ */
+void afLib::queueInit() {
+    for (int i = 0; i < REQUEST_QUEUE_SIZE; i++) {
+        _requestQueue[i].p_value = NULL;
+    }
+}
+
+/**
+ * queuePut
+ *
+ * Add an item to the end of the queue. Return an error if we're out of space in the queue.
+ */
+int afLib::queuePut(uint8_t messageType, uint8_t requestId, const uint16_t attributeId, uint16_t valueLen,
+                    const uint8_t *value) {
+    for (int i = 0; i < REQUEST_QUEUE_SIZE; i++) {
+        if (_requestQueue[i].p_value == NULL) {
+            _requestQueue[i].messageType = messageType;
+            _requestQueue[i].attrId = attributeId;
+            _requestQueue[i].requestId = requestId;
+            _requestQueue[i].valueLen = valueLen;
+            _requestQueue[i].p_value = new uint8_t[valueLen];
+            memcpy(_requestQueue[i].p_value, value, valueLen);
+            return afSUCCESS;
+        }
+    }
+
+    return afERROR_QUEUE_OVERFLOW;
+}
+
+/**
+ * queueGet
+ *
+ * Pull and return the oldest item from the queue. Return an error if the queue is empty.
+ */
+int afLib::queueGet(uint8_t *messageType, uint8_t *requestId, uint16_t *attributeId, uint16_t *valueLen,
+                    uint8_t **value) {
+    for (int i = 0; i < REQUEST_QUEUE_SIZE; i++) {
+        if (_requestQueue[i].p_value != NULL) {
+            *messageType = _requestQueue[i].messageType;
+            *attributeId = _requestQueue[i].attrId;
+            *requestId = _requestQueue[i].requestId;
+            *valueLen = _requestQueue[i].valueLen;
+            *value = new uint8_t[*valueLen];
+            memcpy(*value, _requestQueue[i].p_value, *valueLen);
+            delete[] (_requestQueue[i].p_value); //wsugi delete (_requestQueue[i].p_value);
+            _requestQueue[i].p_value = NULL;
+            return afSUCCESS;
+        }
+    }
+
+    return afERROR_QUEUE_UNDERFLOW;
+}
+
+/****************************************************************************
+ *                              Debug Methods                               *
+ ****************************************************************************/
+/**
+ * dumpBytes
+ *
+ * Dump a byte buffer to the debug log.
+ */
+void afLib::dumpBytes(char *label, int len, uint8_t *bytes) {
+    return ;
+    printf("%s\n",label);
+    for (int i = 0; i < len; i++) {
+        if (i > 0) {
+            printf(", ");
+        }
+        uint8_t b = bytes[i] & 0xff;
+
+        if (b < 0x10) {
+            printf("0x02x", b);
+        } else {
+            //_theLog->print("0x");
+            printf("0x02x",b);//, HEX);
+        }
+    }
+    printf("\n");
+}
+
+/**
+ * printState
+ *
+ * Print the current state of the afLib state machine. For debugging, just remove the return statement.
+ */
+void afLib::printState(int state) { 
+    return;
+    switch (state) {
+        case STATE_IDLE:
+            printf("STATE_IDLE\n");
+            break;
+        case STATE_STATUS_SYNC:
+            printf("STATE_STATUS_SYNC\n");
+            break;
+        case STATE_STATUS_ACK:
+            printf("STATE_STATUS_ACK\n");
+            break;
+        case STATE_SEND_BYTES:
+            printf("STATE_SEND_BYTES\n");
+            break;
+        case STATE_RECV_BYTES:
+            printf("STATE_RECV_BYTES\n");
+            break;
+        case STATE_CMD_COMPLETE:
+            printf("STATE_CMD_COMPLETE\n");
+            break;
+        default:
+            printf("Unknown State!\n");
+            break;
+    }
+}
+
+void afLib::printTransaction(uint8_t *rbytes, int len)
+{
+    return;
+    int i = 0;
+    for(;i<=len;++i)
+    {
+        printf("0x%02x:",rbytes[i]);
+    }
+    printf("\n");
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib/afLib.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,173 @@
+/**
+ * Copyright 2015 Afero, 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 AFLIB_H__
+#define AFLIB_H__
+
+#include "mbed.h"
+#include "iafLib.h"
+#include "SPI.h"
+#include "Command.h"
+#include "StatusCommand.h"
+#include "afSPI.h"
+// #include "WatchDogWrapper.hpp"
+
+#define STATE_IDLE                          0
+#define STATE_STATUS_SYNC                   1
+#define STATE_STATUS_ACK                    3
+#define STATE_SEND_BYTES                    4
+#define STATE_RECV_BYTES                    5
+#define STATE_CMD_COMPLETE                  6
+
+#define SPI_FRAME_LEN                       16
+
+#define REQUEST_QUEUE_SIZE                  10
+
+typedef struct {
+    uint8_t     messageType;
+    uint16_t    attrId;
+    uint8_t     requestId;
+    uint16_t    valueLen;
+    uint8_t     *p_value;
+} request_t;
+
+class afLib : public iafLib {
+public:
+    afLib(PinName mcuInterrupt, isr isrWrapper,
+          onAttributeSet attrSet, onAttributeSetComplete attrSetComplete, afSPI *theSPI);
+//wsugi 20161128
+    ~afLib();
+//wsugi 20161128
+
+// motoo tanaka 20171116
+    virtual int getRequestId(void) ;
+// motoo tanaka 20171116
+// motoo tanaka 20171229
+    virtual void disable_irq(void) { fco.disable_irq() ; }
+    virtual void enable_irq(void) { fco.enable_irq() ; }
+    
+    virtual void loop(void);
+
+    virtual int getAttribute(const uint16_t attrId);
+
+    virtual int setAttributeBool(const uint16_t attrId, const bool value);
+
+    virtual int setAttribute8(const uint16_t attrId, const int8_t value);
+
+    virtual int setAttribute16(const uint16_t attrId, const int16_t value);
+
+    virtual int setAttribute32(const uint16_t attrId, const int32_t value);
+
+    virtual int setAttribute64(const uint16_t attrId, const int64_t value);
+
+    virtual int setAttribute(const uint16_t attrId, const string &value);
+
+    virtual int setAttribute(const uint16_t attrId, const uint16_t valueLen, const char *value);
+
+    virtual int setAttribute(const uint16_t attrId, const uint16_t valueLen, const uint8_t *value);
+
+    virtual int setAttributeComplete(uint8_t requestId, const uint16_t attrId, const uint16_t valueLen, const uint8_t *value);
+
+    virtual bool isIdle();
+
+    virtual void mcuISR();
+
+private:
+    Timeout deathWish;
+    Timer *checkLastSync;
+    static void kick_the_bucket();
+    afSPI *_theSPI;
+
+    //SPISettings _spiSettings;
+    volatile int _interrupts_pending;
+    int _state;
+    uint16_t _bytesToSend;
+    uint16_t _bytesToRecv;
+    uint8_t _requestId;
+    uint16_t _outstandingSetGetAttrId;
+
+    // Application Callbacks.
+    onAttributeSet _onAttrSet;
+    onAttributeSetComplete _onAttrSetComplete;
+
+    Command *_writeCmd;
+    uint16_t _writeBufferLen;
+    uint8_t *_writeBuffer;
+
+    Command *_readCmd;
+    uint16_t _readBufferLen;
+    uint8_t *_readBuffer;
+
+    int _writeCmdOffset;
+    int _readCmdOffset;
+
+    StatusCommand *_txStatus;
+    StatusCommand *_rxStatus;
+
+    request_t _request;
+    request_t _requestQueue[REQUEST_QUEUE_SIZE];
+
+#ifdef ATTRIBUTE_CLI
+    int parseCommand(const char *cmd);
+#endif
+
+    void sendCommand(void);
+
+    void runStateMachine(void);
+
+    void printState(int state);
+
+    //void beginSPI();
+
+    //void endSPI();
+
+    int exchangeStatus(StatusCommand *tx, StatusCommand *rx);
+
+    bool inSync(StatusCommand *tx, StatusCommand *rx);
+
+    int writeStatus(StatusCommand *c);
+
+    void sendBytes();
+
+    void recvBytes();
+
+    void dumpBytes(char *label, int len, uint8_t *bytes);
+
+    void updateIntsPending(int amount);
+
+    void queueInit(void);
+
+    int queuePut(uint8_t messageType, uint8_t requestId, const uint16_t attributeId, uint16_t valueLen, const uint8_t *value);
+
+    int queueGet(uint8_t *messageType, uint8_t *requestId, uint16_t *attributeId, uint16_t *valueLen, uint8_t **value);
+
+    int doGetAttribute(uint8_t requestId, uint16_t attrId);
+
+    int doSetAttribute(uint8_t requestId, uint16_t attrId, uint16_t valueLen, uint8_t *value);
+
+    int doUpdateAttribute(uint8_t requestId, uint16_t attrId, uint8_t status, uint16_t valueLen, uint8_t *value);
+
+    void onStateIdle(void);
+    void onStateSync(void);
+    void onStateAck(void);
+    void onStateSendBytes(void);
+    void onStateRecvBytes(void);
+    void onStateCmdComplete(void);
+    void printTransaction(uint8_t *rbytes, int len);
+    InterruptIn fco;
+};
+
+#endif // AFLIB_H__
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib/afSPI.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2015 Afero, 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 AFLIB_AFSPI_H
+#define AFLIB_AFSPI_H
+
+class afSPI {
+    public:
+        virtual void begin() = 0;
+        virtual void beginSPI() = 0;
+        virtual void endSPI() = 0;
+        virtual void transfer(char *bytes,int len) = 0;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib/iafLib.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,126 @@
+/**
+ * Copyright 2015 Afero, 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.
+ */
+
+/**
+ * afLib public interface
+ *
+ * This file defines everything your application should need for commuinicating with the Afero ASR-1 radio module.
+ * Is there is anything missing from this file, please post a request on the developer forum and we will see what
+ * we can do.
+ */
+#ifndef AFLIB_IAFLIB_H
+#define AFLIB_IAFLIB_H
+
+#include "mbed.h"
+#include <string>
+using namespace std;
+#include "afErrors.h"
+#include "afSPI.h"
+
+#if defined (TARGET_TEENSY3_1)
+    #include "USBSerial.h"
+#endif
+
+#define afMINIMUM_TIME_BETWEEN_REQUESTS     1000
+
+#define MAX_ATTRIBUTE_SIZE                  255
+
+typedef void (*isr)();
+typedef void (*onAttributeSet)(const uint8_t requestId, const uint16_t attributeId, const uint16_t valueLen, const uint8_t *value);
+typedef void (*onAttributeSetComplete)(const uint8_t requestId, const uint16_t attributeId, const uint16_t valueLen, const uint8_t *value);
+
+class iafLib {
+public:
+    /**
+     * create
+     *
+     * Create an instance of the afLib object. The afLib is a singleton. Calling this method multiple
+     * times will return the same instance.
+     *
+     * @param   mcuInterrupt    The Arduino interrupt to be used (returned from digitalPinToInterrupt)
+     * @param   isrWrapper      This is the isr method that must be defined in your sketch
+     * @param   attrSet         Callback for notification of attribute set requests
+     * @param   attrSetComplete Callback for notification of attribute set request completions
+     * @return  iafLib *        Instance of iafLib
+     */
+    static iafLib * create(PinName mcuInterrupt, isr isrWrapper,
+        onAttributeSet attrSet, onAttributeSetComplete attrSetComplete, afSPI *theSPI);
+                           
+    //wsugi 20161128
+    static void destroy();
+
+    /**
+     * loop
+     *
+     * Called by the loop() method in your sketch to give afLib some CPU time
+     */
+    virtual void loop(void) = 0;
+
+    /**
+     * getAttribute
+     *
+     * Request the value of an attribute be returned from the ASR-1.
+     * Value will be returned in the attrSetComplete callback.
+     */
+    virtual int getAttribute(const uint16_t attrId) = 0;
+
+    /**
+     * setAttribute
+     *
+     * Request setting an attribute.
+     * For MCU attributes, the attribute value will be updated.
+     * For IO attributes, the attribute value will be updated, and then onAttrSetComplete will be called.
+     */
+    virtual int setAttributeBool(const uint16_t attrId, const bool value) = 0;
+
+    virtual int setAttribute8(const uint16_t attrId, const int8_t value) = 0;
+
+    virtual int setAttribute16(const uint16_t attrId, const int16_t value) = 0;
+
+    virtual int setAttribute32(const uint16_t attrId, const int32_t value) = 0;
+
+    virtual int setAttribute64(const uint16_t attrId, const int64_t value) = 0;
+
+    virtual int setAttribute(const uint16_t attrId, const string &value) = 0;
+
+    virtual int setAttribute(const uint16_t attrId, const uint16_t valueLen, const char *value) = 0;
+
+    virtual int setAttribute(const uint16_t attrId, const uint16_t valueLen, const uint8_t *value) = 0;
+
+    /**
+     * setAttributeComplete
+     *
+     * Call this in response to an onAttrSet. This lets the ASR-1 know that the set request has been handled.
+     */
+    virtual int setAttributeComplete(uint8_t requestId, const uint16_t attrId, const uint16_t valueLen, const uint8_t *value) = 0;
+
+    /**
+     * isIdle
+     *
+     * Call to find out of the ASR-1 is currently handling a request.
+     *
+     * @return true if an operation is in progress
+     */
+    virtual bool isIdle() = 0;
+
+    /**
+     * mcuISR
+     *
+     * Called by your sketch to pass the interrupt along to afLib.
+     */
+    virtual void mcuISR() = 0;
+};
+#endif //AFLIB_IAFLIB_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib/msg_types.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2015 Afero, 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 MSG_TYPE_H__
+#define MSG_TYPE_H__
+
+typedef uint8_t msg_type_t;
+
+#define MSG_TYPE_UNKNOWN    0
+#define MSG_TYPE_ERROR      1
+
+// Messaging channel messages
+#define MESSAGE_CHANNEL_BASE                    10
+#define MSG_TYPE_SET                            (MESSAGE_CHANNEL_BASE + 1)
+#define MSG_TYPE_GET                            (MESSAGE_CHANNEL_BASE + 2)
+#define MSG_TYPE_UPDATE                         (MESSAGE_CHANNEL_BASE + 3)
+
+#define NEGOTIATOR_CHANNEL_BASE                 20
+#define MSG_TYPE_AUTHENTICATOR_SESSION_INFO     (NEGOTIATOR_CHANNEL_BASE + 1)
+#define MSG_TYPE_PERIPHERAL_SESSION_INFO        (NEGOTIATOR_CHANNEL_BASE + 2)
+#define MSG_TYPE_SIGNED_SESSION_PUBLIC_KEYS     (NEGOTIATOR_CHANNEL_BASE + 3)
+#define MSG_TYPE_MESSAGING_AVAILABLE            (NEGOTIATOR_CHANNEL_BASE + 4)
+#define MSG_TYPE_PAIRING_COMPLETE               (NEGOTIATOR_CHANNEL_BASE + 5)
+
+#endif  // MSG_TYPE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/af_attriburtes.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,700 @@
+#include "mbed.h"
+#include <ctype.h>
+#include "af_attributes.h"
+#include "edge_time.h"
+#include "edge_sensor.h"
+#include "edge_accel.h"
+#include "edge_color.h"
+#include "edge_temp.h"
+#include "edge_pressure.h"
+#include "edge_mgr.h"
+#include "edge_reset_mgr.h"
+// #include "SO1602A.h"
+#include <ILI9341.h>
+#include "pending.h"
+
+// extern SO1602A *display ;
+extern ILI9341 *display ;
+extern pending_class *pending ;
+
+static const af_attribute_type af_attr[] = {
+/*     ID,                     Description,                Type,                Size */
+    {  ATTR_SENSE_VAL,         "Sensor Value",             ATTRIBUTE_TYPE_UTF8S, 255 },
+    {  ATTR_ACCEL_PRESENT,     "Accel Present",            ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_ACCEL_ENABLE,      "Accel Enable",             ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_ACCEL_INTERVAL,    "Accel Interval",           ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_ACCEL_VALUE,       "Accel Value",              ATTRIBUTE_TYPE_FIXED_15_16, 4},
+/* first color sensor (VEML6040) and LED set */    
+    {  ATTR_COLOR0_PRESENT,    "Color1 Present",           ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_COLOR0_ENABLE,     "Color1 Enable",            ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_COLOR0_INTERVAL,   "Color1 Interval",          ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_COLOR0_TRIGMODE,   "Color1 Trigger Mode",      ATTRIBUTE_TYPE_SINT8,   1 },
+    {  ATTR_COLOR0_ITIME,      "Color1 Integration Time",  ATTRIBUTE_TYPE_SINT8,   1 },    
+    {  ATTR_COLOR0_CALIBRATE,  "Color1 Calibrate",         ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_COLOR0_PWM_R,      "Color1 PWM R",             ATTRIBUTE_TYPE_SINT32,  4 },
+    {  ATTR_COLOR0_PWM_G,      "Color1 PWM G",             ATTRIBUTE_TYPE_SINT32,  4 },
+    {  ATTR_COLOR0_PWM_B,      "Color1 PWM B",             ATTRIBUTE_TYPE_SINT32,  4 },
+    {  ATTR_COLOR0_PWM_PERIOD, "Color1 PWM Period",        ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_COLOR0_PWM_TARGET, "Color1 PWM Target",        ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_COLOR0_R_VALUE,    "Color1 R",                 ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_COLOR0_G_VALUE,    "Color1 G",                 ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_COLOR0_B_VALUE,    "Color1 B",                 ATTRIBUTE_TYPE_SINT16,  2 },
+/* second color sensor (VEML6040) and LED set */ 
+    {  ATTR_COLOR1_PRESENT,    "Color2 Present",           ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_COLOR1_ENABLE,     "Color2 Enable",            ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_COLOR1_INTERVAL,   "Color2 Interval",          ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_COLOR1_TRIGMODE,   "Color2 Trigger Mode",      ATTRIBUTE_TYPE_SINT8,   1 },
+    {  ATTR_COLOR1_ITIME,      "Color2 Integration Time",  ATTRIBUTE_TYPE_SINT8,   1 },
+    {  ATTR_COLOR1_CALIBRATE,  "Color2 Calibrate",         ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_COLOR1_PWM_R,      "Color2 PWM R",             ATTRIBUTE_TYPE_SINT32,  4 },
+    {  ATTR_COLOR1_PWM_G,      "Color2 PWM G",             ATTRIBUTE_TYPE_SINT32,  4 },
+    {  ATTR_COLOR1_PWM_B,      "Color2 PWM B",             ATTRIBUTE_TYPE_SINT32,  4 },
+    {  ATTR_COLOR1_PWM_PERIOD, "Color2 PWM Period",        ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_COLOR1_PWM_TARGET, "Color2 PWM Target",        ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_COLOR1_R_VALUE,    "Color2 R",                 ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_COLOR1_G_VALUE,    "Color2 G",                 ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_COLOR1_B_VALUE,    "Color2 B",                 ATTRIBUTE_TYPE_SINT16,  2 },
+/* first temperature sensor (LM75B) */    
+    {  ATTR_TEMP0_PRESENT,    "Temp0 Present",             ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_TEMP0_ENABLE,     "Temp0 Enable",              ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_TEMP0_INTERVAL,   "Temp0 Interval",            ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_TEMP0_VALUE,      "Temp0 Value",               ATTRIBUTE_TYPE_FIXED_15_16, 4},
+/* second temperature sensor (SMTC502AT/Before) */    
+    {  ATTR_TEMP1_PRESENT,    "Temp1 Present",             ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_TEMP1_ENABLE,     "Temp1 Enable",              ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_TEMP1_INTERVAL,   "Temp1 Interval",            ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_TEMP1_VALUE,      "Temp1 Value",               ATTRIBUTE_TYPE_FIXED_15_16, 4},
+/* third temperature sensor (SMTC502AT/After) */    
+    {  ATTR_TEMP2_PRESENT,    "Temp2 Present",             ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_TEMP2_ENABLE,     "Temp2 Enable",              ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_TEMP2_INTERVAL,   "Temp2 Interval",            ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_TEMP2_VALUE,      "Temp2 Value",               ATTRIBUTE_TYPE_FIXED_15_16, 4},
+/* fouth temperateure sensor (LM75B) */
+    {  ATTR_TEMP3_PRESENT,    "Temp3 Present",             ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_TEMP3_ENABLE,     "Temp3 Enable",              ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_TEMP3_INTERVAL,   "Temp3 Interval",            ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_TEMP3_VALUE,      "Temp3 Value",               ATTRIBUTE_TYPE_FIXED_15_16, 4}, 
+/* Gas Pressure sensor (PSE530) */    
+    {  ATTR_GAS_PRESENT,      "Gas Pressure Present",      ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_GAS_ENABLE,       "Gas Pressure Enable",       ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_GAS_INTERVAL,     "Gas Pressure Interval",     ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_GAS_VALUE,        "Gas Pressure Value",        ATTRIBUTE_TYPE_FIXED_15_16, 4}, 
+    {  ATTR_GAS_THR_MODE,     "Gas Press Threshold Mode",  ATTRIBUTE_TYPE_SINT8,   1 },
+    {  ATTR_GAS_THR_HIGH,     "Gas Press High Thresh",     ATTRIBUTE_TYPE_SINT16,  2 },
+    {  ATTR_GAS_THR_LOW,      "Gas Press Low Thresh",      ATTRIBUTE_TYPE_SINT16,  2 },
+/* Software Reset Request */    
+    {  ATTR_SOFTWARE_RESET,   "Software Reset",            ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_DISPLAY_MODE,     "Display Mode",              ATTRIBUTE_TYPE_SINT8,   1 },
+    {  ATTR_MCU_RESET_REASON, "MCU Reset Reason",          ATTRIBUTE_TYPE_UTF8S,  64 },
+                   
+    { ATTR_LED,               "LED",                       ATTRIBUTE_TYPE_SINT16,  2 },
+    { ATTR_IO0,               "I/O 0",                     ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_IO1,               "I/O 1",                     ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_IO2,               "I/O 2",                     ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_BUTTON,            "BUTTON",                    ATTRIBUTE_TYPE_BOOLEAN, 2 },
+    { ATTR_IO3,               "I/O 3",                     ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_BOOT_LOADER_VER,   "Bootloader Version",        ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_BLE_STACK_VER,     "BLE Stack Version",         ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_FW_APP_VER,        "FW Application Version",    ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_DEVICE_DESC,       "Device Description",        ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_WIFI_VER,          "Wi-Fi chip",                ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_OFFLINE_SCHED,     "Offline Schedules enable",  ATTRIBUTE_TYPE_SINT16,  2 }, 
+    { ATTR_SECURITY_ENABLED,  "Security Enabled",          ATTRIBUTE_TYPE_SINT8,   1 }, /* ? */
+    { ATTR_UTC_OFFSET,        "UTC offset data",           ATTRIBUTE_TYPE_BYTES,   8 },
+    { ATTR_CONFIGURES_SSID,   "Configured SSID",           ATTRIBUTE_TYPE_UTF8S,  10 }, /* ? */
+    { ATTR_WIFI_BARS,         "Wi-Fi Bars",                ATTRIBUTE_TYPE_SINT8,   1 },
+    { ATTR_WIFI_STDY_STATE,   "Wi-Fi Steady State",        ATTRIBUTE_TYPE_SINT8,   1 },
+    { ATTR_COMMAND,           "Command",                   ATTRIBUTE_TYPE_BYTES,   8 }, /* ? */   
+    { ATTR_ASR_STATE,         "ASR State",                 ATTRIBUTE_TYPE_SINT8,   1 },
+    { ATTR_LOW_BATTERY,       "Low Battery Warning",       ATTRIBUTE_TYPE_SINT8,   1 },
+    { ATTR_LINKED_TIMESTAMP,  "Linked Timestamp",          ATTRIBUTE_TYPE_SINT32,  4 },
+    { ATTR_ATTR_ACK,          "Attribute ACK",             ATTRIBUTE_TYPE_SINT16,  8 },
+    { ATTR_REBOOT_REASON,     "Reboot Reason",             ATTRIBUTE_TYPE_UTF8S, 100 },
+    { ATTR_BLE_COMMS,         "BLE Comms",                 ATTRIBUTE_TYPE_BYTES,  12 },
+    { ATTR_MCU_INTERFACE,     "MCU Interface",             ATTRIBUTE_TYPE_SINT8,   1 },
+    { 0,                      0,                           0,                      0 }
+} ;
+
+int get_af_attr(uint16_t id) 
+{
+    int i ;
+    for (i = 0 ; af_attr[i].id != 0 ; i++ ) {
+        if (id == af_attr[i].id) {
+            break ;
+        }
+    }
+    return (i) ;
+}
+
+void print_af_error(int resultCode) 
+{
+    switch(resultCode) {
+    case afSUCCESS:
+        printf("Operation completed successfully\n") ;
+        break ;
+    case afERROR_NO_SUCH_ATTRIBUTE:
+        printf("Request was made for unknown attribute id\n") ;
+        break ;
+    case afERROR_BUSY:
+        printf("Request already in progress, try again\n") ;
+        break ;
+    case afERROR_INVALID_COMMAND:
+        printf("Command could not be parsed\n") ;
+        break ;
+    case afERROR_QUEUE_OVERFLOW:
+        printf("Queue is full\n") ;
+        break ;
+    case afERROR_QUEUE_UNDERFLOW:
+        printf("Queue is empty\n") ;
+        break ;
+    case afERROR_INVALID_PARAM:
+        printf("Bad input parameter\n") ;
+        break ;
+    default:
+        printf("Unknown error code %d\n", resultCode) ;
+        break ;
+    }
+}
+
+void af_print_values(
+    const uint8_t   requestId, 
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value
+) 
+{
+    int i, id ;
+
+    id = get_af_attr(attributeId) ;
+
+    if (af_attr[id].id  != 0) {
+        printf(af_attr[id].description) ;
+        printf(" : ") ;
+        switch(af_attr[id].attribute_type) {
+        case ATTRIBUTE_TYPE_BOOLEAN:
+        case ATTRIBUTE_TYPE_SINT8: 
+            if (valueLen >= 1) {
+                printf("%02X\n", value[0]) ;
+            }
+            break ;
+        case ATTRIBUTE_TYPE_SINT16:
+            if (valueLen >= 2) {
+                printf("%02X%02X\n", value[1], value[0]) ;
+            }
+            break ; 
+        case ATTRIBUTE_TYPE_SINT32:
+            if (valueLen >= 4) {
+                printf("%02X%02X%02X%02X\n",
+                    value[3],value[2],value[1],value[0]) ;
+            }
+            break ;
+        case ATTRIBUTE_TYPE_SINT64:
+            if (valueLen >= 8) {
+                printf("%02X%02X %02X%02X %02X%02X %02X%02X\n",
+                    value[7], value[6], value[5], value[4],
+                    value[3], value[2], value[1], value[0]) ;
+            }
+            break ;
+        case ATTRIBUTE_TYPE_UTF8S: 
+            if (valueLen > 0) {
+                for (i = 0 ; i < valueLen ; i++) {
+                    if (isprint(value[i])) {
+                        printf("%c", value[i]) ;
+                    } else if (value[i] == 0) { /* string terminator NULL */
+                        break ;
+                    } else {
+                        printf("\'%02X\'",value[i]) ;
+                    }
+                }
+                printf("\n") ;
+            }
+            break ;
+        case ATTRIBUTE_TYPE_BYTES:
+        default:
+            if (valueLen > 0) {
+                for (i = 0 ; i < valueLen ; i++ ) {
+                    printf("%02X ", value[i]) ;
+                }
+                printf("\n") ;
+            }
+            break ;
+        }
+    } else {
+        if (valueLen > 0) {
+            for (i = 0 ; i < valueLen ; i++ ) {
+                printf("%02X ", value[i]) ;
+            }
+            printf("\n") ;
+        }
+    }
+//    printf("\n") ;
+}
+
+void assignAttribute(
+    const uint8_t   requestId, 
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value,
+    bool fromRequest
+) 
+{
+    switch(attributeId) {
+    case ATTR_LINKED_TIMESTAMP: /* timestamp */  
+        set_time(valueLen, value) ; /* 68 us */
+        if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        printf("timestampe = ") ;
+        print_date_wd(&current_time) ;
+//        print_time(&current_time) ;
+        printf("\n") ;
+        break ;
+    case ATTR_SOFTWARE_RESET: /* software reset requested! */
+        if (value[0]) {
+            reset_watch_dog() ;
+            printf("Software Reset Requested!\n") ;
+            if (display != 0) {
+                display->cls() ;
+                display->locate(0,0) ;
+                display->printf("System Rebooting!") ;
+            }
+            reset_watch_dog() ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+            wait(0.5) ;
+            reset_watch_dog() ;
+            reboot_edge() ;
+        }
+        break ;
+    case ATTR_DISPLAY_MODE:
+        if (display_mode != value[0]) {
+            display_mode = value[0] ;
+            if (display) {
+                display->BusEnable(true) ;
+                display->cls() ;
+                display->BusEnable(false) ;
+            }
+/* following function is only for testing color sensor power on/off */
+#if 0
+            if (value[0] == DISPLAY_MODE_OFF) {
+                disable_color_sensor() ;
+            } else {
+                enable_color_sensor() ;
+            }
+#endif            
+        }
+        reset_watch_dog() ;
+        switch(value[0]) {
+        case DISPLAY_MODE_GAS: /* gas pressure monitor only */
+            break ;
+        case DISPLAY_MODE_SUMMARY: /* summary */
+            break ;
+        case DISPLAY_MODE_CHART: /* chart mode */
+            if (display) {
+                draw_all_chart_frame() ;
+            }
+            break ;
+        case DISPLAY_MODE_OFF: /* display off */
+        default:
+            display_mode = DISPLAY_MODE_OFF ;          
+            break ;
+        }
+        if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        break ;
+    case ATTR_ACCEL_ENABLE: /* accel enable */
+        if (sensor[SENSOR_ID_ACCEL]) {
+            if (value[0]) {
+                sensor[SENSOR_ID_ACCEL]->reset() ;
+                sensor[SENSOR_ID_ACCEL]->enable() ;
+            } else if (sensor[SENSOR_ID_ACCEL]){
+                sensor[SENSOR_ID_ACCEL]->disable() ;
+            }
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;
+    case ATTR_ACCEL_INTERVAL:
+        if (sensor[SENSOR_ID_ACCEL]) {
+            sensor[SENSOR_ID_ACCEL]->setInterval((value[1] << 8) | value[0]) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;
+    case ATTR_COLOR0_ENABLE: /* color0 enable */
+        if (sensor[SENSOR_ID_COLOR1]) {
+            if (value[0]) {
+                sensor[SENSOR_ID_COLOR1]->reset() ;
+                sensor[SENSOR_ID_COLOR1]->enable() ;
+            } else {
+                sensor[SENSOR_ID_COLOR1]->disable() ;
+            }
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;
+    case ATTR_COLOR0_INTERVAL:
+        if (sensor[SENSOR_ID_COLOR1]) {
+            sensor[SENSOR_ID_COLOR1]->setInterval((value[1] << 8) | value[0]) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;    
+    case ATTR_COLOR0_TRIGMODE: /* color0 config */
+        if (sensor[SENSOR_ID_COLOR1]) {
+            uint8_t config = ((edge_color*)sensor[SENSOR_ID_COLOR1])->getConfig() & 0x70 ;
+            if (value[0]) {
+                config = config | 0x06 ;
+            } 
+            ((edge_color*)sensor[SENSOR_ID_COLOR1])->setConfig(config) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;
+    case ATTR_COLOR0_ITIME: /* color0 config */
+        if (sensor[SENSOR_ID_COLOR1]) {
+            uint8_t config = ((edge_color*)sensor[SENSOR_ID_COLOR1])->getConfig() & 0x07 ;
+            config = (value[0] << 4) | config ;
+            ((edge_color*)sensor[SENSOR_ID_COLOR1])->setConfig(config) ;
+          if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;    
+    case ATTR_COLOR0_PWM_PERIOD: /* color0 pwm period */
+        if (sensor[SENSOR_ID_COLOR1]) {
+            ((edge_color*)sensor[SENSOR_ID_COLOR1])->set_pwm_period((value[1] << 8) | value[0]) ;
+          if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }            
+        break ;
+    case ATTR_COLOR0_PWM_TARGET: /* color0 pwm calibration target */
+        if (sensor[SENSOR_ID_COLOR1]) {
+            color0_target[0] = (value[1] << 8) | value[0] ;
+            color0_target[1] = color0_target[0] ;
+            color0_target[2] = color0_target[1] ;
+          if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }            
+        break ;     
+#if 1 /* do not handle calibration twice */   
+    case ATTR_COLOR0_CALIBRATE: /* calibrate color0 */
+        if (sensor[SENSOR_ID_COLOR1] && value[0] && fromRequest) { /* do calibration */ 
+            ((edge_color*)sensor[SENSOR_ID_COLOR1])->request_calibration() ;
+        }
+        break ;
+#endif
+    case ATTR_COLOR0_PWM_R:
+        if (sensor[SENSOR_ID_COLOR1]) {
+            ((edge_color*)sensor[SENSOR_ID_COLOR1])->setPwmR( (value[1] << 8) | value[0] ) ;
+//            color0_pwm[0] = (value[1] << 8) | value[0] ;
+        }
+        if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;       
+        break ;
+    case ATTR_COLOR0_PWM_G:
+        if (sensor[SENSOR_ID_COLOR1]) {
+            ((edge_color*)sensor[SENSOR_ID_COLOR1])->setPwmG( (value[1] << 8) | value[0] ) ;
+//            color0_pwm[1] = (value[1] << 8) | value[0] ;
+        }
+        if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;       
+        break ;
+    case ATTR_COLOR0_PWM_B:
+        if (sensor[SENSOR_ID_COLOR1]) {
+            ((edge_color*)sensor[SENSOR_ID_COLOR1])->setPwmB( (value[1] << 8) | value[0] ) ;
+//            color0_pwm[2] = (value[1] << 8) | value[0] ;
+        }
+        if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;       
+        break ;
+    case ATTR_COLOR1_ENABLE: /* color1 enable */
+        if (sensor[SENSOR_ID_COLOR2]) {
+            if (value[0]) {
+                sensor[SENSOR_ID_COLOR2]->reset() ;
+                sensor[SENSOR_ID_COLOR2]->enable() ;
+            } else {
+                sensor[SENSOR_ID_COLOR2]->disable() ;
+            }
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;
+    case ATTR_COLOR1_INTERVAL:
+        if (sensor[SENSOR_ID_COLOR2]) {
+            sensor[SENSOR_ID_COLOR2]->setInterval((value[1] << 8) | value[0]) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;    
+    case ATTR_COLOR1_TRIGMODE: /* color0 config */
+        if (sensor[SENSOR_ID_COLOR2]) {
+            uint8_t config = ((edge_color*)sensor[SENSOR_ID_COLOR2])->getConfig() & 0x70 ;
+            if (value[0]) {
+                config = config | 0x06 ;
+            } 
+            ((edge_color*)sensor[SENSOR_ID_COLOR2])->setConfig(config) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;
+    case ATTR_COLOR1_ITIME: /* color0 config */
+        if (sensor[SENSOR_ID_COLOR2]) {
+            uint8_t config = ((edge_color*)sensor[SENSOR_ID_COLOR2])->getConfig() & 0x07 ;
+            config = (value[0] << 4) | config ;
+            ((edge_color*)sensor[SENSOR_ID_COLOR2])->setConfig(config) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;  
+    case ATTR_COLOR1_PWM_PERIOD: /* color0 pwm period */
+        if (sensor[SENSOR_ID_COLOR2]) {
+            ((edge_color*)sensor[SENSOR_ID_COLOR2])->set_pwm_period((value[1] << 8) | value[0]) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }            
+        break ;
+    case ATTR_COLOR1_PWM_TARGET: /* color0 pwm calibration target */
+        if (sensor[SENSOR_ID_COLOR2]) {
+            color1_target[0] = (value[1] << 8) | value[0] ;
+            color1_target[1] = color1_target[0] ;
+            color1_target[2] = color1_target[1] ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }            
+        break ;   
+#if 1 /* do not handle calibration twice */
+    case ATTR_COLOR1_CALIBRATE: /* calibrate color1 */
+        if (sensor[SENSOR_ID_COLOR2] && value[0] && fromRequest) { /* do calibration! */
+            ((edge_color*)sensor[SENSOR_ID_COLOR2])->request_calibration() ;
+        }
+        break ;
+#endif
+    case ATTR_COLOR1_PWM_R:
+        if (sensor[SENSOR_ID_COLOR2]) {
+            ((edge_color*)sensor[SENSOR_ID_COLOR2])->setPwmR( (value[1] << 8) | value[0] ) ;
+//            color1_pwm[0] = (value[1] << 8) | value[0] ;
+        }
+        if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;       
+        break ;
+    case ATTR_COLOR1_PWM_G:
+        if (sensor[SENSOR_ID_COLOR2]) {
+            ((edge_color*)sensor[SENSOR_ID_COLOR2])->setPwmG( (value[1] << 8) | value[0] ) ;
+//            color1_pwm[1] = (value[1] << 8) | value[0] ;
+        }
+        if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;       
+        break ;
+    case ATTR_COLOR1_PWM_B:
+        if (sensor[SENSOR_ID_COLOR2]) {
+            ((edge_color*)sensor[SENSOR_ID_COLOR2])->setPwmB( (value[1] << 8) | value[0] ) ;
+//            color1_pwm[2] = (value[1] << 8) | value[0] ;
+        }
+        if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;       
+        break ;
+    case ATTR_TEMP0_ENABLE: /* temp0 is used to control temp-sensors */
+        if (sensor[SENSOR_ID_TEMP]) {
+            if (value[0]) {
+                sensor[SENSOR_ID_TEMP]->reset() ;
+                sensor[SENSOR_ID_TEMP]->enable() ;
+            } else {
+                sensor[SENSOR_ID_TEMP]->disable() ;
+            }
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        } 
+        break ;
+    case ATTR_TEMP0_INTERVAL:
+        if (sensor[SENSOR_ID_TEMP]) {
+            sensor[SENSOR_ID_TEMP]->setInterval((value[1] << 8) | value[0]) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ; 
+    case ATTR_TEMP3_ENABLE: /* temp3 enable */
+        break ;
+    case ATTR_GAS_ENABLE: /* pressure enable */
+        if (sensor[SENSOR_ID_PRESS]) {
+            if (value[0]) {
+                sensor[SENSOR_ID_PRESS]->reset() ;
+                sensor[SENSOR_ID_PRESS]->enable() ;
+            } else {
+                sensor[SENSOR_ID_PRESS]->disable() ;
+            }
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }   
+        break ;
+    case ATTR_GAS_INTERVAL:
+        if (sensor[SENSOR_ID_PRESS]) {
+            sensor[SENSOR_ID_PRESS]->setInterval((value[1] << 8) | value[0]) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ; 
+    case ATTR_GAS_THR_MODE:
+        if (sensor[SENSOR_ID_PRESS]) {
+            ((edge_pressure*)sensor[SENSOR_ID_PRESS])->set_thr_mode(value[0]) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;
+    case ATTR_GAS_THR_HIGH:
+        if (sensor[SENSOR_ID_PRESS]) {
+            ((edge_pressure*)sensor[SENSOR_ID_PRESS])->set_thr_high((value[1] << 8) | value[0]) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;
+    case ATTR_GAS_THR_LOW:
+        if (sensor[SENSOR_ID_PRESS]) {
+            ((edge_pressure*)sensor[SENSOR_ID_PRESS])->set_thr_low((value[1] << 8) | value[0]) ;
+            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        }
+        break ;               
+    default:
+        break ;    
+    }
+}
+
+/*
+ * Callback that allows ASR to request an MCU attribute be changed. 
+ * You should define this function in your MCU firmware to perform application-specific actions 
+ * your code must take (e.g., updating the state of the hardware), 
+ * in light of the attribute value change.
+*/
+void attributeChangeRequest(
+    const uint8_t   requestId, 
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value
+) 
+{ 
+    uint32_t timestamp = edge_time ;
+    if ((pending != 0)&&(pending->request->requestId == requestId)) {
+        pending->replied_time = timestamp ;
+
+    }
+    ts2time(timestamp, &current_time) ; /* 12 us */
+    if (verbos) {
+        print_time(&current_time) ;
+        printf(" %5d ASR requested [%d] : ", attributeId, requestId) ;
+        af_print_values(requestId, attributeId, valueLen, value) ;
+    }
+
+    assignAttribute(requestId, attributeId, valueLen, value, true) ;
+
+//    af_print_values(requestId, attributeId, valueLen, value) ;
+    if ((pending != 0)&&(pending->request->requestId == requestId)) {
+        printf("Request [%d] replied in %d sec!\n", requestId, pending->replied_time - pending->submit_time) ;
+        delete pending ;
+        pending = 0 ;
+    }
+}
+
+/*
+ * Application callback that allows afLib to notify that an attribute has changed. 
+ * This method will be called in response to a getAttribute call from the application 
+ * and whenever a ASR module attribute changes.
+ */
+void attributeUpdatedReport(
+    const uint8_t   requestId,
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value
+) 
+{
+    uint32_t timestamp = edge_time ;
+    int result ;
+    if ((pending != 0)&&(pending->request->requestId == requestId)) {
+        pending->replied_time = timestamp ;
+    }   
+    ts2time(timestamp, &current_time) ; /* 12us */
+    if (verbos) {
+        print_time(&current_time) ;
+        printf(" %5d ASR reported [%d]: ", attributeId, requestId) ;
+        af_print_values(requestId, attributeId, valueLen, value) ;
+    }
+
+    switch(attributeId) {
+    case ATTR_LINKED_TIMESTAMP:
+        set_time(valueLen, value) ; /* 68 us */
+        printf("timestampe = ") ;
+        print_date_wd(&current_time) ;
+//        print_time(&current_time) ;
+        printf("\n") ;
+        break ;         
+    case ATTR_WIFI_STDY_STATE:
+        gConnected = false ;
+        printf("WiFi Steady State: ") ;
+        switch(value[0]) {
+        case 0: printf("Not Connected\n")      ; break ;
+        case 1: printf("Pending\n") ;            break ;
+        case 2: 
+            printf("Connected\n") ;       
+            gConnected = true ; // the only case Connected state is OK   
+            break ;
+        case 3: printf("Unknown Failure\n") ;    break ;
+        case 4: printf("Association Failed\n") ; break ;
+        case 5: printf("Handshake Failed\n") ;   break ;
+        case 6: printf("Echo Failed\n") ;        break ;
+        case 7: printf("SSID Not Found\n") ;     break ;
+        case 8: printf("NTP Failed\n") ;         break ;
+        default: printf("Unknown [%d]\n", value[0]) ; break ;
+        }
+        break ;
+    case ATTR_REBOOT_REASON:
+        printf("Reboot Reason: ") ;
+        switch(value[0]) {
+        case 1: printf("Reset pin asserted\n") ; break ;
+        case 2: printf("Watchdog reset\n") ;     break ;
+        case 4: printf("Software reset\n") ;     break ;
+        case 8: printf("CPU Lock up\n") ;        break ;
+        default: printf("Unknown [%d]\n", value[0]) ;     break ;
+        }
+        if (reboot_requested) {
+            printf("Unexpected ASR Reboot. Rebooting MCU.\n") ;
+            wait_ms(100) ;
+            reboot_edge() ;
+        }
+        break ; 
+    case ATTR_MCU_INTERFACE:
+        printf("MCU Interface: ") ;
+        switch(value[0]) {
+        case 0:  printf("No MCU\n") ;    break ;
+        case 1:  printf("SPI Slave\n") ; break ;
+        case 2:  printf("UART\n") ;      break ;
+        default: printf("Unknown\n") ;   break ; 
+        }
+        break ;
+    case AF_SYSTEM_ASR_STATE:
+        printf("ASR state: ") ;
+        switch(value[0]) {
+        case MODULE_STATE_REBOOTED:
+            gLinked = false ;
+            printf("Rebooted\n") ;
+//            wait_ms(100) ; /* */
+            if (edge_mgr_status == EDGE_MGR_RUNNING) {
+                result = afero->getAttribute(ATTR_REBOOT_REASON) ;
+                reboot_requested = true ;
+//                reboot_edge() ;
+            }
+            break ;
+        case MODULE_STATE_LINKED:
+            if (gLinked == false) { /* new link established */
+                result = afero->getAttribute(ATTR_LINKED_TIMESTAMP) ;
+                if (result != afSUCCESS) {
+                    printf("getAttriute for ATTR_LINKED_TIMESTAMP failed\n") ;
+                }
+            }
+            gLinked = true ;
+            printf("Linked\n") ;
+            break ;
+        case MODULE_STATE_UPDATING:
+            gLinked = true ; 
+            printf("Updating\n") ;
+            if (display) {
+                display->cls() ;
+                display->locate(5, 5) ;
+                display->printf("FW Updating...") ;
+            }
+            break ;
+        case MOUDLE_STATE_UPDATE_READY:
+            gLinked = false ;
+            printf("Update ready - rebooting\n") ;
+            if (display) {
+                display->cls() ;
+                display->locate(5, 5) ;
+                display->printf("Rebooting...") ;
+            }
+            while(afero->setAttribute32(AF_SYSTEM_COMMAND, MODULE_COMMAND_REBOOT) != afSUCCESS) {
+                afero->loop() ;
+                wait_us(100) ;
+            }
+            reboot_edge() ;
+            break ;
+        default:
+            break ;
+        }
+        break ;
+    default:
+        assignAttribute(requestId, attributeId, valueLen, value, false) ;
+        break ;
+    }      
+    if ((pending != 0)&&(pending->request->requestId == requestId)) {
+        printf("Request [%d] replied in %d sec!\n", requestId, pending->replied_time - pending->submit_time) ;
+        delete pending ;
+        pending = 0 ;
+    }      
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/af_attributes.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,201 @@
+#ifndef _AF_ATTRIBUTES_H_
+#define _AF_ATTRIBUTES_H_
+
+#include "mbed.h"
+#include "afLib.h"
+
+/**
+ * af_attributes.h
+ *
+ */
+
+#define ATTRIBUTE_TYPE_SINT8                                       2
+#define ATTRIBUTE_TYPE_SINT16                                      3
+#define ATTRIBUTE_TYPE_SINT32                                      4
+#define ATTRIBUTE_TYPE_SINT64                                      5
+#define ATTRIBUTE_TYPE_BOOLEAN                                     1
+#define ATTRIBUTE_TYPE_UTF8S                                      20
+#define ATTRIBUTE_TYPE_BYTES                                      21
+#define ATTRIBUTE_TYPE_FIXED_15_16                                 6
+
+#define afSUCCESS                    0    // Operation completed successfully
+#define afERROR_NO_SUCH_ATTRIBUTE   -1    // Request was made for unknown attribute id
+#define afERROR_BUSY                -2    // Request already in progress, try again
+#define afERROR_INVALID_COMMAND     -3    // Command could not be parsed
+#define afERROR_QUEUE_OVERFLOW      -4    // Queue is full
+#define afERROR_QUEUE_UNDERFLOW     -5    // Queue is empty
+#define afERROR_INVALID_PARAM       -6    // Bad input parameter
+
+#define AF_SYSTEM_COMMAND            65012
+#define AF_SYSTEM_ASR_STATE          65013
+#define AF_SYSTEM_LINKED_TIMESTAMP   65015
+
+#define MODULE_STATE_REBOOTED                 0
+#define MODULE_STATE_LINKED                   1
+#define MODULE_STATE_UPDATING                 2
+#define MOUDLE_STATE_UPDATE_READY             3
+
+#define MODULE_COMMAND_NONE                   0
+#define MODULE_COMMAND_REBOOT                 1
+
+#define ATTR_SENSE_VAL               1
+#define ATTR_ACCEL_PRESENT           100
+#define ATTR_ACCEL_ENABLE            101
+#define ATTR_ACCEL_INTERVAL          102 
+#define ATTR_ACCEL_VALUE             103
+
+#define ATTR_COLOR0_PRESENT          200
+#define ATTR_COLOR0_ENABLE           201
+#define ATTR_COLOR0_INTERVAL         202
+#define ATTR_COLOR0_TRIGMODE         203
+#define ATTR_COLOR0_ITIME            204
+#define ATTR_COLOR0_CALIBRATE        205
+#define ATTR_COLOR0_PWM_R            206
+#define ATTR_COLOR0_PWM_G            207
+#define ATTR_COLOR0_PWM_B            208
+#define ATTR_COLOR0_PWM_PERIOD       209
+#define ATTR_COLOR0_PWM_TARGET       210
+#define ATTR_COLOR0_R_VALUE          211
+#define ATTR_COLOR0_G_VALUE          212
+#define ATTR_COLOR0_B_VALUE          213
+
+#define ATTR_COLOR1_PRESENT          220
+#define ATTR_COLOR1_ENABLE           221
+#define ATTR_COLOR1_INTERVAL         222
+#define ATTR_COLOR1_TRIGMODE         223
+#define ATTR_COLOR1_ITIME            224
+#define ATTR_COLOR1_CALIBRATE        225
+#define ATTR_COLOR1_PWM_R            226
+#define ATTR_COLOR1_PWM_G            227
+#define ATTR_COLOR1_PWM_B            228
+#define ATTR_COLOR1_PWM_PERIOD       229
+#define ATTR_COLOR1_PWM_TARGET       230
+#define ATTR_COLOR1_R_VALUE          231
+#define ATTR_COLOR1_G_VALUE          232
+#define ATTR_COLOR1_B_VALUE          233
+
+/* temperature sensor LM75B with color0 */
+#define ATTR_TEMP0_PRESENT           300
+#define ATTR_TEMP0_ENABLE            301
+#define ATTR_TEMP0_INTERVAL          302
+#define ATTR_TEMP0_VALUE             303
+
+/* temperature sensor AT502-11 (before) */
+#define ATTR_TEMP1_PRESENT           310
+#define ATTR_TEMP1_ENABLE            311
+#define ATTR_TEMP1_INTERVAL          312
+#define ATTR_TEMP1_VALUE             313
+
+/* temperature sensor AT502-11 (after) */
+#define ATTR_TEMP2_PRESENT           320
+#define ATTR_TEMP2_ENABLE            321
+#define ATTR_TEMP2_INTERVAL          322
+#define ATTR_TEMP2_VALUE             323
+
+/* temperature sensor LM75B with color1 */
+#define ATTR_TEMP3_PRESENT           330
+#define ATTR_TEMP3_ENABLE            331
+#define ATTR_TEMP3_INTERVAL          332
+#define ATTR_TEMP3_VALUE             333
+
+/* gas pressure sensor */
+/* gas pressure sensor */
+#define ATTR_GAS_PRESENT            400
+#define ATTR_GAS_ENABLE             401
+#define ATTR_GAS_INTERVAL           402
+#define ATTR_GAS_VALUE              403
+#define ATTR_GAS_THR_MODE           404
+#define ATTR_GAS_THR_HIGH           405
+#define ATTR_GAS_THR_LOW            406
+
+/* current trans sensor */
+#define ATTR_CURRENT_PRESENT         500
+#define ATTR_CURRENT_ENABLE          501
+#define ATTR_CURRENT_INTERVAL        502
+#define ATTR_CURRENT_VALUE           503
+
+#define ATTR_SOFTWARE_RESET          666
+#define ATTR_DISPLAY_MODE            777
+#define ATTR_MCU_RESET_REASON        999
+
+#define ATTR_LED                 1024
+#define ATTR_IO0                 1025
+#define ATTR_IO1                 1026
+#define ATTR_IO2                 1028
+#define ATTR_BUTTON              1030
+#define ATTR_IO3                 1031
+
+#define ATTR_BOOT_LOADER_VER     2001
+#define ATTR_BLE_STACK_VER       2002
+#define ATTR_FW_APP_VER          2003
+#define ATTR_DEVICE_DESC         2004
+#define ATTR_WIFI_VER            2006
+
+#define ATTR_OFFLINE_SCHED      59001
+#define ATTR_SECURITY_ENABLED   60000
+#define ATTR_UTC_OFFSET         65001
+#define ATTR_CONFIGURES_SSID    65004
+#define ATTR_WIFI_BARS          65005
+#define ATTR_WIFI_STDY_STATE    65006
+
+#define ATTR_COMMAND            65012
+#define ATTR_ASR_STATE          65013
+#define ATTR_LOW_BATTERY        65014
+#define ATTR_LINKED_TIMESTAMP   65015
+#define ATTR_ATTR_ACK           65018
+#define ATTR_REBOOT_REASON      65019
+#define ATTR_BLE_COMMS          65020
+#define ATTR_MCU_INTERFACE      65021
+
+#define DISPLAY_MODE_OFF        0
+#define DISPLAY_MODE_GAS        1
+#define DISPLAY_MODE_SUMMARY    2
+#define DISPLAY_MODE_CHART      3
+
+typedef struct {
+    uint16_t id ;
+    char *description ;
+    int attribute_type ;
+    int size ;
+} af_attribute_type ;
+
+/**
+ * get_af_attr
+ * @param id attribute id value to look up
+ * @returns index of the attribute in the af_attribute_type af_attr[]
+ */
+int get_af_attr(uint16_t id) ;
+
+/**
+ * print_af_error
+ * @param resultCode return value from afLib function(s)
+ */
+void print_af_error(int resultCode) ;
+
+/**
+ * Callback that allows ASR to request an MCU attribute be changed. 
+ * You should define this function in your MCU firmware to perform application-specific actions 
+ * your code must take (e.g., updating the state of the hardware), 
+ * in light of the attribute value change.
+*/
+void attributeChangeRequest(
+    const uint8_t   requestId, 
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value
+) ;
+
+/*
+ * Application callback that allows afLib to notify that an attribute has changed. 
+ * This method will be called in response to a getAttribute call from the application 
+ * and whenever a ASR module attribute changes.
+ */
+void attributeUpdatedReport(
+    const uint8_t   requestId,
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value
+) ;
+
+extern afLib *afero ; 
+#endif /* _AF_ATTRIBUTES_H */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/af_mgr.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,46 @@
+#include "mbed.h"
+#include "string.h"
+#include "vt100.h"
+#include "edge_time.h"
+#include "edge_pin.h"
+#include "edge_reset_mgr.h"
+#include "afLib.h"
+#include "pending.h"
+#include "msg_types.h"
+#include "mbedSPI.h"
+#include "af_mgr.h"
+
+afLib           *afero = 0 ;
+pending_class   *pending = 0 ;
+InterruptIn     *afero_int = 0 ;
+mbedSPI         *afero_spi = 0 ;
+DigitalOut      *afero_reset ;
+bool            gLinked = false ;
+bool            gConnected = false ;
+
+void afero_isr(void)
+{
+    afero->mcuISR() ;
+}
+
+void init_aflib(void)
+{
+    afero_reset = new DigitalOut(PIN_ASR_RESET, 1) ; /* create as deasserted */
+    afero_spi = new mbedSPI(PIN_MOSI, PIN_MISO, PIN_SCK, PIN_CS) ;
+
+reset_watch_dog() ;
+    afero = new afLib(
+        PIN_INTR,
+        afero_isr,
+        attributeChangeRequest,
+        attributeUpdatedReport,
+        afero_spi ) ;
+reset_watch_dog() ;
+    wait(0.1) ;
+    *afero_reset = 0 ;
+    wait(0.5) ; /* required 250ms ~ time for reset */
+    *afero_reset = 1 ; 
+reset_watch_dog() ;      
+    wait(0.5) ;
+reset_watch_dog() ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/af_mgr.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,13 @@
+#ifndef _AF_MGR_H_
+#define _AF_MGR_H_
+#include "afLib.h"
+#include "pending.h"
+
+extern afLib           *afero ;
+extern pending_class   *pending ;
+extern bool             gLinked ;
+extern bool             gConnected ;
+
+void init_aflib(void) ;
+
+#endif /* _AF_MGR_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/mbedSPI.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,74 @@
+#include "mbed.h"
+#include "vt100.h"
+#include "afSPI.h"
+#include "mbedSPI.h"
+
+#if defined (TARGET_KL25Z) || defined (TARGET_TEENSY3_1)
+ #ifndef SPI0_C1
+  #define SPI0_C1 (*(uint8_t *)0x40076000)
+ #endif
+#endif
+/*
+class mbedSPI : public afSPI {
+public:
+    mbedSPI(PinName mosi, PinName miso, PinName sckl, PinName cs) ;
+    virtual void begin() ;
+    virtual void beginSPI() ;
+    virtual void endSPI() ;
+    virtual void transfer(char *bytes,int len) ;
+private:
+    SPI         _spi ;
+    DigitalOut  _cs ;
+} ;
+*/
+
+mbedSPI::mbedSPI(PinName mosi, PinName miso, PinName sckl, PinName cs) :
+    _spi(mosi, miso, sckl), _cs(cs, 1)
+{
+    _spi.format(8, 0) ;
+    _spi.frequency(1000000) ; /* 1MHz */
+
+#if defined (TARGET_KL25Z) || defined (TARGET_TEENSY3_1)
+    #ifndef SPI0_C1
+        #define SPI0_C1 (*(uint8_t *)0x40076000)
+    #endif
+//    SPI0_C1 |= 0x01 ; /* LSB First */
+//    SPI0_C1 &= 0xFE ; /* MSB First */
+#endif
+
+}
+
+void mbedSPI::begin(void)
+{
+}
+
+void mbedSPI::beginSPI()
+{
+//    printf("+") ; fflush(stdout) ;
+    _cs = 0 ;
+    SPI0_C1 |= 0x01 ; /* LSB First */
+    wait_us(1) ;
+}
+
+void mbedSPI::endSPI()
+{
+    _cs = 1 ;
+    SPI0_C1 &= 0xFE ; /* MSB First */
+    wait_us(1) ;
+//    printf("-") ; fflush(stdout) ;
+}
+
+/**
+ * on 17-Jan-2018 disable/enable irq added
+ * before and after of each _spi.writes
+ */
+void mbedSPI::transfer(char *bytes, int len)
+{
+    int i ;
+    for (i = 0 ; i < len ; i++ ) {
+        __disable_irq() ; // Disable Interrupts
+        bytes[i] = _spi.write(bytes[i]) ;
+        __enable_irq() ; // Enable Interrupts
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/mbedSPI.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,19 @@
+#ifndef _MBEDSPI_H_
+#define _MBEDSPI_H_
+#include "mbed.h"
+#include "afSPI.h"
+
+class mbedSPI : public afSPI {
+public:
+    mbedSPI(PinName mosi, PinName miso, PinName sckl, PinName cs) ;
+    virtual void begin() ;
+    virtual void beginSPI() ;
+    virtual void endSPI() ;
+    virtual void transfer(char *bytes,int len) ;
+private:
+    SPI         _spi ;
+    DigitalOut  _cs ;
+} ;
+    
+
+#endif /* _MBEDSPI_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/pending.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,55 @@
+#include "mbed.h"
+#include "edge_time.h"
+#include "pending.h"
+
+/*
+class pending_class {
+public:
+pending_class() ;
+~pending_class() ;
+
+request_t *request ;
+uint32_t submit_time ;
+uint32_t replied_time ;
+} ;
+*/
+
+pending_class::pending_class()
+{
+    submit_time = edge_time ; /* save current time */
+    replied_time = 0 ;
+    request = new request_t ;
+    request->messageType = 0 ;
+    request->attrId = 0 ;
+    request->requestId = 0 ;
+    request->valueLen = 0 ;
+    request->p_value = new uint8_t[256] ;
+}
+
+pending_class::pending_class(
+    uint8_t     messageType, 
+    uint16_t    attrId, 
+    uint8_t     requestId, 
+    uint16_t    valueLen, 
+    uint8_t     *value
+) 
+{
+    submit_time = edge_time ; /* save current time */
+    replied_time = 0 ;
+    request = new request_t ;
+    request->p_value = new uint8_t[256] ;
+    request->messageType = messageType ;
+    request->attrId = attrId ;
+    request->requestId = requestId ;
+    request->valueLen = valueLen ;
+    memcpy(request->p_value, value, valueLen) ;
+}
+
+pending_class::~pending_class()
+{
+    submit_time = 0 ;
+    replied_time = 0 ;
+    delete [] request->p_value ;
+    request->p_value = 0 ;
+    delete request ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/pending.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,23 @@
+#ifndef _PENDING_H_
+#define _PENDING_H_
+#include "mbed.h"
+#include "afLib.h"
+#include "af_attributes.h"
+
+class pending_class {
+public:
+    pending_class() ;
+    pending_class(
+        uint8_t     messageType, 
+        uint16_t    attrId, 
+        uint8_t     requestId, 
+        uint16_t    valueLen, 
+        uint8_t     *value
+    ) ;
+    ~pending_class() ;
+
+    request_t *request ;
+    uint32_t submit_time ;
+    uint32_t replied_time ;
+} ;
+#endif /* _PENDING_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_sensor/edge_accel.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,163 @@
+#include "mbed.h"
+#include "afLib.h"
+#include "edge_reset_mgr.h"
+#include "edge_sensor.h"
+#include "edge_accel.h"
+#include "MMA8451Q.h"
+
+edge_accel::edge_accel(MMA8451Q *accel) : edge_sensor() 
+{
+    _accel = accel ;
+    _sample_count = 0 ;
+    _accumulation = 0 ;
+    _prev_x = 0 ;
+    _prev_y = 0 ;
+    _prev_z = 0 ;
+    
+    _interval = 30 ;
+}
+
+edge_accel::~edge_accel(void)
+{
+    delete _accel ;
+}
+
+void    edge_accel::reset(void) 
+{
+    clear_value() ;
+    edge_sensor::reset() ;
+}
+
+#if 0
+void    edge_accel::prepare(void) 
+{
+//    printf("accel prepare\n") ;
+}
+#endif
+
+int    edge_accel::sample(void) 
+{
+    int result ;
+    float theValue = 0.0 ;
+    if (_sample_count > 1) { /* if sample is 1 or less, no data */
+        _num_sampled = _sample_count - 1 ;
+        theValue = (float)_accumulation / (float)(_num_sampled) ;
+        result = 0 ; /* success */
+    } else {
+        result = 1 ; /* fail! */
+    }
+    _value = theValue / 4096.0 ;
+    _sampled_time = edge_time ;
+    _sample_count = 0 ;
+    _accumulation = 0 ;
+    return( result ) ;
+}
+
+int    edge_accel::deliver(void) 
+{
+    int result ;
+    char timestr[16] ;
+    
+    print_time(_sampled_time) ;
+//    _value = get_value() ;
+    printf(" accel: %.3f [%d samples]\n", _value, _num_sampled) ;
+    time2seq(_sampled_time, timestr) ;
+    sprintf(_str_buf,
+        "{\"DEVICE\":\"ACCEL\",\"PN\":\"MMA8451Q\",\"VAL_X\":\"%.3f\",\"VAL_Y\":\"0\",\"VAL_Z\":\"0\",\"UNIT\":\"g\",\"T\":\"%s\",\"E\":\"%d\"}",
+        _value, timestr, _error_count) ;
+    result = afero->setAttribute(1, _str_buf) ;
+
+    return( result == afSUCCESS ) ;
+}
+
+int accel_v2y(float value, edge_chart_type *p)
+{
+    int y ;
+    if (value < p->min) {
+        value = p->min ;
+    } else if (value > p->max) {
+        value = p->max ;
+    }
+    y = p->top + p->height/2 - 1
+        - (int)((p->height - 2) * value /(p->max - p->min)) ;
+    return( y ) ;
+}
+
+void edge_accel::show(void)
+{
+    int x, y ;
+    edge_chart_type *p = &edge_chart[0] ; /* edge_chart for accel */
+    reset_watch_dog() ;
+    if (display) {
+        switch(display_mode) {
+        case DISPLAY_MODE_SUMMARY:
+            display->BusEnable(true) ;
+            display->set_font((unsigned char*) Arial12x12);
+            display->set_font_zoom(2, 2) ;
+            display->foreground(White) ;
+            display->locate(EDGE_SUMMARY_X, EDGE_SUMMARY_TIME_Y) ;
+            displayTime(_sampled_time) ;
+//          display->locate(10, 5) ;
+//          display->printf(timestr) ;
+            display->locate(EDGE_SUMMARY_X, EDGE_SUMMARY_ACCEL_Y) ;
+            display->printf("Accel: %.3f [%4d]", _value, _num_sampled) ;
+            display->BusEnable(false) ;
+            reset_watch_dog() ;
+            break ;
+        case DISPLAY_MODE_CHART:
+            x = p->left + p->index + 1;
+            y = accel_v2y(_value, p) ;
+            display->BusEnable(true) ;
+            if (p->index == 0) {
+                draw_chart_frame(p) ;
+            }
+            display->pixel(x, y, White) ;
+            display->BusEnable(false) ;
+            p->index = (p->index + 1) % (p->width - 2) ;
+            break ;
+        default:
+            break ;
+        }
+    }
+    clear_value() ;
+    reset_watch_dog() ;
+}
+
+int edge_accel::accum(void)
+{
+    int result ;
+    int16_t value[3] ;
+
+    if (_enable) {
+       result = _accel->getAllRawData(value) ;
+       
+        if (result == 0) { /* success */
+            if (_sample_count != 0) { /* first data does not have prev_data */
+                    _accumulation +=
+                    abs(_prev_x - value[0])
+                    + abs(_prev_y - value[1])
+                    + abs(_prev_z - value[2]) ; 
+            }
+            
+            _sample_count++ ;
+    
+            _prev_x = value[0] ;
+            _prev_y = value[1] ;
+            _prev_z = value[2] ;
+        }
+    }
+        
+    return( result ) ;
+}
+
+void edge_accel::clear_value(void)
+{
+    _sample_count = 0 ;
+    _accumulation = 0 ;
+    _prev_x = 0 ;
+    _prev_y = 0 ;
+    _prev_z = 0 ;
+}
+
+
+        
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_sensor/edge_accel.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,78 @@
+#ifndef _EDGE_ACCEL_H_
+#define _EDGE_ACCEL_H_
+#include "mbed.h"
+#include "edge_sensor.h"
+#include "MMA8451Q.h"
+
+/**
+ * edge_accel edge_sensor which manage the accelerometer sensor (MMA8451Q)
+ * @note The behavior of this class is somewhat exceptional as an edge_sensor
+ * @note it samples and accumulates data which is the abs sum of current
+ * @note values and previous values every 0.1 sec
+ * @note and in each "interval" it delivers the averaged value 
+ */
+
+class edge_accel : public edge_sensor {
+public:
+/**
+ * constructor
+ * @param the MMA8451Q object
+ */
+    edge_accel(MMA8451Q *accel) ;
+    
+/**
+ * destructor
+ */
+    ~edge_accel(void) ;
+
+/**
+ * clear and reset interval values
+ */
+    virtual void    reset(void) ;
+//    virtual void    prepare(void) ;
+
+/**
+ * sample calculate the average value
+ * from _accumulation and _sample_count
+ * the average value is assigned to _value
+ * and currnt _sample_count is stored in _num_sampled
+ * then both _accumuation and _sample_count will be cleared
+ * @returns 0: success non-0: failure
+ */
+    virtual int    sample(void) ;
+    
+/**
+ * deliver the value to the afero cloud
+ */
+    virtual int     deliver(void) ;
+    
+/**
+ * show the data in the display (TFT)
+ */
+    virtual void    show(void) ;
+        
+/**
+ * accum this is the real sampling
+ * and the differences of sampled values 
+ * and previous values are calcurated and accumulated
+ * @returns 0: success non-0: failure
+ */
+    int accum(void) ;
+    
+/**
+ * Clear internal values
+ */
+    void clear_value(void) ;
+
+private:
+    MMA8451Q *_accel ;
+    float   _value ;
+    int32_t _num_sampled ;
+    int32_t _sample_count ;
+    int32_t _accumulation ;
+    int16_t _prev_x ;
+    int16_t _prev_y ;
+    int16_t _prev_z ;
+} ;
+
+#endif /* _EDGE_ACCEL_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_sensor/edge_color.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,443 @@
+#include "mbed.h"
+#include "edge_sensor.h"
+#include "VEML6040.h"
+#include "edge_color.h"
+#include "edge_reset_mgr.h"
+#include "edge_chart.h"
+
+/* VEML6040 config bits */
+/* sensor config loser 4bit */
+/* trigger mode etc. */
+#define SD_BIT   0x01
+#define AF_BIT   0x02
+#define TRIG_BIT 0x04
+
+/* sensor config upper 4bit */
+/* integration time */
+ int sensor_delay[] = { 
+    40,
+    80,
+    160,
+    320,
+    640,
+    1280, 
+    1280, /* place holder */ 
+    1280  /* place holder */
+} ;
+
+uint16_t        color0_pwm[3] ;
+uint16_t        color1_pwm[3] ;
+uint16_t        color0_target[3] = { 3500, 3500, 3500 } ;
+uint16_t        color1_target[3] = { 3500, 3500, 3500 } ;
+
+
+edge_color::edge_color(VEML6040 *sensor, PwmOut *led[], uint16_t *pwm) : edge_sensor() 
+{
+    uint16_t dummy[3] ;
+    _sensor = sensor ;
+    _sensor_config = AF_BIT | TRIG_BIT ;
+    _interval = 30 ;
+    _calibration_request = 0 ; /* 1 for testing */ 
+
+reset_watch_dog() ;
+    _pwm_period = 2000 ; /* 2ms */
+    _probe = 0xFA00 ; /* to avoid satulation at 255, using 250 */
+//    _probe = 0xFF00 ; 
+    for (int i = 0 ; i < 3 ; i++ ) {
+        _led[i] = led[i] ;
+        _led[i]->write(1.0) ; /* turn LED off */
+        _value[i] = 0 ;
+        _pwm[i] = pwm[i] ;
+        _led[i]->period_us(_pwm_period) ;
+    }
+    getRGB(dummy) ; // dummy read, the first data is usually garbage
+reset_watch_dog() ;
+}
+
+edge_color::~edge_color(void) 
+{
+    delete _sensor ;
+    delete [] _led ;
+}
+
+void edge_color::setLEDs(uint16_t led_value[]) 
+{
+    for (int i = 0 ; i < 3 ; i++ ) {
+        _led[i]->write((float)(65535 - led_value[i])/65535.0) ;
+    }
+}
+
+void edge_color::setLEDs(uint16_t r, uint16_t g, uint16_t b) 
+{
+    _led[0]->write((float)(65535 - r)/65535.0) ;
+    _led[1]->write((float)(65535 - g)/65535.0) ;
+    _led[2]->write((float)(65535 - b)/65535.0) ;
+}
+
+void edge_color::reset(void) 
+{
+    for (int i = 0 ; i < 3 ; i++ ) {
+        _value[i] = 0 ;
+    }
+}
+
+void edge_color::prepare(void) 
+{
+//    setLEDs(_pwm) ; // <- the other color sensor turns off (;_;)
+}
+
+int edge_color::sample(void) 
+{
+    int result ;
+reset_watch_dog() ;
+    setLEDs(_pwm) ;
+reset_watch_dog() ;
+    result = getRGB(_value) ;
+    _sampled_time = edge_time ;
+    setLEDs(0, 0, 0) ; /* turn LEDs off */
+reset_watch_dog() ;
+    return( result ) ;
+}
+
+int edge_color::deliver(void) 
+{
+    int result ;
+    char timestr[16] ;
+    print_time(_sampled_time) ;
+    time2seq(_sampled_time, timestr) ;
+    printf(" color%d : R = %4d, G = %4d, B = %4d\n",
+        _id, _value[0], _value[1], _value[2]) ;
+    if (_id == 1) { /* color1 */
+    sprintf(_str_buf,
+          "{\"DEVICE\":\"COLOR\",\"PN\":\"VEML6040\",\"VAL_R\":\"%d\",\"VAL_G\":\"%d\",\"VAL_B\":\"%d\",\"UNIT\":\"mW/cm2\",\"T\":\"%s\",\"E\":\"%d\"}",
+          _value[0], _value[1], _value[2], timestr, _error_count) ; 
+    } else { /* color2 */
+        sprintf(_str_buf,
+          "{\"DEVICE\":\"COLOR02\",\"PN\":\"VEML6040\",\"VAL_R\":\"%d\",\"VAL_G\":\"%d\",\"VAL_B\":\"%d\",\"UNIT\":\"mW/cm2\",\"T\":\"%s\",\"E\":\"%d\"}",
+          _value[0], _value[1], _value[2], timestr, _error_count) ; 
+    }
+    result = afero->setAttribute(1, _str_buf) ;
+
+    return( result == afSUCCESS ) ;
+}
+
+int color_v2y(float value, edge_chart_type *p)
+{
+    int y ;
+    if (value < p->min) {
+        value = p->min ;
+    } else if (value > p->max) {
+        value = p->max ;
+    }
+    y = p->top + p->height - 1
+        - (int)((p->height - 2) * value /(p->max - p->min)) ;
+    return( y ) ;
+}
+
+void edge_color::show(void)
+{
+    int r, g, b ;
+    int x ;
+    edge_chart_type *p = &edge_chart[_id] ;
+    if (display) {
+        switch(display_mode) {
+        case DISPLAY_MODE_SUMMARY:
+            reset_watch_dog() ;
+            display->BusEnable(true) ;
+            display->set_font((unsigned char*) Arial12x12);
+            display->set_font_zoom(2, 2) ;
+            display->foreground(White) ;
+            display->locate(EDGE_SUMMARY_X, EDGE_SUMMARY_TIME_Y) ;
+            displayTime(_sampled_time) ;
+            if (_id == 1) {
+                display->locate(EDGE_SUMMARY_X, EDGE_SUMMARY_COLOR1_Y) ;
+                display->printf("Color :%5d,%5d,%5d",
+                    _value[0], _value[1], _value[2]) ;
+            } else {
+                display->locate(EDGE_SUMMARY_X, EDGE_SUMMARY_COLOR2_Y) ;
+                display->printf("Color2:%5d,%5d,%5d",
+                    _value[0], _value[1], _value[2]) ;
+            }
+            display->BusEnable(false) ;
+            reset_watch_dog() ;
+            break ;
+        case DISPLAY_MODE_CHART:
+            reset_watch_dog() ;
+            x = p->left + p->index + 1 ;
+            r = color_v2y(_value[0], p) ;
+            g = color_v2y(_value[1], p) ;
+            b = color_v2y(_value[2], p) ;
+            display->BusEnable(true) ;
+            if (p->index == 0) {
+                draw_chart_frame(p) ;
+            }
+            display->pixel(x, r, Red) ;
+            display->pixel(x, g, Green) ;
+            display->pixel(x, b, Blue) ;
+            display->BusEnable(false) ;
+            p->index = (p->index + 1) % (p->width - 2) ;
+            break ;       
+        }
+    }   
+    reset_watch_dog() ;
+}
+
+int edge_color::getRGB(uint16_t v[])
+{
+    int result ;
+    result = _sensor->setCOLORConf(_sensor_config) ;
+    if (result == 0) {
+        wait_ms(sensor_delay[(_sensor_config >> 4)&0x07] * 1.25) ;
+     
+        result = _sensor->getRData(&v[0]) ;
+        if (result == 0) {
+            wait_ms(10) ;
+            result = _sensor->getGData(&v[1]) ;
+            if (result == 0) {
+                wait_ms(10) ;
+                result = _sensor->getBData(&v[2]) ;
+                if (result == 0) {
+                    wait_ms(10) ;
+                }
+            }
+        }
+    }
+    return( result ) ;
+}
+
+/**
+ * Measure num_ave + 2 times
+ * and throw away min and max
+ * before calculating average
+ */ 
+void edge_color::getAveColor(uint16_t led[], uint16_t v[], int num_ave)
+{
+    int i, c ;
+    uint16_t min[3] = { 0, 0, 0 } ;
+    uint16_t max[3] = { 0, 0, 0 } ;
+    uint16_t tmp[3] ;
+    long sum[3] = { 0, 0, 0 } ;
+        
+reset_watch_dog() ;
+    setLEDs(led) ;
+    getRGB(tmp) ; // dummy read
+    setLEDs(0, 0, 0) ;
+    wait_ms(10) ;
+    for (i = 0 ; i < num_ave+2 ; i++ ) {
+reset_watch_dog() ;
+        setLEDs(led) ;
+        getRGB(tmp) ;
+        setLEDs(0, 0, 0) ;
+        wait_ms(10) ;
+        for (c = 0 ; c < 3 ; c++ ) {
+            sum[c] += tmp[c] ;
+            if ((i == 0) || (tmp[c] < min[c])) {
+                min[c] = tmp[c] ;
+            }
+            if ((i == 0) || (tmp[c] > max[c])) {
+                max[c] = tmp[c] ;
+            }
+        }
+    }    
+reset_watch_dog() ;
+    for (c = 0 ; c < 3 ; c++ ) {
+        sum[c] = sum[c] - (min[c] + max[c]) ;
+        v[c] = (uint16_t)(sum[c] / num_ave) ;
+    }
+//    delete [] tmp ;
+// printf("=== average ===\n") ;
+// printf("%04x %04x %04x\n", v[0], v[1], v[2]) ;
+}
+
+#if 1
+void edge_color::calibrate(uint16_t target[], uint16_t result[], int num_ave) 
+{
+//   const uint16_t led_interval = 10 ; /* wait 10ms for LED */
+    float      denominator ;
+    float      numerator[3] ;
+    float      a,b,c,d,e,f,g,h,i ;
+    uint16_t  v[3], tmp[3] ;
+    uint16_t  L[3][3] ;
+    int       idx ;
+    uint8_t   conf ;
+
+    printf("=== Calibrating Color Sensor %d ===\n", _id) ;
+    for (idx = 0 ; idx < 3 ; idx++ ) {
+reset_watch_dog() ;
+        tmp[0] = tmp[1] = tmp[2] = 0 ;
+        tmp[idx] = _probe ;
+
+//        setLEDs(tmp) ;
+//        wait_ms(led_interval) ;
+        getAveColor(tmp, v, num_ave) ;
+        
+        printf("R:%5d, G:%5d, B:%5d\n", v[0], v[1], v[2]) ;
+        L[idx][0] = v[0] ;
+        L[idx][1] = v[1] ;
+        L[idx][2] = v[2] ;
+//        setLEDs(0, 0, 0) ; /* clear LEDs */
+    }
+    
+reset_watch_dog() ;
+    printf("=== Initial Equation ===\n") ;
+    for (idx = 0 ; idx < 3 ; idx++) {
+        printf("%5d * R / %d + %5d * G / %d + %5d * B / %d = %d,\n",
+        L[0][idx], _probe, L[1][idx], _probe,  L[2][idx], _probe, target[idx]) ;
+    }
+
+     a = L[0][0] ; b = L[1][0] ; c = L[2][0] ;
+     d = L[0][1] ; e = L[1][1] ; f = L[2][1] ;
+     g = L[0][2] ; h = L[1][2] ; i = L[2][2] ;
+     
+    denominator = a * (f * h - e * i) + b * (d * i - f * g) + c * (e * g - d * h) ;
+//    printf("Denominator = %f\n", denominator) ;
+
+    if (denominator != 0) {
+        numerator[0] = (f * h - e * i) * target[0] 
+            + b * (i * target[1] - f * target[2]) 
+            + c * (e * target[2] - h * target[1]) ;
+
+        numerator[1] = -((f * g - d * i) * target[0]
+            + a * (i * target[1] - f * target[2]) 
+            + c * (d * target[2] - g * target[1])) ;
+
+        numerator[2] = (e * g - d * h) * target[0]
+            + a * (h * target[1] - e * target[2]) 
+            + b * (d * target[2] - g * target[1]) ;
+
+        for (idx = 0 ; idx < 3 ; idx++ ) {
+// printf("Numerator[%d] = %f\n", idx, numerator[idx]) ;
+            _pwm[idx] = (uint16_t) (0.5 + (((double)_probe * numerator[idx]) / denominator)) ;
+            result[idx] = _pwm[idx] ;
+        }
+
+        printf("PWM R = %d [0x%04x] ", result[0], result[0]) ; 
+        wait_ms(1) ;
+        printf("G = %d [0x%04x] ", result[1], result[1]) ;
+        wait_ms(1) ;
+        printf("B = %d [0x%04x] ", result[2], result[2]) ;
+        wait_ms(1) ;
+        printf("\n") ;
+        wait_ms(1) ;
+        printf("=== test ===\n") ;
+//        setLEDs(_pwm[0], _pwm[1], _pwm[2]) ;
+//        wait_ms(led_interval) ;
+        getAveColor(_pwm, v, num_ave) ;
+        printf("R:%d, G:%d, B:%d\n", v[0], v[1], v[2]) ;
+        printf("============\n") ;
+        wait_ms(1) ;
+    } else {
+        printf("calibration failed, pwm values were not updated\n") ;
+    }
+    printf("Reseting Color Sensor ... ") ;
+reset_watch_dog() ;
+    _sensor->getCOLORConf(&conf) ;
+    wait_ms(10) ;
+    _sensor->setCOLORConf(conf | 0x01) ; /* shutdown VEML6040 */
+    wait_ms(200) ;
+reset_watch_dog() ;
+    _sensor->setCOLORConf(conf) ;
+    wait_ms(200) ;
+    printf("Done\n") ;
+    _calibration_request = 0 ;
+    _status = EDGE_SENSOR_INACTIVE ;
+reset_watch_dog() ;
+}
+#endif /* calibration int version */
+
+#if 0
+void edge_color::calibrate(uint16_t target[], uint16_t result[], int num_ave) 
+{
+   const uint16_t led_interval = 10 ; /* wait 10ms for LED */
+    double      denominator ;
+    double      numerator[3] ;
+    double      a,b,c,d,e,f,g,h,i ;
+    uint16_t    v[3], tmp[3] ;
+//    uint16_t    L[3][3] ;
+    double    L[3][3] ;
+    double      ftarget[3] ;
+    int         idx ;
+    uint8_t     conf ;
+    
+    ftarget[0] = target[0] ;
+    ftarget[1] = target[1] ;
+    ftarget[2] = target[2] ;
+    printf("=== Calibrating Color Sensor %d ===\n", _id) ;
+    for (idx = 0 ; idx < 3 ; idx++ ) {
+reset_watch_dog() ;
+        tmp[0] = tmp[1] = tmp[2] = 0 ;
+        tmp[idx] = _probe ;
+
+        setLEDs(tmp) ;
+        wait_ms(led_interval) ;
+        getAveColor(v, num_ave) ;
+        
+        printf("R:%5d, G:%5d, B:%5d\n", v[0], v[1], v[2]) ;
+        L[idx][0] = v[0] ;
+        L[idx][1] = v[1] ;
+        L[idx][2] = v[2] ;
+        setLEDs(0, 0, 0) ; /* clear LEDs */
+    }
+    
+reset_watch_dog() ;
+    printf("=== Initial Equation ===\n") ;
+    for (idx = 0 ; idx < 3 ; idx++) {
+        printf("%5d * R / %d + %5d * G / %d + %5d * B / %d = %d,\n",
+        (int)L[0][idx], _probe, (int)L[1][idx], _probe,  (int)L[2][idx], _probe, target[idx]) ;
+    }
+
+     a = L[0][0] ; b = L[1][0] ; c = L[2][0] ;
+     d = L[0][1] ; e = L[1][1] ; f = L[2][1] ;
+     g = L[0][2] ; h = L[1][2] ; i = L[2][2] ;
+     
+    denominator = a * (f * h - e * i) + b * (d * i - f * g) + c * (e * g - d * h) ;
+
+    if (denominator != 0) {
+        numerator[0] = (f * h - e * i) * ftarget[0] 
+            + b * (i * ftarget[1] - f * ftarget[2]) 
+            + c * (e * ftarget[2] - h * ftarget[1]) ;
+
+        numerator[1] = -((f * g - d * i) * ftarget[0]
+            + a * (i * ftarget[1] - f * ftarget[2]) 
+            + c * (d * ftarget[2] - g * ftarget[1])) ;
+
+        numerator[2] = (e * g - d * h) * ftarget[0]
+            + a * (h * ftarget[1] - e * ftarget[2]) 
+            + b * (d * ftarget[2] - g * ftarget[1]) ;
+
+        for (idx = 0 ; idx < 3 ; idx++ ) {
+            _pwm[idx] = (uint16_t) (0.5 + ((double)_probe * numerator[idx]) / denominator) ;
+            result[idx] = _pwm[idx] ;
+        }
+
+        printf("PWM R = %d [0x%04x] ", result[0], result[0]) ; 
+        wait_ms(1) ;
+        printf("G = %d [0x%04x] ", result[1], result[1]) ;
+        wait_ms(1) ;
+        printf("B = %d [0x%04x] ", result[2], result[2]) ;
+        wait_ms(1) ;
+        printf("\n") ;
+        wait_ms(1) ;
+        printf("=== test ===\n") ;
+        setLEDs(_pwm[0], _pwm[1], _pwm[2]) ;
+        wait_ms(led_interval) ;
+        getAveColor(v, num_ave) ;
+        printf("R:%d, G:%d, B:%d\n", v[0], v[1], v[2]) ;
+        printf("============\n") ;
+        wait_ms(1) ;
+    } else {
+        printf("calibration failed, pwm values were not updated\n") ;
+    }
+reset_watch_dog() ;
+    _sensor->getCOLORConf(&conf) ;
+    wait_ms(10) ;
+    _sensor->setCOLORConf(conf | 0x01) ; /* shutdown VEML6040 */
+    wait_ms(200) ;
+reset_watch_dog() ;
+    _sensor->setCOLORConf(conf) ;
+    wait_ms(200) ;
+    _calibration_request = 0 ;
+    _status = EDGE_SENSOR_INACTIVE ;
+reset_watch_dog() ;
+}
+#endif /* calibration double version */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_sensor/edge_color.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,215 @@
+#ifndef _EDGE_COLOR_H_
+#define _EDGE_COLOR_H_
+#include "mbed.h"
+#include "edge_sensor.h"
+#include "VEML6040.h"
+
+/**
+ * edge_color edge_sensor which manages LED and color sensor (VEML6040)
+ */
+
+class edge_color : public edge_sensor {
+public:
+/**
+ * constructor 
+ * @param *sensor VEML6040 object
+ * @param *led[] PwmOuts for LEDs
+ * @param *pwm[] uint16_t pwm duty values
+ */
+    edge_color(VEML6040 *sensor, PwmOut *led[], uint16_t *pwm) ;
+    
+/**
+ * destructor
+ */
+    ~edge_color(void) ;
+
+/**
+ * reset and clear internal values
+ */
+    virtual void        reset(void) ;
+
+/**
+ * prepare at first this was planned to set LEDs 
+ * before sampling, but turned out to be not neccesarry
+ */
+    virtual void        prepare(void) ;
+
+/**
+ * sample sampling the color value(s) is some what complicated.
+ * At first leds are turned on using the pwm values _pwm[].
+ * then VEML6040 is triggered with config value, which includes
+ * the trigger method and integration time.
+ * Wait for the integration time (actually x 1.25 of the value)
+ * then acquire the color values from VEML6040 and turn the leds off.
+ */
+    virtual int        sample(void) ;
+    
+/**
+ * Deliver the sampled value to the afero cloud.
+ */
+    virtual int         deliver(void) ;
+    
+/**
+ * Show the value(s) in the display (TFT)
+ */
+    virtual void        show(void) ;
+
+/**
+ * calibrate: caribrate the led pwm values trying to adjust the measured
+ * values to the values given in target[]. Measurements are repeated
+ * num_ave+2 times and the minimum and maximum values will be discarded
+ * then average values are calculated using the remaining values.
+ * @param target[] uint16_t target values for R, G, B measurement
+ * @param result[] uint16_t calibrated pwm R,G,B values
+ * @param num_ave repeat time for averaging the measurement data
+ */
+    void        calibrate(uint16_t target[], uint16_t result[], int num_ave) ;
+    
+/**
+ * request_calibration: set the flag to calibrate next avilable time slot
+ */
+    void        request_calibration(void) { _calibration_request = 1 ; }
+    
+/**
+ * calibration_requested
+ * @returns if the calibration is due
+ */
+    int         calibration_requested(void) { return _calibration_request ; }
+    
+/**
+ * getAveColor
+ * @param led[] uint16_t pwm values for R,G,B
+ * @param v[]   uint16_t averaged measurement value
+ * @param num_ave int    measurment repeat time for averaging
+ */
+    void        getAveColor(uint16_t led[], uint16_t v[], int num_ave) ;
+    
+/**
+ * getRGB
+ * @param v[] uint16_t measured R,G,B values
+ * @returns 0: success non-0: failure
+ */
+    int        getRGB(uint16_t v[]) ;
+    
+/**
+ * getConfig
+ * @returns config this value is used to trigger VEML6040 measurement
+ */
+    uint8_t     getConfig(void) { return _sensor_config ; }
+
+/**
+ * setConfig
+ * @param config uint8_t 8bit value to use trigger VEML6040 measurement
+ */
+    void        setConfig(uint8_t config) { _sensor_config = config ; }
+    
+/**
+ * get_pwm_period
+ * @returns pwm_period in us
+ */
+    uint16_t    get_pwm_period(void) { return _pwm_period ; }   
+
+/**
+ * set_pwm_period
+ * @param pwm_period uint16_t pwm period in us
+ */
+    void        set_pwm_period(uint16_t period) { _pwm_period = period ; }
+    
+/**
+ * get_pwm_target
+ * @returns measurment target value controlled by the pwm
+ */
+    uint16_t    get_pwm_target(void) { return _pwm_target ; }
+    
+/**
+ * set_pwm_target
+ * @param target uint16_t measurement target value
+ */
+    void        set_pwm_target(uint16_t target) { _pwm_target = target ; }
+    
+/**
+ * getR
+ * @returns measured value of R
+ */
+    uint16_t    getR(void) { return _value[0] ; }
+
+/**
+ * getG
+ * @returns measured value of G
+ */
+    uint16_t    getG(void) { return _value[1] ; }
+    
+/**
+ * getB
+ * @returns measured value of B
+ */
+    uint16_t    getB(void) { return _value[2] ; }
+    
+/**
+ * getPwmR
+ * @returns PWM value of R LED
+ */
+    uint16_t    getPwmR(void) { return _pwm[0] ; }
+
+/**
+ * setPwmR
+ * @param pwm_r 
+ */
+   void setPwmR(uint16_t pwm_r) { _pwm[0] = pwm_r ; } 
+
+/**
+ * getPwmG
+ * @returns PWM value of G LED
+ */
+    uint16_t    getPwmG(void) { return _pwm[1] ; }
+
+/**
+ * setPwmG
+ * @param pwm_g 
+ */
+   void setPwmG(uint16_t pwm_g) { _pwm[1] = pwm_g ; } 
+    
+/**
+ * getPwmB
+ * @returns PWM value of B LED
+ */
+    uint16_t    getPwmB(void) { return _pwm[2] ; }
+
+/**
+ * setPwmB
+ * @param pwm_b 
+ */
+   void setPwmB(uint16_t pwm_b) { _pwm[2] = pwm_b ; } 
+    
+/**
+ * setLEDs set pwm values to PwmOut pins to drive LEDS
+ * @param led_value[] uint16_t pwm values for R, G, B
+ */
+    void        setLEDs(uint16_t led_value[]) ;
+    
+/**
+ * setLEDs set pwm values to PwmOut pins to drive LEDS
+ * @param r uint16_t pwm value of R LED
+ * @param g uint16_t pwm value of G LED
+ * @param b uint16_t pwm value of B LED
+ */
+    void        setLEDs(uint16_t r, uint16_t g, uint16_t b) ;
+    
+protected:
+    VEML6040    *_sensor ;
+    uint8_t     _sensor_config ;
+    PwmOut      *_led[3] ;
+    uint16_t    _pwm_period ;
+    uint16_t    _pwm_target ;
+    uint16_t    _value[3] ; /* r, g, b */
+    uint16_t    _pwm[3] ;   /* r, g, b */
+    uint16_t    _probe ; /* probing value for calibration */
+    uint8_t     _calibration_request ;
+} ;
+
+extern uint16_t        color0_pwm[3] ;
+extern uint16_t        color1_pwm[3] ;
+extern uint16_t        color0_target[3] ;
+extern uint16_t        color1_target[3] ;
+
+#endif /* _EDGE_COLOR_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_sensor/edge_pressure.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,346 @@
+#include "mbed.h"
+#include "edge_sensor.h"
+#include "edge_time.h"
+#include "edge_reset_mgr.h"
+#include "PSE530.h"
+#include "edge_pressure.h"
+#include <ILI9341.h>
+#include "edge_chart.h"
+// #include "SO1602A.h"
+
+// extern SO1602A *display ; /* OLED display on I2C */
+extern ILI9341 *display ;
+
+#define LOW_THR   0.2
+#define HIGH_THR  0.3 
+#define MIN_TEMP 12.0
+#define MAX_TEMP 30.0
+
+/**
+ * SMC PSE530 pressure sensor
+ * analog output 1.0V - 5.0V
+ * 1.0V : 0
+ * 5.0V : 1MPa
+ * (at 0.6V : -0.1MPa)
+ * Our sensor I/F converts 0-5V to 0-1
+ * So we suppose V = Analog Float Value : Pressure
+ * 0.2 =  0
+ * 1.0 = 1MPa
+ */
+ 
+float temp2expected(float temp)
+{
+    const float coef_A = 0.089 ;
+    const float coef_B = 0.831 ;
+    float pressure ;
+
+    pressure = temp * coef_A + coef_B ;
+    return( pressure ) ;
+}
+
+edge_pressure::edge_pressure(PSE530 *pse, DigitalOut *en)
+{
+    _pse = pse ;
+    _en = en ;
+    _value = 0.0 ;
+    _interval = 30 ;
+    _thr_mode = 0 ;
+    _thr_high = HIGH_THR ;
+    _thr_low = LOW_THR ;
+}
+
+edge_pressure::~edge_pressure(void)
+{
+    if (_pse) {
+        delete _pse ;
+    }
+    _value = 0.0 ;
+}
+
+float edge_pressure::get_value(void)
+{
+    float value = 0.0 ;
+    value = _pse->getPressure() ;
+    return( value ) ;
+}
+
+void edge_pressure::reset(void) 
+{
+    _value = 0.0 ;
+    _sampled_time = 0 ;
+}
+
+void edge_pressure::prepare(void) 
+{
+}
+
+int edge_pressure::sample(void) 
+{
+    int result = 0 ;
+    *_en = 1 ; /* enable pressure sensor */
+    wait_ms(30) ;
+    _value = get_value() ;
+    _sampled_time = edge_time ;
+    *_en = 0 ; /* disable pressure sensor */
+    wait_ms(10) ; /* to avoid power transition effect remaining */
+    return( result ) ; /* this always success */
+}
+
+void edge_pressure::set_thr_high(int16_t thr_high)
+{
+    switch(_thr_mode) {
+    case 0: /* absolute value */
+        _thr_high = (float)thr_high/100.0 ;
+        break ;
+    case 1: /* persentage */
+        _thr_high = (float)(thr_high/100.0) ;
+        break ;
+    default:
+        printf("Unknown Threshold mode %d\n", _thr_mode) ;
+        _thr_high = (float)thr_high/100.0 ;
+        break ;
+    }
+// printf("thr_high = %.3f\n", _thr_high) ;
+}
+
+float edge_pressure::get_thr_high(float expected)
+{
+    float thr_high ;
+    
+    switch(_thr_mode) {
+    case 0: /* absolute value */
+        thr_high = expected + _thr_high ;
+        break ;
+    case 1: /* persentage */
+        thr_high = expected * (1.0 + _thr_high) ;
+        break ;
+    default:
+        printf("Unknown Threshold mode %d\n", _thr_mode) ;
+        thr_high = expected + _thr_high ; /* use this as default */
+        break ;
+    }
+    return (thr_high) ;
+}
+
+void edge_pressure::set_thr_low(int16_t thr_low)
+{   
+    switch(_thr_mode) {
+    case 0: /* absolute value */
+        _thr_low = (float)thr_low/100.0 ;
+        break ;
+    case 1: /* persentage */
+        _thr_low = (float)(thr_low/100.0) ;
+        break ;
+    default:
+        printf("Unknown Threshold mode %d\n", _thr_mode) ;
+        _thr_low = (float)thr_low/100.0 ;
+        break ;
+    }
+//printf("thr_low = %.3f\n", _thr_low) ;
+}
+
+float edge_pressure::get_thr_low(float expected)
+{
+    float thr_low ;
+    
+    switch(_thr_mode) {
+    case 0: /* absolute value */
+        thr_low = expected - _thr_low ;
+        break ;
+    case 1: /* persentage */
+        thr_low = expected * (1.0 - _thr_low) ;
+        break ;
+    default:
+        printf("Unknown Threshold mode %d\n", _thr_mode) ;
+        thr_low = expected + _thr_low ; /* use this as default */
+        break ;
+    }
+    return (thr_low) ;
+}
+
+int edge_pressure::deliver(void) 
+{
+    char str_buf[32] ;
+    char timestr[16] ;
+    int result ;
+
+reset_watch_dog() ;
+    print_time(_sampled_time) ;
+    if (current_temp != 0) {
+        sprintf(str_buf, "GAS: %.3f kgf/cm2 @ %.1fC", _value, *current_temp ) ;
+    } else {
+        sprintf(str_buf, "GAS: %.3f kgf/cm2", _value  ) ;
+    }
+    printf(" ") ;
+    printf(str_buf) ;
+
+    if (current_temp != 0) {
+reset_watch_dog() ;
+        _expected = temp2expected(*current_temp) ;
+        _higher = get_thr_high(_expected) ;
+        _lower = get_thr_low(_expected) ;
+        printf(" (%.3f, %.3f) ", _higher, _lower) ;
+    }
+
+reset_watch_dog() ;
+    printf(" %s\n", str_buf) ;
+    time2seq(_sampled_time, timestr) ;
+//    printf(str_buf) ;
+//    printf("\n") ;
+    sprintf(_str_buf,
+       "{\"DEVICE\":\"PRESS\",\"PN\":\"PSE530\",\"VAL\":\"%.3f\",\"UNIT\":\"kgf/cm2\",\"T\":\"%s\",\"E\":\"%d\"}",
+       _value, timestr, _error_count) ;
+reset_watch_dog() ;
+    result = afero->setAttribute(1, _str_buf) ;
+    return( result == afSUCCESS ) ;
+}
+
+int v2x(float value)
+{
+    int result ;
+    if (value < 0) {
+        result = 20 ;
+    } else if (value > 4) {
+        result = 300 ;
+    } else {
+        result = 20 + (int)(70 * value + 0.5) ;
+    }
+    return( result ) ;
+}
+
+int press_v2y(float value, edge_chart_type *p)
+{
+    int y ;
+    if (value < p->min) {
+        value = p->min ;
+    } else if (value > p->max) {
+        value = p->max ;
+    }
+    y = p->top + p->height - 2
+        - (int)((p->height - 2) * ((value - p->min) /(p->max - p->min))) ;
+    return( y ) ;
+}
+
+/**
+ * drawPointer
+ *
+ * draw a triangle pointer at value place
+ * in GAS pressure display mode 
+ */
+void edge_pressure::drawPointer(int c)
+{
+    float delta_x ;
+    int x[2], y, i ;
+    const int top = 75 ;
+    const int pointer_height = 15 ;
+    for (i = 0 ; i < pointer_height ; i++ ) {
+        y = top + i ;
+        delta_x = i * 5.0 / 8.0 ;
+        x[0] = c - delta_x ;
+        x[1] = c + delta_x ;
+        display->line(x[0], y, x[1], y, White) ;
+    }
+}
+
+void edge_pressure::show(void)
+{
+    edge_chart_type *p = &edge_chart[ _id ] ;
+    uint16_t color = White ;
+    char str_buf[32] ;
+    int i, x, y, l, r, c, str_x ;
+    if (display) {
+        reset_watch_dog() ;
+/* for debug */
+//  _value = _lower - 0.5 ; /* LOW */
+// _value = (_higher + _lower) / 2 ; /* GOOD */
+// _value = _higher + 0.2 ; /* HIGH */
+ 
+        if (_value > _higher) {
+            sprintf(str_buf, "HIGH") ;
+            color = Red ;
+            str_x = 60 ;
+        } else if (_value < _lower) {
+            sprintf(str_buf, "LOW") ;
+            color = Yellow ;
+            str_x = 60 ;
+        } else {
+            sprintf(str_buf, "GOOD") ;
+            color = Green ;
+            str_x = 35 ;
+        }
+        switch(display_mode) {
+        case DISPLAY_MODE_GAS:
+            display->BusEnable(true) ;
+            display->cls() ;
+            /* printf frame */
+            display->foreground(White) ;
+            display->line(20, 75, 300, 75, White) ;
+            for (i = 0 ; i <= 8 ; i++ ) {
+                x = 20 + i * 35 ;
+                if (i & 0x01) { /* odd */
+                    display->line(x, 55, x, 95, White) ;
+                } else { /* even */
+                    display->line(x, 45, x, 105, White) ;
+                }
+            }
+            display->set_font((unsigned char*) Arial28x28);
+            for (i = 0 ; i <= 4 ; i++ ) {
+                x = 12 + i * 70 ;
+                display->locate(x, 10) ;
+                display->printf("%d", i) ;
+            }
+            /* print expected area and current pressure */
+            l = v2x(_lower) ;
+            r = v2x(_higher) ;
+            c = v2x(_value) ;
+//            display->fillrect(l, 70, r, 80, Red) ;
+            display->fillrect(l, 65, r, 74, Red) ;
+//            display->fillcircle(c, 75, 10, White) ;
+            drawPointer(c) ;
+                    
+            /* print status */
+            display->locate(str_x, 140) ;
+            display->set_font_zoom(3, 3) ;
+            display->foreground(color) ;
+            display->printf(str_buf) ;
+            display->set_font_zoom(1, 1) ;
+            display->BusEnable(false) ;
+            break ;
+        case DISPLAY_MODE_SUMMARY:
+            display->BusEnable(true) ;
+            display->set_font((unsigned char*) Arial12x12);
+            display->set_font_zoom(2, 2) ;
+            display->foreground(White) ;
+            display->locate(10, EDGE_SUMMARY_TIME_Y) ;
+            displayTime(_sampled_time) ;
+//          display->locate(10,50) ;
+//          display->printf(timestr) ;
+            display->locate(10, EDGE_SUMMARY_PRESS_Y) ;
+            display->printf("Press: ") ;
+            display->foreground(color) ;
+            display->locate(90, EDGE_SUMMARY_PRESS_Y) ;
+            display->printf("%.3f ", _value) ;
+            display->foreground(White) ;
+            display->printf("kgf/cm2") ;
+            display->BusEnable(false) ;
+            break ;
+        case DISPLAY_MODE_CHART:
+            x = p->left + p->index + 1;
+            y = press_v2y(_value, p) ;
+            display->BusEnable(true) ;
+            if (p->index == 0) {
+                draw_chart_frame(p) ;
+            }
+            display->foreground(color) ;
+            display->pixel(x, y, color) ;
+            display->set_font((unsigned char*) Arial12x12);
+            display->locate(p->left + 40, p->top + 5) ;
+            display->printf("%5s", str_buf) ;
+            display->foreground(White) ;
+            display->BusEnable(false) ;
+            p->index = (p->index + 1) % (p->width - 2) ;
+            break ;
+        }
+    }
+    reset_watch_dog() ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_sensor/edge_pressure.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,115 @@
+#ifndef _EDGE_PRESSURE_H_
+#define _EDGE_PRESSURE_H_
+#include "mbed.h"
+#include "edge_sensor.h"
+#include "PSE530.h"
+
+/**
+ * edge_pressure edge_sensor for measuring gas presssure
+ */
+
+class edge_pressure : public edge_sensor {
+public:
+/**
+ * constructor 
+ * @param *pse PSE530 pressure sensor object
+ */
+    edge_pressure(PSE530 *pse, DigitalOut *en) ;
+
+/**
+ * destructor
+ */
+    ~edge_pressure(void) ;
+    
+/**
+ * reset and clear internal values
+ */
+    virtual void    reset(void) ;
+
+/**
+ * prepare for sampling (not used)
+ */
+    virtual void    prepare(void) ;
+    
+/**
+ * sample the value
+ * @returns 0: success non-0: failure
+ */
+    virtual int    sample(void) ;
+
+/**
+ * deliver the sampled value to afero cloud
+ */
+    virtual int     deliver(void) ;
+    
+/**
+ * show the value in the display (TFT)
+ */
+    virtual void    show(void) ;
+//    virtual void    send_config(void) ; /* send config data to cloud */
+//    virtual void    recv_config(void) ; /* receive config data from cloud */
+
+/**
+ * get_value sample sensor value and calcurate it to the metric value
+ * @returns measured value in kgf/cm2
+ */
+    float get_value(void) ;
+
+/**
+ * Set threshold mode
+ * @param mode int 0: absolute value 1: relative value in percent
+ */
+    void  set_thr_mode(int mode)    { _thr_mode = mode ; }
+
+/**
+ * Get threshold mode
+ * @returns the mode 0: absolute value 1: relative value in percent
+ */
+    int   get_thr_mode(void)        { return _thr_mode ; }
+    
+/**
+ * Set higher threshold
+ * @param thr_high int16_t the higher threshold
+ */
+    void  set_thr_high(int16_t thr_high) ;
+    
+/**
+ * Get higher threshold, the value is calcurated with expected value
+ * @param expected float the expected pressure value for current temperature
+ */
+    float get_thr_high(float expected) ;
+    
+/**
+ * Set lower threshold
+ * @param thr_low int16_t the lower threshold
+ */
+    void  set_thr_low(int16_t thr_low) ;
+    
+/**
+ * Get lower threshold, the value is calcurated with expected value
+ * @param expected float the expected pressure value for current temperature
+ */
+    float get_thr_low(float expected)  ;
+    
+/**
+ * draw triangle pointer for GAS pressure mode display
+ */
+
+    void drawPointer(int c) ;
+    
+private:
+    PSE530  *_pse ;
+    DigitalOut *_en ;
+    float   _value ;
+    float   _thr_high ;
+    float   _thr_low ;
+    int     _thr_mode ;
+    float   _expected ;
+    float   _higher ;
+    float   _lower ;
+} ;
+
+float temp2expected(float temp) ;
+extern float *current_temp ;
+
+#endif /* _EDGE_PRESSURE_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_sensor/edge_sensor.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,200 @@
+#include "mbed.h"
+#include "vt100.h"
+#include "edge_mgr.h"
+#include "edge_reset_mgr.h"
+#include "edge_time.h"
+#include "edge_sensor.h"
+
+extern vt100 *tty ;
+static uint16_t id = 0 ;
+
+edge_sensor::edge_sensor()
+{
+    _interval = 0 ;
+    _prev_status = EDGE_SENSOR_INACTIVE ;
+    _status = EDGE_SENSOR_INACTIVE ;
+    _id = id++ ;
+    _enable = false ;
+    _error_count = 0 ;
+    _sample_error = 0 ;
+}
+
+edge_sensor::~edge_sensor()
+{
+}
+
+void edge_sensor::reset(void)
+{
+    _status = EDGE_SENSOR_INACTIVE ;
+}
+
+void edge_sensor::enable(void) 
+{
+    _enable = true ;
+}
+
+void edge_sensor::disable(void) 
+{
+    _enable = false ;
+}
+
+bool edge_sensor::isEnabled(void)
+{
+    return( _enable ) ;
+}
+
+void edge_sensor::prepare(void)
+{
+//    printf("Sensor %d prepare for sample\n", _id) ;
+}
+
+int edge_sensor::sample(void)
+{
+    int result = EDGE_SAMPLE_SUCCESS ;
+//    printf("Sensor %d sample\n", _id) ;
+    return( result ) ;
+}
+
+int edge_sensor::deliver(void) 
+{
+//  printf("Sensor %d data delivered\n", _id) ;
+    /* usually return( result == afSUCCESS ) ; */
+    return 1 ; /* return non zero for success */
+}
+
+void edge_sensor::show(void)
+{
+    /* display value(s) to TFT */
+}
+
+void edge_sensor::displayTime(int32_t ts)
+{
+    struct tm timestruct ;
+    if (display) {
+reset_watch_dog() ;
+        ts2tm(ts, &timestruct) ;
+reset_watch_dog() ;
+        display->set_font((unsigned char*) Arial12x12);
+        display->set_font_zoom(2, 2) ;
+        display->foreground(White) ;
+//        display->locate(10, 5) ;
+        display->printf("%d/%02d/%02d %02d:%02d:%02d",
+            timestruct.tm_year,
+            timestruct.tm_mon + 1,
+            timestruct.tm_mday,
+            timestruct.tm_hour,
+            timestruct.tm_min,
+            timestruct.tm_sec
+        ) ;
+reset_watch_dog() ;
+    }
+}
+
+void edge_sensor::toJson(char *buf)
+{
+    sprintf(buf, "EDGE_SENSOR%d is not a real sensor", _id) ;
+}
+
+void edge_sensor::setInterval(uint16_t interval) 
+{
+    _interval = interval ;
+}
+
+uint16_t edge_sensor::getInterval(void) 
+{
+    return( _interval ) ;
+}
+
+int edge_sensor::getStatus(void)
+{
+    return( _status ) ;
+}
+
+/*
+#define EDGE_SENSOR_INACTIVE    0
+#define EDGE_SENSOR_WAIT        1
+#define EDGE_SENSOR_READY       2
+#define EDGE_SENSOR_PREPARED    3
+#define EDGE_SENSOR_SAMPLED     4
+#define EDGE_SENSOR_DELIVERD    5
+*/
+
+int edge_sensor::runStateMachine(void)
+{
+    int result ;
+    reset_watch_dog() ;
+    switch(_status) {
+    case EDGE_SENSOR_INACTIVE: /* inactive */
+        if (isEnabled()) {
+            _status = EDGE_SENSOR_WAIT ;
+        }
+        _prev_status = EDGE_SENSOR_INACTIVE ;
+        break ;
+    case EDGE_SENSOR_WAIT: /* wait for interval time expires */
+        if (_prev_status == EDGE_SENSOR_INACTIVE) { // initial end_interval
+            _end_interval = edge_time + _interval ;
+        }
+        _prev_status = EDGE_SENSOR_WAIT ;
+        if (edge_time >= _end_interval) {
+            _status = EDGE_SENSOR_READY ;
+            _end_interval += _interval ;
+        }
+        break ;
+    case EDGE_SENSOR_READY: /* prepare to sample */
+        result = sample() ;
+        if (result == EDGE_SAMPLE_SUCCESS) {
+            _status = EDGE_SENSOR_SAMPLED ;
+            _sample_error = 0 ;
+        } else {
+            reset_watch_dog() ;
+            printf("Sampling error: ") ;
+            switch(_id) {
+            case SENSOR_ID_ACCEL:  printf("Accel (MMA8451Q) ") ;  break ;
+            case SENSOR_ID_COLOR1: printf("Color1 (VEML6040) ") ; break ;
+            case SENSOR_ID_COLOR2: printf("Color2 (VEML6040) ") ; break ;
+            case SENSOR_ID_TEMP: printf("Temp (LM75B) ") ;      break ;
+            case SENSOR_ID_PRESS: printf("Pressure (PSE530) ") ; break ;
+            default: printf("Sensor[%d] ", _id) ;  break ;
+            }
+            switch(result) {
+            case -2: printf("Bus Busy") ;         break ;
+            case -1: printf("No Slave") ;         break ;
+            case 0: printf("No Error") ;          break ;
+            case 1: printf("Nack Received") ;     break ;
+            case 2: printf("Time Out") ;          break ;
+            default: printf("error[%d]",result) ; break ;
+            }
+            _sample_error++ ;
+            printf("\n") ;
+        }
+        if (_sample_error > SAMPLE_ERROR_TOLERANCE) {
+            printf("Sampling error of sensor[%d]\n", _id) ;
+            wait(0.1) ;
+            reset_watch_dog() ;
+            reboot_edge() ;
+        }
+        _prev_status = EDGE_SENSOR_READY ;
+        break ;
+    case EDGE_SENSOR_SAMPLED: /* data is ready, wait for delivery */
+        if (_prev_status != EDGE_SENSOR_SAMPLED) {
+            _error_count = 0 ;
+        }
+        result = deliver() ;
+        if (result) {
+            _status = EDGE_SENSOR_DELIVERED ; // EDGE_SENSOR_INACTIVE ;
+        } else {
+            _error_count++ ;
+        }
+
+        _prev_status = EDGE_SENSOR_SAMPLED ;
+        break ;
+    case EDGE_SENSOR_DELIVERED:
+        show() ;
+        _status = EDGE_SENSOR_WAIT ;
+        _prev_status = EDGE_SENSOR_DELIVERED ;
+        break ;
+    }
+    reset_watch_dog() ;
+    return(_status) ;
+}
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_sensor/edge_sensor.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,162 @@
+#ifndef _EDGE_SENSOR_H_
+#define _EDGE_SENSOR_H_
+/**
+ * edge_sensor super class of each sensor manager class
+ */
+#include "edge_time.h"
+#include "afLib.h"
+#include "af_mgr.h"
+#include <ILI9341.h>
+#include "edge_chart.h"
+
+class edge_sensor {
+public:
+/**
+ * constructor 
+ */
+    edge_sensor() ;
+
+/**
+ * destructor
+ */
+    ~edge_sensor() ;
+
+/**
+ * reset reset property valuse of edge_sensor
+ */
+    virtual void    reset(void) ;
+
+/**
+ * assign _id manually
+ */
+    virtual void    setId(uint16_t id) { _id = id ; }
+    
+    virtual uint16_t getId(void) { return _id ; } 
+    
+/**
+ * enable the edge_sensor 
+ */
+    virtual void    enable(void) ;
+    
+/**
+ * disable the edge_sensor
+ */
+    virtual void    disable(void) ;
+    
+/**
+ * test if the edge_sensor is enabled (or not)
+ * @returns true: the sensor is enabled false: the sensor is disabled
+ */
+    virtual bool    isEnabled(void) ;
+
+/**
+ * prepare the sensor for sampling
+ */
+    virtual void    prepare(void) ;
+    
+/**
+ * sample trigger sampling action of the sensor and acquire the data
+ * @returns 0:success non-0:failure
+ */
+    virtual int    sample(void) ;
+
+    
+/**
+ * deliver the sampled data to the afero cloud via setAttributes
+ */
+    virtual int     deliver(void) ;
+    
+/**
+ * show the value(s) to the display (TFT)
+ */
+    virtual void    show(void) ;
+    
+/**
+ * toJson convert sampled data to json format
+ * @param buf char* string buf to store the json string
+ */
+    virtual void    toJson(char *buf) ;
+    
+/**
+ * display timestamp in human readable format
+ * @parm ts int32_t timestamp value to display
+ */
+    virtual void    displayTime(int32_t ts) ;
+
+/**
+ * setInterval assign sampling interval time (in sec)
+ * @param interval uint16_t the value to assign
+ */
+    void            setInterval(uint16_t interval) ;
+    
+/**
+ * getInterval get sampling interval time (in sec)
+ * @returns the interval time in uint16_t
+ */
+    uint16_t        getInterval(void) ;
+    
+/**
+ * getStatus get current status of the state machine
+ * @returns current status as int
+ */
+    int             getStatus(void) ;
+    
+/**
+ * advanceStatus proceed status into the next state
+ * @returns advanced status
+ */
+    int             advanceStatus(void) ;
+
+/**
+ * runStateMachine run the statemachine for single cycle
+ * @returns the result status
+ */
+    virtual int     runStateMachine(void) ;
+protected:
+    uint16_t        _id ;
+    bool            _enable ;
+    uint32_t        _interval ;
+    int             _status ;
+    int             _error_count ;
+    int             _sample_error ;
+    int             _prev_status ;
+    uint32_t        _end_interval ;
+    uint32_t        _sampled_time ;
+    char            _str_buf[256] ;
+} ;
+
+/* may be, we had better use enum here */
+#define EDGE_SENSOR_INACTIVE    0
+#define EDGE_SENSOR_WAIT        1
+#define EDGE_SENSOR_READY       2
+#define EDGE_SENSOR_PREPARED    3
+#define EDGE_SENSOR_SAMPLED     4
+#define EDGE_SENSOR_DELIVERED   5
+#define EDGE_SENSOR_DISPLAYED   6
+
+/* _id numbers for sensors */
+#define SENSOR_ID_ACCEL          0
+#define SENSOR_ID_COLOR1         1
+#define SENSOR_ID_COLOR2         2
+#define SENSOR_ID_TEMP           3
+#define SENSOR_ID_PRESS          4
+
+/* Y position of SUMMARY MODE */
+#define EDGE_SUMMARY_X          10
+#define EDGE_SUMMARY_TIME_Y     10
+#define EDGE_SUMMARY_ACCEL_Y    45
+#define EDGE_SUMMARY_PRESS_Y    80
+#define EDGE_SUMMARY_COLOR1_Y   115
+#define EDGE_SUMMARY_COLOR2_Y   150
+#define EDGE_SUMMARY_TEMP_Y     185
+
+#define EDGE_SAMPLE_SUCCESS     0
+#define SAMPLE_ERROR_TOLERANCE  3
+
+extern ILI9341             *display     ;
+extern int                 display_mode ;
+extern const unsigned char Arial12x12[] ;
+extern const unsigned char Arial24x23[] ;
+extern const unsigned char Arial28x28[] ;
+
+#endif /* _EDGE_SENSOR_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_sensor/edge_temp.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,143 @@
+#include "mbed.h"
+#include "LM75B.h"
+#include "edge_reset_mgr.h"
+#include "edge_sensor.h"
+#include "edge_temp.h"
+#include "edge_chart.h"
+
+float *current_temp = 0 ;
+
+edge_temp::edge_temp(LM75B *temp1, SMTC502AT *temp2, SMTC502AT *temp3, LM75B *temp4) 
+{
+    _temp1 = temp1 ;
+    _temp2 = temp2 ;
+    _temp3 = temp3 ;
+    _temp4 = temp4 ;
+    _ftemp[0] = _ftemp[1] = _ftemp[2] = _ftemp[3] = 0.0 ;
+    _interval = 30 ;
+    current_temp = &_ftemp[1] ; /* use before for current temp */
+}
+
+edge_temp::~edge_temp(void)
+{
+    if (_temp1) {
+        delete _temp1 ;
+    }
+    if (_temp2) {
+        delete _temp2 ;
+    }
+    if (_temp3) {
+        delete _temp3 ;
+    }
+    if (_temp4) {
+        delete _temp4 ;
+    }
+}
+
+void    edge_temp::reset(void) 
+{
+}
+
+void    edge_temp::prepare(void) 
+{
+}
+
+int    edge_temp::sample(void) 
+{
+    int result ;
+    if (_temp1) {
+        result = _temp1->getTemp(&_ftemp[0]) ;
+    }
+    if (_temp2) {
+        _ftemp[1] = _temp2->getTemp() ;
+    }
+    if (_temp3) {
+        _ftemp[2] = _temp3->getTemp() ;
+    }
+    if (_temp4) {
+        _temp4->getTemp(&_ftemp[3]) ;
+    }
+    _sampled_time = edge_time ;
+    return( result ) ;
+}
+
+int    edge_temp::deliver(void) 
+{
+    int result ;
+    char timestr[16] ;
+    
+    print_time() ;
+    printf(" temp: ") ;
+    if (_temp1) {
+        printf("LM75B1 = %.2f ", _ftemp[0]) ;
+    } 
+    if (_temp2) {
+        printf("before = %.2f ", _ftemp[1]) ;
+    }
+    if (_temp3) {
+        printf("after = %.2f ", _ftemp[2]) ;
+    }
+    if (_temp4) {
+        printf("LM75B2 = %.2f ", _ftemp[3]) ;
+    }
+    printf("\n") ;
+    time2seq(_sampled_time, timestr) ;
+    sprintf(_str_buf,
+    "{\"DEVICE\":\"TEMP04\",\"VAL_1\":\"%.1f\",\"VAL_2\":\"%.1f\",\"VAL_3\":\"%.1f\",\"T\":\"%s\",\"E\":\"%d\"}",
+        _ftemp[0], _ftemp[1], _ftemp[2], timestr, _error_count) ;
+    result = afero->setAttribute(1, _str_buf) ;
+    return( result == afSUCCESS ) ;
+}
+
+int temp_v2y(float value, edge_chart_type *p)
+{
+    int y ;
+    if (value < p->min) {
+        value = p->min ;
+    } else if (value > p->max) {
+        value = p->max ;
+    }
+    y = p->top + p->height - 1
+        - (int)((p->height - 2) * (value - p->min) /(p->max - p->min)) ;
+    return( y ) ;
+}
+
+void edge_temp::show(void)
+{
+    edge_chart_type *p = &edge_chart[ _id ] ;
+    int x, temp, before, after ;
+    reset_watch_dog() ;
+    if (display) {
+        switch(display_mode) {
+        case DISPLAY_MODE_SUMMARY:
+            display->BusEnable(true) ;
+            display->set_font((unsigned char*) Arial12x12);
+            display->set_font_zoom(2, 2) ;
+            display->foreground(White) ;
+            display->locate(EDGE_SUMMARY_X, EDGE_SUMMARY_TIME_Y) ;
+            displayTime(_sampled_time) ;
+            display->locate(EDGE_SUMMARY_X, EDGE_SUMMARY_TEMP_Y) ;
+            display->printf("Temp : %.2f %.2f %.2f",_ftemp[0], _ftemp[1], _ftemp[2]) ;
+            display->BusEnable(false) ;
+            reset_watch_dog() ;
+            break ;
+        case DISPLAY_MODE_CHART:
+            x = p->left + p->index + 1;
+            temp =  temp_v2y(_ftemp[0], p) ;
+            before = temp_v2y(_ftemp[1], p) ;
+            after = temp_v2y(_ftemp[2], p) ;
+            display->BusEnable(true) ;
+            if (p->index == 0) {
+                draw_chart_frame(p) ;
+            }
+            display->pixel(x, temp, White) ;
+            display->pixel(x, before, Red) ;
+            display->pixel(x, after, Blue) ;
+            display->BusEnable(false) ;
+            p->index = (p->index + 1) % (p->width - 2) ;
+            break ;  
+        }
+    }
+    reset_watch_dog() ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_sensor/edge_temp.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,63 @@
+#ifndef _EDGE_TEMP_H_
+#define _EDGE_TEMP_H_
+#include "mbed.h"
+#include "edge_sensor.h"
+#include "LM75B.h"
+#include "SMTC502AT.h"
+
+/**
+ * edge_temp edge_sensor to measre temperature sensors
+ */
+
+class edge_temp : public edge_sensor {
+public:
+/**
+ * constructor
+ * @param *temp1 LM75B temperature sensor object (with Color1)
+ * @param *temp2 SMTC502AT temperature sensor object (befor)
+ * @param *temp3 SMTC502AT temperature sensor object (after)
+ * @param *temp4 LM75B temperature sensor object (with Color2)
+ */
+    edge_temp(LM75B *temp1, SMTC502AT *temp2, SMTC502AT *temp3, LM75B *temp4) ;
+    
+/**
+ * destructor
+ */
+    ~edge_temp(void) ;
+    
+/**
+ * reset and clear the internal values
+ */
+    virtual void    reset(void) ;
+
+/**
+ * prepare for sampling 
+ */
+    virtual void    prepare(void) ;
+    
+/**
+ * sample measure and store sensor values
+ * @return 0: success non-0: failure
+ */
+    virtual int    sample(void) ;
+    
+/**
+ * deliver the values to the afero cloud
+ */
+    virtual int     deliver(void) ;
+    
+/**
+ * Show the value(s) in the display (TFT)
+ */
+    virtual void    show(void) ;
+
+private:
+    LM75B       *_temp1 ;
+    SMTC502AT   *_temp2 ;
+    SMTC502AT   *_temp3 ;
+    LM75B       *_temp4 ;
+    float       _ftemp[4] ;
+} ;
+
+extern float *current_temp ;
+#endif /* _EDGE_TEMP_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/KL25Z_SystemInit.c	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,235 @@
+#if defined (TARGET_KL25Z)
+/*
+** ###################################################################
+**     Processor:           MKL25Z128VLK4
+**     Compilers:           ARM Compiler
+**                          Freescale C/C++ for Embedded ARM
+**                          GNU C Compiler
+**                          IAR ANSI C/C++ Compiler for ARM
+**
+**     Reference manual:    KL25RM, Rev.1, Jun 2012
+**     Version:             rev. 1.1, 2012-06-21
+**
+**     Abstract:
+**         Provides a system configuration function and a global variable that
+**         contains the system frequency. It configures the device and initializes
+**         the oscillator (PLL) that is part of the microcontroller device.
+**
+**     Copyright: 2012 Freescale Semiconductor, Inc. All Rights Reserved.
+**
+**     http:                 www.freescale.com
+**     mail:                 support@freescale.com
+**
+**     Revisions:
+**     - rev. 1.0 (2012-06-13)
+**         Initial version.
+**     - rev. 1.1 (2012-06-21)
+**         Update according to reference manual rev. 1.
+**
+** ###################################################################
+*/
+
+/**
+ * @file MKL25Z4
+ * @version 1.1
+ * @date 2012-06-21
+ * @brief Device specific configuration file for MKL25Z4 (implementation file)
+ *
+ * Provides a system configuration function and a global variable that contains
+ * the system frequency. It configures the device and initializes the oscillator
+ * (PLL) that is part of the microcontroller device.
+ */
+
+#include <stdint.h>
+#include "MKL25Z4.h"
+
+//MODIFICATION: We DO want watchdog, uC default after reset is enabled with timeout=1024ms (2^10*LPO=1KHz)
+//#define DISABLE_WDOG    1
+
+#define CLOCK_SETUP     1
+/* Predefined clock setups
+   0 ... Multipurpose Clock Generator (MCG) in FLL Engaged Internal (FEI) mode
+         Reference clock source for MCG module is the slow internal clock source 32.768kHz
+         Core clock = 41.94MHz, BusClock = 13.98MHz
+   1 ... Multipurpose Clock Generator (MCG) in PLL Engaged External (PEE) mode
+         Reference clock source for MCG module is an external crystal 8MHz
+         Core clock = 48MHz, BusClock = 24MHz
+   2 ... Multipurpose Clock Generator (MCG) in Bypassed Low Power External (BLPE) mode
+         Core clock/Bus clock derived directly from an external crystal 8MHz with no multiplication
+         Core clock = 8MHz, BusClock = 8MHz
+   3 ... Multipurpose Clock Generator (MCG) in FLL Engaged External (FEE) mode
+         Reference clock source for MCG module is an external crystal 32.768kHz
+         Core clock = 47.97MHz, BusClock = 23.98MHz
+         This setup sets the RTC to be driven by the MCU clock directly without the need of an external source.
+         RTC register values are retained when MCU is reset although there will be a slight (mSec's)loss of time
+         accuracy durring the reset period. RTC will reset on power down. 
+*/
+
+/*----------------------------------------------------------------------------
+  Define clock source values
+ *----------------------------------------------------------------------------*/
+#if (CLOCK_SETUP == 0)
+    #define CPU_XTAL_CLK_HZ                 8000000u /* Value of the external crystal or oscillator clock frequency in Hz */
+    #define CPU_INT_SLOW_CLK_HZ             32768u   /* Value of the slow internal oscillator clock frequency in Hz  */
+    #define CPU_INT_FAST_CLK_HZ             4000000u /* Value of the fast internal oscillator clock frequency in Hz  */
+    #define DEFAULT_SYSTEM_CLOCK            41943040u /* Default System clock value */
+#elif (CLOCK_SETUP == 1)
+    #define CPU_XTAL_CLK_HZ                 8000000u /* Value of the external crystal or oscillator clock frequency in Hz */
+    #define CPU_INT_SLOW_CLK_HZ             32768u   /* Value of the slow internal oscillator clock frequency in Hz  */
+    #define CPU_INT_FAST_CLK_HZ             4000000u /* Value of the fast internal oscillator clock frequency in Hz  */
+    #define DEFAULT_SYSTEM_CLOCK            48000000u /* Default System clock value */
+#elif (CLOCK_SETUP == 2)
+    #define CPU_XTAL_CLK_HZ                 8000000u /* Value of the external crystal or oscillator clock frequency in Hz */
+    #define CPU_INT_SLOW_CLK_HZ             32768u   /* Value of the slow internal oscillator clock frequency in Hz  */
+    #define CPU_INT_FAST_CLK_HZ             4000000u /* Value of the fast internal oscillator clock frequency in Hz  */
+    #define DEFAULT_SYSTEM_CLOCK            8000000u /* Default System clock value */
+#elif (CLOCK_SETUP == 3)    
+    #define CPU_XTAL_CLK_HZ                 32768u   /* Value of the external crystal or oscillator clock frequency in Hz */
+    #define CPU_INT_SLOW_CLK_HZ             32768u   /* Value of the slow internal oscillator clock frequency in Hz  */
+    #define CPU_INT_FAST_CLK_HZ             4000000u /* Value of the fast internal oscillator clock frequency in Hz  */
+    #define DEFAULT_SYSTEM_CLOCK            47972352u /* Default System clock value */       
+#endif /* (CLOCK_SETUP == 3) */
+
+/* ----------------------------------------------------------------------------
+   -- Core clock
+   ---------------------------------------------------------------------------- */
+
+//MODIFICATION: That vartiable already exists
+// uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
+
+/* ----------------------------------------------------------------------------
+   -- SystemInit()
+   ---------------------------------------------------------------------------- */
+
+void $Sub$$SystemInit (void) {
+    
+    //MODIFICATION:
+    // That variable already exists, we set it here
+    SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
+    // We want visual indication of boot time with red LED on
+    //TODO
+
+#if (DISABLE_WDOG)
+  /* Disable the WDOG module */
+  /* SIM_COPC: COPT=0,COPCLKS=0,COPW=0 */
+  SIM->COPC = (uint32_t)0x00u;
+#endif /* (DISABLE_WDOG) */
+#if (CLOCK_SETUP == 0)
+  /* SIM->CLKDIV1: OUTDIV1=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,OUTDIV4=2,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
+  SIM->CLKDIV1 = (uint32_t)0x00020000UL; /* Update system prescalers */
+  /* Switch to FEI Mode */
+  /* MCG->C1: CLKS=0,FRDIV=0,IREFS=1,IRCLKEN=1,IREFSTEN=0 */
+  MCG->C1 = (uint8_t)0x06U;
+  /* MCG_C2: LOCRE0=0,??=0,RANGE0=0,HGO0=0,EREFS0=0,LP=0,IRCS=0 */
+  MCG->C2 = (uint8_t)0x00U;
+  /* MCG->C4: DMX32=0,DRST_DRS=1 */
+  MCG->C4 = (uint8_t)((MCG->C4 & (uint8_t)~(uint8_t)0xC0U) | (uint8_t)0x20U);
+  /* OSC0->CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
+  OSC0->CR = (uint8_t)0x80U;
+  /* MCG->C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=0 */
+  MCG->C5 = (uint8_t)0x00U;
+  /* MCG->C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=0 */
+  MCG->C6 = (uint8_t)0x00U;
+  while((MCG->S & MCG_S_IREFST_MASK) == 0x00U) { /* Check that the source of the FLL reference clock is the internal reference clock. */
+  }
+  while((MCG->S & 0x0CU) != 0x00U) {    /* Wait until output of the FLL is selected */
+  }
+#elif (CLOCK_SETUP == 1)
+  /* SIM->SCGC5: PORTA=1 */
+  SIM->SCGC5 |= (uint32_t)0x0200UL;     /* Enable clock gate for ports to enable pin routing */
+  /* SIM->CLKDIV1: OUTDIV1=1,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,OUTDIV4=1,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
+  SIM->CLKDIV1 = (uint32_t)0x10010000UL; /* Update system prescalers */
+  /* PORTA->PCR18: ISF=0,MUX=0 */
+  PORTA->PCR[18] &= (uint32_t)~0x01000700UL;
+  /* PORTA->PCR19: ISF=0,MUX=0 */
+  PORTA->PCR[19] &= (uint32_t)~0x01000700UL;
+  /* Switch to FBE Mode */
+  /* OSC0->CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=1,SC4P=0,SC8P=0,SC16P=1 */
+  OSC0->CR = (uint8_t)0x89U;
+  /* MCG->C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=0 */
+  MCG->C2 = (uint8_t)0x24U;
+  /* MCG->C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=1,IREFSTEN=0 */
+  MCG->C1 = (uint8_t)0x9AU;
+  /* MCG->C4: DMX32=0,DRST_DRS=0 */
+  MCG->C4 &= (uint8_t)~(uint8_t)0xE0U;
+  /* MCG->C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=1 */
+  MCG->C5 = (uint8_t)0x01U;
+  /* MCG->C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=0 */
+  MCG->C6 = (uint8_t)0x00U;
+  while((MCG->S & MCG_S_IREFST_MASK) != 0x00U) { /* Check that the source of the FLL reference clock is the external reference clock. */
+  }
+  while((MCG->S & 0x0CU) != 0x08U) {    /* Wait until external reference clock is selected as MCG output */
+  }
+  /* Switch to PBE Mode */
+  /* MCG->C6: LOLIE0=0,PLLS=1,CME0=0,VDIV0=0 */
+  MCG->C6 = (uint8_t)0x40U;
+  while((MCG->S & 0x0CU) != 0x08U) {    /* Wait until external reference clock is selected as MCG output */
+  }
+  while((MCG->S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait until locked */
+  }
+  /* Switch to PEE Mode */
+  /* MCG->C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=1,IREFSTEN=0 */
+  MCG->C1 = (uint8_t)0x1AU;
+  while((MCG->S & 0x0CU) != 0x0CU) {    /* Wait until output of the PLL is selected */
+  }
+#elif (CLOCK_SETUP == 2)
+  /* SIM->SCGC5: PORTA=1 */
+  SIM->SCGC5 |= (uint32_t)0x0200UL;     /* Enable clock gate for ports to enable pin routing */
+  /* SIM->CLKDIV1: OUTDIV1=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,OUTDIV4=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
+  SIM->CLKDIV1 = (uint32_t)0x00000000UL; /* Update system prescalers */
+  /* PORTA->PCR18: ISF=0,MUX=0 */
+  PORTA->PCR[18] &= (uint32_t)~0x01000700UL;
+  /* PORTA->PCR19: ISF=0,MUX=0 */
+  PORTA->PCR[19] &= (uint32_t)~0x01000700UL;
+  /* Switch to FBE Mode */
+  /* OSC0->CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=1,SC4P=0,SC8P=0,SC16P=1 */
+  OSC0->CR = (uint8_t)0x89U;
+  /* MCG->C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=0,IRCS=0 */
+  MCG->C2 = (uint8_t)0x24U;
+  /* MCG->C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=1,IREFSTEN=0 */
+  MCG->C1 = (uint8_t)0x9AU;
+  /* MCG->C4: DMX32=0,DRST_DRS=0 */
+  MCG->C4 &= (uint8_t)~(uint8_t)0xE0U;
+  /* MCG->C5: ??=0,PLLCLKEN0=0,PLLSTEN0=0,PRDIV0=0 */
+  MCG->C5 = (uint8_t)0x00U;
+  /* MCG->C6: LOLIE0=0,PLLS=0,CME0=0,VDIV0=0 */
+  MCG->C6 = (uint8_t)0x00U;
+  while((MCG->S & MCG_S_IREFST_MASK) != 0x00U) { /* Check that the source of the FLL reference clock is the external reference clock. */
+  }
+  while((MCG->S & 0x0CU) != 0x08U) {    /* Wait until external reference clock is selected as MCG output */
+  }
+  /* Switch to BLPE Mode */
+  /* MCG->C2: LOCRE0=0,??=0,RANGE0=2,HGO0=0,EREFS0=1,LP=1,IRCS=0 */
+  MCG->C2 = (uint8_t)0x26U;
+  while((MCG->S & 0x0CU) != 0x08U) {    /* Wait until external reference clock is selected as MCG output */
+  }
+#elif (CLOCK_SETUP == 3)  
+/* SIM->SCGC5: PORTA=1 */
+  SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;   /* Enable clock gate for ports to enable pin routing */
+  /* SIM->CLKDIV1: OUTDIV1=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,OUTDIV4=1,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */
+  SIM->CLKDIV1 = (SIM_CLKDIV1_OUTDIV1(0x00) | SIM_CLKDIV1_OUTDIV4(0x01)); /* Update system prescalers */
+  /* PORTA->PCR[3]: ISF=0,MUX=0 */
+  PORTA->PCR[3] &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07)));
+  /* PORTA->PCR[4]: ISF=0,MUX=0 */
+  PORTA->PCR[4] &= (uint32_t)~(uint32_t)((PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x07)));
+  /* Switch to FEE Mode */
+  /* MCG->C2: LOCRE0=0,??=0,RANGE0=0,HGO0=0,EREFS0=1,LP=0,IRCS=0 */
+  MCG->C2 = (MCG_C2_RANGE0(0x00) | MCG_C2_EREFS0_MASK);
+  /* OSC0->CR: ERCLKEN=1,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */
+  OSC0->CR = OSC_CR_ERCLKEN_MASK | OSC_CR_SC16P_MASK | OSC_CR_SC4P_MASK | OSC_CR_SC2P_MASK;
+  /* MCG->C1: CLKS=0,FRDIV=0,IREFS=0,IRCLKEN=1,IREFSTEN=0 */
+  MCG->C1 = (MCG_C1_CLKS(0x00) | MCG_C1_FRDIV(0x00) | MCG_C1_IRCLKEN_MASK);
+  /* MCG->C4: DMX32=1,DRST_DRS=1 */
+  MCG->C4 = (uint8_t)((MCG->C4 & (uint8_t)~(uint8_t)(
+            MCG_C4_DRST_DRS(0x02)
+           )) | (uint8_t)(
+            MCG_C4_DMX32_MASK |
+            MCG_C4_DRST_DRS(0x01)
+           ));
+  while((MCG->S & MCG_S_IREFST_MASK) != 0x00U) { /* Check that the source of the FLL reference clock is the external reference clock. */
+  }
+  while((MCG->S & 0x0CU) != 0x00U) {    /* Wait until output of the FLL is selected */
+  }          
+#endif /* (CLOCK_SETUP == 3) */
+}
+#endif // TARGET_KL25Z
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_chart.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,56 @@
+#include "mbed.h"
+#include "edge_mgr.h"
+#include "edge_reset_mgr.h"
+#include "edge_chart.h"
+#if 0
+typedef struct _edge_chart_st {
+    char *name ;
+    int left ;
+    int top ;
+    int width ;
+    int height ;
+    int index ;
+    int min ;
+    int max ;
+} edge_chart_type ;
+
+extern edge_chart_type edge_chart[] ;
+#endif
+
+edge_chart_type edge_chart[] = {
+/*      name,  left, top, width, height, index,   min,     max */
+    { "Accel",    0,   0,   160,     60,     0,  -0.2,     0.2 },
+    { "Color",  160,   0,   160,    120,     0,   0.0, 10000.0 },
+    { "Color2", 160, 120,   160,    120,     0,   0.0, 10000.0 },
+    { "Temp",     0, 120,   160,    120,     0, -10.0,    50.0 },
+    { "Press",    0,  60,   160,     60,     0,  -1.0,     5.0 },
+    {        0,   0,   0,     0,      0,     0,   0.0,     0.0 }
+} ;
+
+void draw_chart_frame(edge_chart_type *p)
+{
+    if (display) {
+        display->fillrect(p->left+1, p->top+1,
+        p->left + p->width - 2, p->top + p->height - 2, Black) ;
+        display->rect(p->left, p->top, 
+            p->left + p->width - 1,
+            p->top + p->height -1, Blue) ;
+        display->set_font((unsigned char*) Arial12x12);
+        display->foreground(White) ;
+        display->locate(p->left + 5, p->top + 5) ;
+        display->printf(p->name) ;
+    }
+}
+
+void   draw_all_chart_frame(void) 
+{
+    edge_chart_type *p ;
+    if (display) {
+        reset_watch_dog() ;
+        display->BusEnable(true) ;
+        for(p = edge_chart ; p->name ; p++ ) {
+            draw_chart_frame(p) ;
+        }
+        display->BusEnable(false) ;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_chart.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,22 @@
+#ifndef _EDGE_CHART_H_
+#define _EDGE_CHART_H_
+#include "mbed.h"
+
+typedef struct _edge_chart_st {
+    char *name ;
+    int left ;
+    int top ;
+    int width ;
+    int height ;
+    int index ;
+    float min ;
+    float max ;
+} edge_chart_type ;
+
+extern edge_chart_type edge_chart[] ;
+
+void draw_chart_frame(edge_chart_type *p) ;
+void draw_all_chart_frame(void) ;
+
+
+#endif /* _EDGE_CHART_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_mgr.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,598 @@
+#include "mbed.h"
+#include "edge_mgr.h"
+#include "af_attributes.h"
+
+#include "edge_time.h"
+#include "edge_pin.h"
+#include "MMA8451Q.h"
+#include "VEML6040.h"
+#include "LM75B.h"
+#include "SMTC502AT.h"
+#include "PSE530.h"
+#include <ILI9341.h>
+#include "Arial12x12.h"
+#include "Arial24x23.h"
+#include "Arial28x28.h"
+
+#include "edge_sensor.h"
+#include "edge_accel.h"
+#include "edge_color.h"
+#include "edge_temp.h"
+#include "edge_pressure.h"
+#include "edge_reset_mgr.h"
+#include "edge_chart.h"
+
+#define MMA8451Q_I2C_ADDRESS 0x1C
+#define VEML6040_I2C_ADDRESS 0x10
+#define LM75B_I2C_ADDRESS    0x48
+#define SO1602A_I2C_ADDRESS  0x3C
+
+#define NUM_MAX_SENSOR 5
+
+uint16_t attr_to_set[] = {
+ATTR_ACCEL_PRESENT,
+ATTR_COLOR0_PRESENT,
+ATTR_COLOR1_PRESENT,
+ATTR_TEMP0_PRESENT,
+ATTR_GAS_PRESENT,
+} ;
+
+uint16_t attr_to_get[] = {
+// accel
+ATTR_ACCEL_ENABLE,
+ATTR_ACCEL_INTERVAL,
+// Color0
+ATTR_COLOR0_ENABLE,
+ATTR_COLOR0_INTERVAL,
+ATTR_COLOR0_ITIME,
+ATTR_COLOR0_PWM_PERIOD,
+ATTR_COLOR0_PWM_TARGET,
+ATTR_COLOR0_PWM_R,
+ATTR_COLOR0_PWM_G,
+ATTR_COLOR0_PWM_B,
+// Color1
+ATTR_COLOR1_ENABLE,
+ATTR_COLOR1_INTERVAL,
+ATTR_COLOR1_ITIME,
+ATTR_COLOR1_PWM_PERIOD,
+ATTR_COLOR1_PWM_TARGET,
+ATTR_COLOR1_PWM_R,
+ATTR_COLOR1_PWM_G,
+ATTR_COLOR1_PWM_B,
+// Temp
+ATTR_TEMP0_INTERVAL,
+ATTR_TEMP0_ENABLE,
+// Gas Pressure
+ATTR_GAS_ENABLE,
+ATTR_GAS_INTERVAL,
+ATTR_GAS_THR_MODE,
+ATTR_GAS_THR_HIGH,
+ATTR_GAS_THR_LOW,
+0 } ;
+
+bool            verbos = true ;
+edge_sensor     *sensor[NUM_MAX_SENSOR] ;
+int             num_sensor   = 0 ;
+
+edge_accel      *accel       = 0 ;
+edge_color      *color[2]    = {0, 0} ;
+edge_temp       *temp        = 0 ;
+edge_pressure   *pressure    = 0 ;
+
+PwmOut          *led[3]      = {0, 0, 0} ;
+uint16_t        pwm[3]       = { 0x5FA2, 0xB09B, 0x83DF } ;
+I2C             *edge_i2c0   = 0 ;
+I2C             *edge_i2c1   = 0 ;
+ILI9341         *display     = 0 ;
+MMA8451Q        *mma8451q    = 0 ;
+VEML6040        *veml6040[2] = { 0, 0 } ;
+LM75B           *lm75b0      = 0 ; /* for temp1 */
+AnalogIn        *an0         = 0 ; /* for temp2 */
+SMTC502AT       *smtc502at0  = 0 ;
+AnalogIn        *an1         = 0 ; /* for temp3 */
+SMTC502AT       *smtc502at1  = 0 ;
+LM75B           *lm75b1      = 0 ; /* for temp4 */
+AnalogIn        *an2         = 0 ; /* for gas pressure */
+PSE530          *pse530      = 0 ; /* gas pressure sensor */
+
+DigitalOut      *tft_reset   = 0 ;
+DigitalOut      *tft_backlight = 0 ;
+DigitalOut      *tft_cs       = 0 ;
+DigitalOut      *pse530_en    = 0 ;
+DigitalOut      *color_en     = 0 ;
+
+static int error_tolerance   = 100 ;
+static int loop_interval     = 100 ; // 1000 ; 
+static int accel_interval    = 10 ;
+int        edge_mgr_status   = EDGE_MGR_INIT ;
+char       *reset_reason_str = 0 ;
+int        display_mode      = 1 ;
+bool       reboot_requested  = false ;
+
+/* following two functions are for test power on/off of color sensor */
+void   enable_color_sensor(void) 
+{
+    if (color_en == 0) {
+        printf("Color Enable Pin is not initiated\n") ;
+    } else {
+        *color_en = 0 ;
+    }
+}   
+    
+void   disable_color_sensor(void) 
+{
+    if (color_en == 0) {
+        printf("Color Enable Pin is not initiated\n") ;
+    } else {
+        *color_en = 1 ;
+    }    
+}
+
+void init_display(void)
+{
+reset_watch_dog() ;
+    printf("TFT Initializing\n") ;
+    tft_reset = new DigitalOut(PIN_RESET_TFT, 1) ;
+    tft_backlight = new DigitalOut(PIN_BL_TFT, 0) ;
+    tft_cs = new DigitalOut(PIN_CS_TFT, 1) ;
+
+reset_watch_dog() ;
+    display = new ILI9341(SPI_8, 10000000,
+                PIN_MOSI, PIN_MISO, PIN_SCK,
+                PIN_CS_TFT, PIN_RESET_TFT, PIN_DC_TFT, "LaSuno") ;
+
+reset_watch_dog() ;
+    display->BusEnable(true) ;
+    display->set_orientation(1) ;
+    
+reset_watch_dog() ;
+    display->cls() ;
+    *tft_backlight = 1 ;
+    display->BusEnable(false) ;
+    printf("TFT Initialized\n") ;
+}
+
+void   edge_splash(void) 
+{
+    printf("Sensor loop started!\n") ;
+    if (display) {
+        reset_watch_dog() ;
+        display->BusEnable(true) ;
+        display->cls() ;
+        display->foreground(Green) ;
+        display->locate(40, 20) ;
+        display->printf("Sensor Loop") ;
+        display->locate(40, 60) ;
+        display->printf("  Started!") ;
+        display->BusEnable(false) ;
+        reset_watch_dog() ;
+    }
+}
+
+int init_edge_attribute(void)
+{
+    static int sensor_index = 0 ;
+    static int attr_index = 0 ;
+    static int error_count = 0 ;
+    int return_value = 1 ;
+    int result ;
+    
+    reset_watch_dog() ;
+    
+    if (reset_reason_str) { 
+        result = afero->setAttribute(ATTR_MCU_RESET_REASON, reset_reason_str) ;
+        if (result == afSUCCESS) {
+            error_count = 0 ;
+            reset_reason_str = 0 ;
+        } else {
+            error_count++ ;
+        }
+        reset_watch_dog() ;
+    }
+    if (sensor_index < NUM_MAX_SENSOR) {// for each sensor send presence
+// printf("Setting sensor[%d] presence\n", sensor_index) ;
+        if (sensor_index == 3) { /* for temp lm75b0 is used */
+            result = afero->setAttributeBool(attr_to_set[sensor_index], lm75b0) ;
+        } else {
+            result = afero->setAttributeBool(attr_to_set[sensor_index], sensor[sensor_index]) ;
+        }
+        if (result == afSUCCESS) {
+            error_count = 0 ;
+            sensor_index++ ;
+        } else {
+            error_count++ ;
+        }
+        reset_watch_dog() ;
+    } else { // all sensor presence sent, now get attributes
+        if (attr_to_get[attr_index] != 0) {
+// printf("getting attribute [%d]\n", attr_index) ;
+            result = afero->getAttribute(attr_to_get[attr_index]) ;
+            if (result == afSUCCESS) {
+                error_count = 0 ;
+                attr_index++ ;
+            } else {
+                error_count++ ;
+            }
+        }
+        reset_watch_dog() ;
+    }
+    
+    if (error_count > error_tolerance) { // too many fails, trying reset
+        reset_watch_dog() ;
+        reboot_edge() ;
+    }
+ 
+    if ((sensor_index >= NUM_MAX_SENSOR)&&(attr_to_get[attr_index] == 0)) { /* all sensors attributes done */
+        sensor_index = 0 ;
+        attr_index = 0 ;
+        return_value = 0 ;
+    }
+    return(return_value) ;
+}
+
+void edge_loop(uint32_t count_robin)
+{
+    static int sensor_index = 0 ;
+    int result ;
+    
+    reset_watch_dog() ;
+    
+    if ((count_robin % accel_interval) == 0) {
+        if (accel) {
+            accel->accum() ; /* get and accum accel data */
+        }
+        reset_watch_dog() ;
+    }
+
+    if ((count_robin % loop_interval) == 0) {
+        reset_watch_dog() ;
+        loop_interval = 10 ;
+        if ((sensor[sensor_index])&&(sensor[sensor_index]->isEnabled())) {
+            switch(sensor_index) {
+            case SENSOR_ID_COLOR1: /* color0 */
+                if (((edge_color*)sensor[sensor_index])->calibration_requested()) {
+                    ((edge_color*)sensor[sensor_index])->calibrate(color0_target, color0_pwm, 10) ;
+                    reset_watch_dog() ;
+                    while((result = afero->setAttribute32(ATTR_COLOR0_PWM_R, color0_pwm[0])) != afSUCCESS) { 
+                        reset_watch_dog() ;
+                        print_af_error(result) ;
+                        wait_ms(10) ;
+                    }
+                    while((result = afero->setAttribute32(ATTR_COLOR0_PWM_G, color0_pwm[1])) != afSUCCESS) {
+                        reset_watch_dog() ;
+                        print_af_error(result) ;
+                        wait_ms(10) ;
+                    } 
+                    while((result = afero->setAttribute32(ATTR_COLOR0_PWM_B, color0_pwm[2])) != afSUCCESS) {
+                        reset_watch_dog() ;
+                        print_af_error(result) ;
+                        wait_ms(10) ;
+                    }
+                    while((afero->setAttributeBool(ATTR_COLOR0_CALIBRATE, false)) != afSUCCESS) {
+                        reset_watch_dog() ;     
+                        print_af_error(result) ;
+                        wait_ms(10) ;
+                    }
+                } else { 
+                    sensor[sensor_index]->runStateMachine() ;
+                }
+                break ;
+            case SENSOR_ID_COLOR2: /* color1 */
+                if (((edge_color*)sensor[sensor_index])->calibration_requested()) {
+                    ((edge_color*)sensor[sensor_index])->calibrate(color1_target, color1_pwm, 10) ;
+                    reset_watch_dog() ;
+                    if ((result = afero->setAttribute32(ATTR_COLOR1_PWM_R, color1_pwm[0])) != afSUCCESS) {
+                        reset_watch_dog() ;
+                        print_af_error(result) ;
+                        wait_ms(10) ;
+                    }
+                    if ((result = afero->setAttribute32(ATTR_COLOR1_PWM_G, color1_pwm[1])) != afSUCCESS) {
+                        reset_watch_dog() ;
+                        print_af_error(result) ;
+                        wait_ms(10) ;
+                    }
+                    reset_watch_dog() ;
+                    if ((result = afero->setAttribute32(ATTR_COLOR1_PWM_B, color1_pwm[2])) != afSUCCESS) {
+                        reset_watch_dog() ;       
+                        print_af_error(result) ;
+                        wait_ms(10) ;
+                    }
+                    while((afero->setAttributeBool(ATTR_COLOR1_CALIBRATE, false)) != afSUCCESS) {
+                        reset_watch_dog() ;     
+                        print_af_error(result) ;
+                        wait_ms(10) ;
+                    }
+                } else { 
+                    sensor[sensor_index]->runStateMachine() ;
+                }
+                break ;
+            default:
+                sensor[sensor_index]->runStateMachine() ;
+                break ;
+            }
+        }
+        sensor_index = (sensor_index + 1) % NUM_MAX_SENSOR ;
+    }
+    reset_watch_dog() ;
+}
+
+int is_present(I2C *i2c, int address)
+{
+    char t[1] = { 0 } ;
+    char data[2] = { 0, 0 } ;
+    int result ;
+    address <<= 1 ;
+    result = i2c->write(address, t, 1, true) ;
+    if (result == 0) {
+        result = i2c->read(address, data, 2) ;
+    }
+    return((result == 0)) ;    
+}
+
+/**
+ * check_i2c_pins
+ * To avoid I2C dead-lock condition,
+ * check status of SDA and SCL.
+ * As they are supposed to be HIGH
+ * in case one of them is/are LOW,
+ * change SCL pin to a digital out pin and
+ * generate forced clock for a several cycles.
+ * and when SDA come back to High returns
+ * or I2C_UNLOCK_TRIAL_CYCLE exceeds, give up.
+ */ 
+#define I2C_UNLOCK_TRIAL_CYCLE 50
+
+void check_i2c_pins(PinName sda_pin, PinName scl_pin, int number)
+{
+    DigitalIn *sda_in = 0 ; 
+    DigitalIn *scl_in = 0 ;
+    DigitalOut *scl_out = 0 ;
+    int count = 0 ;
+    sda_in = new DigitalIn(sda_pin, PullUp) ;
+    scl_in = new DigitalIn(scl_pin, PullUp) ;
+    printf("I2C%d pin ", number) ;
+    if ((*sda_in == 0) || (*scl_in == 0)) { /* bus hang! */
+        printf("hang detected, trying to clear ... ") ;
+        delete scl_in ;
+        scl_in = 0 ;
+        scl_out = new DigitalOut(scl_pin) ;
+        while((*sda_in == 0)&&(count++ > I2C_UNLOCK_TRIAL_CYCLE)) {
+            *scl_out = 0 ;
+            wait(0.01) ;
+            *scl_out = 1 ;
+            wait(0.01) ;
+        }
+        if (*sda_in != 0) {
+            printf("Cleared!\n") ;
+        } else {
+            printf("Failed to Clear, proceeding\n") ;
+        }
+    } else {
+        printf("condition OK\n") ;
+    }
+    if (sda_in) { delete sda_in ; }
+    if (scl_in) { delete scl_in ; }
+    if (scl_out) { delete scl_out ; }
+}
+
+void init_sensors(void)
+{
+    printf("=== Initializing Sensor(s) ===\n") ;    
+#if 0
+    color_en = new DigitalOut(PIN_COLOR_EN, 0) ;
+    *color_en = 0 ; /* enable */
+    *color_en = 1 ; /* disable */
+    wait_ms(100) ;
+    *color_en = 0 ; /* enable */
+    wait_ms(10) ;
+#endif
+    
+    check_i2c_pins(PIN_I2C0_SDA, PIN_I2C0_SCL, 0) ;
+    edge_i2c0 = new I2C(PIN_I2C0_SDA, PIN_I2C0_SCL) ;
+    
+    check_i2c_pins(PIN_I2C1_SDA, PIN_I2C1_SCL, 1) ;
+    edge_i2c1 = new I2C(PIN_I2C1_SDA, PIN_I2C1_SCL) ;
+                
+    if (display) {
+reset_watch_dog() ;
+printf("printing inital string to TFT\n") ;
+        display->BusEnable(true) ;
+
+
+    display->background(Black) ;
+    display->foreground(White) ;
+reset_watch_dog() ;
+    display->cls() ;
+reset_watch_dog() ;
+        display->set_font((unsigned char*) Arial24x23);
+        display->foreground(Green) ;
+        display->locate(70, 5) ;
+        display->printf("Suntory") ;
+        display->locate(30, 30) ;
+        display->printf("Server Monitor") ;
+        display->set_font((unsigned char*) Arial28x28);
+        display->foreground(White) ;
+        display->locate(30, 60) ;
+        display->printf("La Suno") ;
+        display->locate(30, 100) ;
+        display->foreground(Red) ;
+        display->printf("Preparing...") ;
+    display->BusEnable(true) ;
+    printf("Done\n") ;
+    wait(0.1) ;
+reset_watch_dog() ;
+    display->cls() ;
+    display->foreground(Yellow) ;
+    display->locate(40, 5) ;
+    display->printf("Probing sensors...") ;
+    display->foreground(Green) ;
+    display->BusEnable(false) ;
+    }
+reset_watch_dog() ;
+    if (is_present(edge_i2c1, MMA8451Q_I2C_ADDRESS)) {
+        printf("MMA8451Q on I2C1 is present\n") ;
+        if (display) {
+            display->BusEnable(true) ;
+            display->locate(30, num_sensor * 30 + 40) ;
+            display->printf("ACCEL is present") ;
+            display->BusEnable(false) ;
+        }
+        mma8451q = new MMA8451Q(edge_i2c1, MMA8451Q_I2C_ADDRESS) ;
+        accel    = new edge_accel(mma8451q) ;
+        sensor[SENSOR_ID_ACCEL] = accel ;
+        sensor[SENSOR_ID_ACCEL]->setId(SENSOR_ID_ACCEL) ;
+        num_sensor++ ;
+    } else {
+        sensor[SENSOR_ID_ACCEL] = 0 ;
+        printf("MMA8451Q is absent\n") ;
+    }
+reset_watch_dog() ;   
+    if (is_present(edge_i2c1, VEML6040_I2C_ADDRESS)) {
+        printf("VEML6040 on I2C1 is present\n") ;  
+        if (display) {
+            display->BusEnable(true) ;
+            display->locate(30, num_sensor * 30 + 40) ;
+            display->printf("COLOR1 is present") ;
+            display->BusEnable(false) ;
+        }  
+        veml6040[0] = new VEML6040(edge_i2c1, VEML6040_I2C_ADDRESS) ;
+        led[0] = new PwmOut(PIN_LED_R) ; 
+        led[1] = new PwmOut(PIN_LED_G) ; 
+        led[2] = new PwmOut(PIN_LED_B) ; 
+        color[0] = new edge_color(veml6040[0], led, pwm) ;
+        sensor[SENSOR_ID_COLOR1] = color[0] ;
+        sensor[SENSOR_ID_COLOR1]->setId(SENSOR_ID_COLOR1) ;
+        num_sensor++ ;
+    } else {
+        sensor[SENSOR_ID_COLOR1] = 0 ;
+        printf("VEML6040 on I2C1 is absent\n") ;
+    }
+reset_watch_dog() ;    
+    if (is_present(edge_i2c0, VEML6040_I2C_ADDRESS)) {
+        printf("VEML6040 on I2C0 is present\n") ;  
+        if (display) {
+            display->BusEnable(true) ;
+            display->locate(30, num_sensor * 30 + 40) ;
+            display->printf("COLOR2 is present") ;
+            display->BusEnable(false) ;
+        }   
+        veml6040[1] = new VEML6040(edge_i2c0, VEML6040_I2C_ADDRESS) ;
+        if (led[0] == 0) {
+            led[0] = new PwmOut(PIN_LED_R) ;
+            led[1] = new PwmOut(PIN_LED_G) ;
+            led[2] = new PwmOut(PIN_LED_B) ;
+        }
+        color[1] = new edge_color(veml6040[1], led, pwm) ;
+        sensor[SENSOR_ID_COLOR2] = color[1] ;
+        sensor[SENSOR_ID_COLOR2]->setId(SENSOR_ID_COLOR2) ;
+        num_sensor++ ;
+    } else {
+        sensor[SENSOR_ID_COLOR2] = 0 ;
+        printf("VEML6040 on I2C0 is absent\n") ;
+    }
+reset_watch_dog() ;    
+    if (is_present(edge_i2c1, LM75B_I2C_ADDRESS)) {
+        printf("LM75B on I2C1 is present\n") ;
+        if (display) {
+            display->BusEnable(true) ;
+            display->locate(30, num_sensor * 30 + 40) ;
+            display->printf("TEMP1 is present") ;
+            display->BusEnable(false) ;
+        }   
+        lm75b0 = new LM75B(edge_i2c1, LM75B_I2C_ADDRESS) ;
+    } else {
+        printf("LM75B on I2C1 is absent\n") ;
+    }
+#if 0    
+    if (is_present(edge_i2c0, LM75B_I2C_ADDRESS)) {
+        printf("LM75B on I2C0 is present\n") ;
+        lm75b1 = new LM75B(edge_i2c0, LM75B_I2C_ADDRESS) ;
+    } else {
+        printf("LM75B on I2C0 is absent\n") ;
+    }
+#endif  
+     if (display) { /* press is present anyway */
+        display->BusEnable(true) ;
+        if (lm75b0) {
+            display->locate(30, (num_sensor+1) * 30 + 40) ;
+        } else {
+            display->locate(30, num_sensor * 30 + 40) ;
+        }
+        display->printf("PRESS is present") ;
+        display->BusEnable(false) ;
+    }  
+reset_watch_dog() ;    
+    an0        = new AnalogIn(PIN_AN0) ;
+    smtc502at0 = new SMTC502AT(an0) ;
+    an1        = new AnalogIn(PIN_AN1) ;
+    smtc502at1 = new SMTC502AT(an1) ;
+    temp       = new edge_temp(lm75b0, smtc502at0, smtc502at1, lm75b1) ;
+    sensor[SENSOR_ID_TEMP]  = temp ;
+    sensor[SENSOR_ID_TEMP]->setId(SENSOR_ID_TEMP) ;
+    num_sensor++ ;
+    
+
+reset_watch_dog() ;    
+    an2        = new AnalogIn(PIN_AN2) ;
+    pse530_en  = new DigitalOut(PIN_PRESS_EN, 0) ;
+    pse530     = new PSE530(an2) ;
+    pressure   = new edge_pressure(pse530, pse530_en) ;
+    sensor[SENSOR_ID_PRESS]  = pressure ;
+    sensor[SENSOR_ID_PRESS]->setId(SENSOR_ID_PRESS) ;
+    num_sensor++ ;
+ 
+reset_watch_dog() ;
+    if (num_sensor > 0) {
+        printf("%d edge_sensor(s) registered\n", num_sensor) ;
+        printf("Edge is waiting for ASR to link\n") ;
+        if (display) {
+            display->BusEnable(true) ;
+            display->foreground(White) ;
+            display->locate(40, 200) ;
+            display->printf("Waiting for ASR") ;
+            display->BusEnable(false) ;
+        }
+    }
+reset_watch_dog() ;
+}
+
+void enable_sensors(void) 
+{
+    int i ;
+    for (i = 0 ; i < NUM_MAX_SENSOR ; i++ ) {
+        if (sensor[i]) {
+            sensor[i]->enable() ;
+        }
+    }
+}
+
+void disable_sensors(void)
+{
+    int i ;
+    for (i = 0 ; i < NUM_MAX_SENSOR ; i++ ) {
+        if (sensor[i]) {
+            sensor[i]->disable() ;
+        }
+    }
+}
+
+void   reboot_edge(void) 
+{
+    int i ;
+    reset_watch_dog() ;
+    disable_sensors() ;
+    reset_watch_dog() ;
+    if (display) {
+        delete display ;
+        display = 0 ;
+    }
+    for (i = 0 ; i < NUM_MAX_SENSOR ; i++ ) {
+        if (sensor[i]) {
+            reset_watch_dog() ;
+            delete sensor[i] ;
+            sensor[i] = 0 ;
+        }
+    }
+    reset_watch_dog() ;
+    software_reset() ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_mgr.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,34 @@
+#ifndef _EDGE_MGR_H_
+#define _EDGE_MGR_H_
+#include "edge_sensor.h"
+
+void   init_display(void) ;
+void   init_sensors(void) ;
+void   enable_sensors(void) ;
+void   disable_sensors(void) ;
+int    init_edge_attribute(void) ;
+void   edge_splash(void) ;
+void   edge_loop(uint32_t tick_count) ;
+void   reboot_edge(void) ;
+void   draw_chart_frame(void) ;
+
+/* following two functions are for test power on/off of color sensor */
+void   enable_color_sensor(void) ;
+void   disable_color_sensor(void) ; 
+
+extern ILI9341         *display ;
+extern char             *reset_reason_str ;
+extern edge_sensor      *sensor[] ;
+extern bool             verbos ;
+extern int              display_mode ;
+extern int              edge_mgr_status ;
+extern bool             reboot_requested ;
+
+extern const unsigned char Arial12x12[] ;
+extern const unsigned char Arial24x23[] ;
+extern const unsigned char Arial28x28[] ;
+
+#define EDGE_MGR_INIT    0
+#define EDGE_MGR_RUNNING 1
+
+#endif /* _EDGE_MGR_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_pin.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,38 @@
+#ifndef _EDGE_PIN_H_
+#define _EDGE_PIN_H_
+
+#if defined (TARGET_KL25Z)
+#define PIN_INTR      PTD4
+#define PIN_ASR_RESET PTA13
+#define PIN_SCK       PTD1
+#define PIN_MOSI      PTD2
+#define PIN_MISO      PTD3
+#define PIN_CS        PTD0
+/* ILI9341 */
+#define PIN_CS_TFT    PTC7
+#define PIN_RESET_TFT PTC4
+#define PIN_DC_TFT    PTC0
+#define PIN_BL_TFT    PTC3
+
+#define PIN_FRDM_LEDR PTB18
+#define PIN_FRDM_LEDG PTB19
+#define PIN_FRDM_LEDB PTD1  /* conflict with SCK orz */
+/* on board I2C0 */
+// #define PIN_I2C0_SCL  PTE24
+// #define PIN_I2C0_SDA  PTE25
+/* external I2C0 */
+#define PIN_I2C0_SCL  PTC8 
+#define PIN_I2C0_SDA  PTC9 
+#define PIN_I2C1_SCL  PTE1
+#define PIN_I2C1_SDA  PTE0
+#define PIN_AN0       PTB0
+#define PIN_AN1       PTB1
+#define PIN_AN2       PTB2
+#define PIN_LED_R     PTA5
+#define PIN_LED_G     PTA4
+#define PIN_LED_B     PTA12
+#define PIN_PRESS_EN  PTC5
+#define PIN_COLOR_EN  PTC6
+#endif /* TARGET_KL25Z */
+
+#endif /* _EDGE_PIN_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_reset_mgr.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,145 @@
+#include "mbed.h"
+#include "edge_reset_mgr.h"
+
+/**
+  * System Reset Status Register 0 (RCM_SRS0) 0x4007_F000
+  *
+  * bit[7] : POR         Power-On Reset
+  * bit[6] : PIN         External Reset Pin
+  * bit[5] : WDOG        Watchdog
+  * bit[4] : (Reserved)
+  * bit[3] : LOL         Loss-of-Lock Reset
+  * bit[2] : LOC         Loss-of-Clock Reset
+  * bit[1] : LVD         Low-Voltage Detect Reset
+  * bit[0] : WAKEUP      Low Leakage Wakeup Reset
+  */
+#define REG_RCM_SRS0    (uint8_t *)0x4007F000
+#define POR_RESET_BIT   0x80
+#define PIN_RESET_BIT   0x40
+#define WDG_RESET_BIT   0x20
+#define LOL_RESET_BIT   0x08
+#define LOC_RESET_BIT   0x04
+#define LVD_RESET_BIT   0x02
+#define WUP_RESET_BIT   0x01
+
+  /**
+   * System Reset Status Register 1 (RCM_SRS1) 0x4007_F001
+   *
+   * bit[7:6] (Reserved)
+   * bit[5] : SACKERR     Stop Mode Acknowledge Error Reset
+   * bit[4] : (Reserved)
+   * bit[3] : MDM_AP      MDM-AP System Reset Request
+   * bit[2] : SW          Software Reset
+   * bit[1] : LOCKUP      Core Lockup
+   * bit[0] : (Reserved)
+   */
+#define REG_RCM_SRS1     (uint8_t *)0x4007F001
+#define SACK_RESET_BIT   0x20
+#define MDM_RESET_BIT    0x08
+#define SW_RESET_BIT     0x04
+#define LOCKUP_RESET_BIT 0x02
+
+#define IDX_POR_RESET    0
+#define IDX_PIN_RESET    1
+#define IDX_WDG_RESET    2
+#define IDX_LOL_RESET    3
+#define IDX_LOC_RESET    4
+#define IDX_LVD_RESET    5
+#define IDX_WUP_RESET    6
+#define IDX_SACK_RESET   7
+#define IDX_MDM_RESET    8
+#define IDX_SW_RESET     9
+#define IDX_LOCKUP_RESET 10 
+
+const char *reset_reason[] = {
+    "Power On Reset",
+    "Reset Pin Asserted",
+    "Watch Dog Reset",
+    "Loss of Lock Reset",
+    "Loss of Clock Reset",
+    "Low Voltage Detect Reset",
+    "Low Leakage Wakeup Reset",
+    "Stop Mode Acknowledge Error Reset",
+    "MDM-AP System Reset Request",
+    "Software Reset",
+    "Core Lockup Reset",
+    0
+} ;
+
+void print_reset_reason(void) 
+{
+    extern char *reset_reason_str ;
+    int idx = 0 ;
+    uint8_t *data = REG_RCM_SRS0 ;
+    if (*data & POR_RESET_BIT) {
+        idx = IDX_POR_RESET ;
+    }
+    if (*data & PIN_RESET_BIT) {
+        idx = IDX_PIN_RESET ; 
+    }
+    if (*data & WDG_RESET_BIT) {
+        idx = IDX_WDG_RESET ; 
+    }
+    if (*data & LOL_RESET_BIT) {
+        idx = IDX_LOL_RESET ;
+    }
+    if (*data & LVD_RESET_BIT) {
+        idx = IDX_LVD_RESET ;
+    }  
+    if (*data & LOC_RESET_BIT) {
+        idx = IDX_LOC_RESET ;
+    }
+    if (*data & WUP_RESET_BIT) {
+        idx = IDX_WUP_RESET ;
+    }
+    data = REG_RCM_SRS1 ;
+    if (*data & SACK_RESET_BIT) {
+        idx = IDX_SACK_RESET ;
+    }
+    if (*data & MDM_RESET_BIT) {
+        idx = IDX_MDM_RESET ;
+    }
+    if (*data & SW_RESET_BIT) {
+        idx = IDX_SW_RESET ;
+    }
+    if (*data & LOCKUP_RESET_BIT) {
+        idx = IDX_LOCKUP_RESET ;
+    }
+    printf("%s\n", reset_reason[idx]) ;
+    reset_reason_str = (char *)reset_reason[idx] ;
+}
+
+/**
+ * Software Reset
+ * 
+ * From Cortex-M0 Devices Generic User Guide
+ * 4.3.4 Application Interrupt and Reset Control Register
+ *
+ * Bit[31:16] : VECTCKEY
+ * Bit[15]    : ENDIANESS
+ * Bit[14:3]  : (Reserved)
+ * Bit[2]     : SYSRESETREQ
+ * Bit[1]     : VECTCLRACTIVE (reserved for debug use)
+ * Bit[0]     : (Reserved)
+ *
+ * Note: To trigger software reset, both VECTKEY=0x05FA and SYSRESETREQ
+ * must be written at once, therefore the value will be
+ * 0x05FA0004
+ */
+ 
+void software_reset(void)
+{
+     SCB->AIRCR = 0x05FA0004 ; 
+}
+
+/**
+ * reset_watch_dog
+ * reset the watch dog counter
+ * this function must be called within the limit (1sec)
+ */
+ 
+void reset_watch_dog(void) 
+{
+    SIM->SRVCOP = (uint32_t)0x55u;
+    SIM->SRVCOP = (uint32_t)0xAAu;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_reset_mgr.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,8 @@
+#ifndef _EDGE_RESET_MGR_H_
+#define _EDGE_RESET_MGR_H_
+
+void print_reset_reason(void) ;
+void software_reset(void) ;
+void reset_watch_dog(void) ;
+
+#endif /* _EDGE_RESET_MGR_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_time.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,230 @@
+#include "mbed.h"
+#include "edge_time.h"
+
+static const uint8_t daysInMonth[12] = {
+    31, 28, 31, 30,
+    31, 30, 31, 31,
+    30, 31, 30, 31
+} ;
+
+const char *nameOfDay[7] = {
+    "Sunday", "Monday", "Tuesday", "Wednesday", 
+    "Thursday", "Friday", "Saturday"
+} ;
+
+uint32_t edge_time = 0 ;
+uint32_t utc_offset = 9 * 60 * 60 ;
+tm current_time ;
+Ticker *tokei = 0 ;
+
+void inc_sec(void)
+{
+    __disable_irq() ; // Disable Interrupts
+    edge_time++ ;
+    __enable_irq() ; // Enable Interrupts
+}
+
+void init_timer(void)
+{
+    tokei = new Ticker() ;
+    tokei->attach(inc_sec, 1.0) ;
+}
+
+void set_time(const uint16_t  valueLen, const uint8_t *value) 
+{
+    uint32_t tmp_timestamp = 0 ;
+    for (int i = 0 ; i < valueLen ; i++ ) {
+        tmp_timestamp |= (value[i] & 0xFF) << (i * 8) ;
+    }
+    edge_time = tmp_timestamp ;
+    ts2tm(edge_time, &current_time) ;
+//    ts2time(edge_time, &current_time) ;
+}
+
+void ts2time(uint32_t timestamp, struct tm *tm)
+{
+    uint32_t seconds, minutes, hours, days, month, year ;
+    uint32_t dayOfWeek ;
+    
+//    timestamp += (3600 * 9) ; /* +9 hours for JST */
+    timestamp += utc_offset ;
+    
+    seconds = timestamp % 60 ;
+    minutes = timestamp / 60 ;
+    hours   = minutes / 60  ; /* +9 for JST */
+    minutes -= hours * 60 ;
+    days    = hours / 24 ;
+    hours   -= days * 24 ;
+    
+    tm->tm_sec = seconds ;
+    tm->tm_min = minutes ;
+    tm->tm_hour = hours ; 
+    tm->tm_mday = days + 1 ;
+//    tm->tm_mon  = month ;
+//    tm->tm_year = year ;
+//    tm->tm_wday = dayOfWeek ;
+}
+
+void ts2tm(uint32_t timestamp, struct tm *tm)
+{
+    uint32_t seconds, minutes, hours, days, month, year ;
+    uint32_t dayOfWeek ;
+    
+//    timestamp += (3600 * 9) ; /* +9 hours for JST */
+    timestamp += utc_offset ;
+    
+    seconds = timestamp % 60 ;
+    minutes = timestamp / 60 ;
+    hours   = minutes / 60  ; /* +9 for JST */
+    minutes -= hours * 60 ;
+    days    = hours / 24 ;
+    hours   -= days * 24 ;
+    
+    /* Unix timestamp start 1-Jan-1970 Thursday */
+    year = 1970 ;
+    dayOfWeek = 4 ; /* Thursday */
+    
+    while(1) {
+        bool isLeapYear = 
+            (((year % 4) == 0)
+            &&(((year % 100) != 0)
+            || ((year % 400) == 0))) ;
+        uint16_t daysInYear = isLeapYear ? 366 : 365 ;
+        if (days >= daysInYear) {
+            dayOfWeek += isLeapYear ? 2 : 1 ;
+            days      -= daysInYear ;
+            if (dayOfWeek >= 7) {
+                dayOfWeek -= 7 ;
+            }
+            year++ ;
+        } else {
+            tm->tm_yday = days ;
+            dayOfWeek += days ;
+            dayOfWeek %= 7 ;
+            
+            /* calc the month and the day */
+            for (month = 0 ; month < 12 ; month++) {
+                uint8_t dim = daysInMonth[month] ;
+                
+                /* add a day to feburary if this is a leap year */
+                if ((month == 1) && (isLeapYear)) {
+                    dim++ ;
+                }
+                
+                if (days >= dim) {
+                    days -= dim ;
+                } else {
+                    break ;
+                }
+            }
+            break ;
+        }
+    }
+    tm->tm_sec = seconds ;
+    tm->tm_min = minutes ;
+    tm->tm_hour = hours ; 
+    tm->tm_mday = days + 1 ;
+    tm->tm_mon  = month ;
+    tm->tm_year = year ;
+    tm->tm_wday = dayOfWeek ;
+}
+
+void print_time(struct tm *tm)
+{
+    printf("%02d:%02d:%02d",
+        tm->tm_hour,
+        tm->tm_min,
+        tm->tm_sec ) ;
+}
+
+void print_time(uint32_t thetime) 
+{
+    struct tm timestruct ;
+    ts2time(thetime, &timestruct) ;
+    print_time(&timestruct) ;
+}
+
+void print_time(void)
+{
+    struct tm timestruct ;
+    ts2time(edge_time, &timestruct) ;
+    print_time(&timestruct) ;
+}
+
+void print_date(struct tm *tm) 
+{
+    printf("%d/%d/%d %02d:%02d:%02d",
+        tm->tm_year,
+        tm->tm_mon + 1,
+        tm->tm_mday,
+        tm->tm_hour,
+        tm->tm_min,
+        tm->tm_sec
+        ) ;
+}
+
+void print_date_wd(struct tm *tm) 
+{
+    printf("%d/%d/%d %02d:%02d:%02d (%s)",
+        tm->tm_year,
+        tm->tm_mon + 1,
+        tm->tm_mday,
+        tm->tm_hour,
+        tm->tm_min,
+        tm->tm_sec,
+        nameOfDay[tm->tm_wday]
+        ) ;
+}
+
+void time2str(struct tm *tm, char *timestr) 
+{
+    sprintf(timestr, "%02d:%02d:%02d",
+        tm->tm_hour,
+        tm->tm_min,
+        tm->tm_sec ) ;
+}
+
+void time2str(char *timestr)
+{
+    struct tm timestruct ;
+    ts2time(edge_time, &timestruct) ;
+    time2str(&timestruct, timestr) ;
+}
+
+int32_t time2seq(uint32_t timestamp)
+{
+    struct tm timestruct ;
+    int32_t result  ;
+    ts2time(timestamp, &timestruct) ;
+    result = timestruct.tm_hour * 10000 
+        + timestruct.tm_min * 100
+        + timestruct.tm_sec ;
+    return(result) ;
+}
+
+void time2seq(uint32_t timestamp, char *timestr) 
+{
+    struct tm timestruct ;
+    ts2tm(timestamp, &timestruct) ;
+    sprintf(timestr, "%d%02d%02d%02d%02d%02d",
+        timestruct.tm_year,
+        timestruct.tm_mon + 1,
+        timestruct.tm_mday,
+        timestruct.tm_hour,
+        timestruct.tm_min,
+        timestruct.tm_sec
+    ) ;
+}
+
+void time2date(struct tm *tm, char *datestr)
+{
+    sprintf(datestr, "%d/%d/%d %02d:%02d:%02d (%s)",
+        tm->tm_year,
+        tm->tm_mon + 1,
+        tm->tm_mday,
+        tm->tm_hour,
+        tm->tm_min,
+        tm->tm_sec,
+        nameOfDay[tm->tm_wday]
+    ) ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_time.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,25 @@
+#ifndef _EDGE_TIME_H_
+#define _EDGE_TIME_H_
+#include "mbed.h"
+
+void init_timer(void) ;
+void set_time(const uint16_t  valueLen, const uint8_t *value) ;
+void ts2time(uint32_t timestamp, struct tm *tm) ; /* light version */
+void ts2tm(uint32_t timestamp, struct tm *date) ; /* full version */
+void print_time(void) ; /* light version */
+void print_time(uint32_t thetime) ;
+void print_time(struct tm *tm) ; /* light version */
+void print_date(struct tm *date) ; /* full version */
+void print_date_wd(struct tm *date) ; /* vull version with day of week */
+void time2str(char *timestr) ; /* light version */
+int32_t time2seq(uint32_t timestamp) ; /* hhmmss */
+void time2seq(uint32_t timestamp, char *timestr) ;
+void time2str(struct tm *tm, char *timestr) ; /* hh:mm:ss */
+void time2date(struct tm *tm, char *datestr) ; /* YYYY/MM/DD hh:mm:ss */
+void time2date(struct tm *tm, char *datestr) ; /* full version with day of week */
+
+extern const char *nameOfDay[] ;
+extern tm current_time ;
+extern uint32_t edge_time ;
+extern uint32_t utc_offset ;
+#endif /* _EDGE_TIME_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,130 @@
+#include "mbed.h"
+#include "vt100.h"
+#include "afLib.h"
+#include "af_mgr.h"
+#include "edge_mgr.h"
+#include "edge_time.h"
+#include "edge_reset_mgr.h"
+/**
+ * afero poc1.5 25-Dec-2017 version
+ * from this version, watch dog timer joined again.
+ */
+
+vt100   *tty = 0 ;
+uint32_t wait_tolerance = 500 ; /* 5sec */
+uint32_t connect_tolerance = 60 ; /* after 60 trials, reboot */
+uint32_t wait_count = 0 ;
+uint32_t connect_trial_count = 0 ;
+
+/**
+ * wait_connection
+ * When gConnected == false, which is connection is lost.
+ * Each 5sec check attribute ATTR_WIFI_STDY_STATE to see
+ * if the connection has recovered.
+ * Meantime even if connection is established communicated
+ * data is invalid, so AF_SYSTEM_ASR_STATE is also
+ * checked for gLinked ;
+ * And in case connect_tolerance trials failed
+ * try to reboot the system if it can improve the situation.
+ */
+void wait_connection(void)
+{
+    int result ;
+    wait_count++ ;
+    if (wait_count > wait_tolerance) {
+        reset_watch_dog() ;
+        if (gConnected == false) {
+            result = afero->getAttribute(ATTR_WIFI_STDY_STATE) ;
+            if (result != afSUCCESS) {
+                print_af_error(result) ;
+            }
+        }
+        if (gLinked == false) {
+            result = afero->getAttribute(AF_SYSTEM_ASR_STATE) ;
+            if (result != afSUCCESS) {
+                print_af_error(result) ;
+            }
+        }
+        connect_trial_count++ ;
+        if (connect_trial_count > connect_tolerance) {
+            reboot_edge() ;
+        }
+        wait_count = 0 ;
+    }
+}
+
+void init_hardware(void)
+{
+    int i ;
+    int result ;
+    
+        reset_watch_dog() ;
+    init_display() ;
+        reset_watch_dog() ;
+    init_aflib() ;
+        reset_watch_dog() ;
+    init_sensors() ;
+        reset_watch_dog() ;
+    init_timer() ;
+
+    while(true) {
+        reset_watch_dog() ;
+        for (i = 0 ; i < 10 ; i++ ) {
+            afero->loop() ;
+            reset_watch_dog() ;
+        }
+        if ((gLinked == true)&&(gConnected == true)) {
+            wait_count = 0 ;
+            connect_trial_count = 0 ;
+            if (afero->isIdle()) {
+                result = init_edge_attribute() ;
+                if (result == 0) {
+                    break ;
+                }
+            }
+        } else { /* gLinked == false */
+            wait_connection() ;
+        }
+        wait_ms(10) ;
+    }
+    do {
+//    while(!afero->isIdle()) {
+        reset_watch_dog() ;
+        for (i = 0 ; i < 10 ; i++ ) { 
+            afero->loop() ;
+            wait_ms(100) ; 
+        }
+    } while(!afero->isIdle()) ;
+    edge_mgr_status = EDGE_MGR_RUNNING ;
+}
+
+// main() runs in its own thread in the OS
+int main() {
+    static uint32_t count_robin = 0 ;
+
+    tty = new vt100() ;
+//    tty->cls() ;
+    printf("Afero test program (ver. %s) started\n", __DATE__) ;   
+    printf("=== Reset Reason ===\n") ;
+    print_reset_reason() ;
+    printf("====================\n") ;
+
+    init_hardware() ;
+    
+    edge_splash() ;
+                    
+    while (true) {
+        count_robin++ ;
+        afero->loop() ;
+        if ((gLinked == true)&&(gConnected == true)) {
+            wait_count = 0 ;
+            connect_trial_count = 0 ;
+            if (afero->isIdle()) {
+                edge_loop(count_robin) ;
+            }
+        } else { /* gLinked == false */
+            wait_connection() ;      
+        }
+        wait_ms(10) ;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/7130f322cb7e
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/LM75B.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,122 @@
+#include "mbed.h"
+#include "LM75B.h"
+#include "af_mgr.h"
+
+/* Register list */
+#define PTR_CONF    0x01
+#define PTR_TEMP    0x00
+#define PTR_TOS     0x03
+#define PTR_THYST   0x02
+
+/* Configuration register */
+/* B[7:5] : Reserved */
+/* B[4:3] : OS_F_QUE[1:0] OS fault queue value */
+#define CONFIG_QUE_1    0x00
+#define CONFIG_QUE_2    (0x01 << 3)
+#define CONFIG_QUE_4    (0x10 << 3)
+#define CONFIG_QUE_6    (0x11 << 3) 
+/* B[2] : OS_POL  0 = OS active LOW,  1 = OS active HIGH */
+#define CONFIG_OS_POL_L 0x00
+#define CONFIG_OS_POL_H (0x01 << 2)
+/* B[1] : OS_COMP_INT 0 = OS comparator, 1 = OS interrupt */
+#define CONFIG_OS_COMP  0x00
+#define CONFIG_OS_INT   (0x01 << 1)
+/* B[0] : SHUTDOWN    0 = normal, 1 = shutdown */
+#define CONFIG_NORMARL  0x00
+#define CONFIG_SHUTDOWN 0x01
+
+/* Temperature register */
+/* D[15:5] = 11 bit data 0.125 * temp data */
+/* D[4:0] : reserved */
+
+/* Tos register */
+/* D[15:7] = 9 bit data */
+/* D[6:0] : reserved */
+
+/* Thyst register */
+/* D[15:7] = 9 ibt data */
+/* D[6:0] : reserved */
+
+LM75B::LM75B(I2C *i2c, int addr) : m_addr(addr<<1) {
+    p_i2c = i2c ;
+    p_i2c->frequency(100000); /* 100kHz */
+    // activate the peripheral
+}
+
+LM75B::~LM75B() { }
+
+int LM75B::temp(int8_t *temp)
+{
+    int result ;
+    char t[1] = { 0x00 } ;
+    result = p_i2c->write(m_addr, t, 1, true) ;
+    if (result == 0) {
+        result = p_i2c->read(m_addr, t, 1) ;
+    }
+    if (result == 0) {
+        *temp = (int8_t)t[0] ;
+    }
+    return( result ) ;
+}
+
+int LM75B::getTemp(float *temp)
+{
+    int result ;
+    char t[2] = { 0, 0 } ;
+    int16_t iTemp = 0 ;
+    result = p_i2c->write(m_addr, t, 1) ; /* write pointer byte 0x00 */
+    if (result == 0) {
+        result = p_i2c->read(m_addr, t, 2) ; /* read MSB, LSB */
+    }
+    if (result == 0) {
+        iTemp = (t[0] << 8) | t[1] ;
+        iTemp >>= 5 ;
+        *temp = 0.125 * iTemp ;
+    }
+    return( result ) ;
+}
+
+int LM75B::getConfig(uint8_t ptr_byte, uint8_t *config_data) 
+{
+    int result ;
+    char config = 0x00 ; /* default value */
+    result = p_i2c->write(m_addr, (char*)(&ptr_byte), 1, true) ;
+    if (result == 0) {
+        result = p_i2c->read(m_addr, &config, 1) ;
+    }
+    if (result == 0) {
+        *config_data = config ;
+    }
+    return( result ) ;
+}
+
+int LM75B::setConfig(uint8_t ptr_byte, uint8_t config_data) 
+{
+    int result ;
+    char t[2] ;
+    t[0] = ptr_byte ;
+    t[1] = config_data ;
+    result = p_i2c->write(m_addr, t, 2, true) ;
+    return( result ) ;
+}
+
+int LM75B::readRegs(int addr, uint8_t * data, int len) 
+{
+    int result ;
+    char t[1] = {addr};
+    __disable_irq() ; // Disable Interrupts
+    result = p_i2c->write(m_addr, t, 1, true);
+    if (result == 0) {
+        result = p_i2c->read(m_addr, (char *)data, len);
+    }
+    __enable_irq() ; // Enable Interrupts
+    return( result ) ;
+}
+
+int LM75B::writeRegs(uint8_t * data, int len) {
+    int result ;
+    __disable_irq() ; // Disable Interrupts
+    result = p_i2c->write(m_addr, (char *)data, len);
+    __enable_irq() ; // Enable Interrupts
+    return( result ) ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/LM75B.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,104 @@
+#ifndef _LM75B_H_
+#define _LM75B_H_
+
+#include "mbed.h"
+
+/**
+* NXP LM75B Digital temperature sensor and thermal watchdog
+*
+* @code
+#include "mbed.h"
+#include "LM75B.h"
+#define LM75B_I2C_ADDRESS (0x48)
+
+#if defined (TARGET_KL25Z)
+#define PIN_SCL  PTE1
+#define PIN_SDA  PTE0
+#elif defined (TARGET_KL46Z)
+#define PIN_SCL  PTE1
+#define PIN_SDA  PTE0
+#elif defined (TARGET_K64F)
+#define PIN_SCL  PTE24
+#define PIN_SDA  PTE25
+#elif defined (TARGET_K22F)
+#define PIN_SCL  PTE1
+#define PIN_SDA  PTE0
+#elif defined (TARGET_KL05Z)
+#define PIN_SCL  PTB3
+#define PIN_SDA  PTB4
+#elif defined (TARGET_NUCLEO_F411RE)
+#define PIN_SCL  PB_8
+#define PIN_SDA  PB_9
+#else
+ #error TARGET NOT DEFINED
+#endif
+
+int main() {
+    int8_t itemp = 0 ;
+    float ftemp = 0.0 ;
+    LM75B lm75b(PIN_SDA, PIN_SCL, LM75B_I2C_ADDRESS) ;
+    
+    while(1) {
+        itemp = lm75b.temp() ;
+        lm75b.getTemp(&ftemp) ;
+        printf("Temp = %d C degree,  %.3f C degree\n", itemp, ftemp) ;
+        wait(1) ;
+    }
+}
+* @endcode
+*/
+class LM75B
+{
+public:
+  /**
+  * LM75B constructor
+  *
+  * @param i2c pointer to the I2C object
+  * @param addr addr of the I2C peripheral
+  */
+  LM75B(I2C *i2c, int addr);
+
+  /**
+  * LM75B destructor
+  */
+  ~LM75B();
+
+  /**
+  * get temperature as one byte (signed)
+  * @param *temp int8_t returns integer part of the temperature
+  * @return 0: success not-0: failure
+  */
+  int temp(int8_t *temp) ;
+  
+  /**
+   * get temperature as 11 bit (float)
+   * @param *temp float returns the temperature as float 
+   * @return 0: success not-0: failure
+   */
+  int getTemp(float *temp) ;
+  
+  /**
+   * get configuration register
+   * @param ptr_byte uint8_t pointer value for the register
+   * @param *config_data uint8_t value of the config register
+   * @return 0: success non-0: failure
+   */
+  int getConfig(uint8_t ptr_byte, uint8_t *config_data) ;
+  
+  /**
+   * set configuration register
+   * @param ptr_byte uint8_t pointer value for the register
+   * @param config_data uint8_t value to set in the config register
+   * @return 0: success non-0: failure
+   */
+  int setConfig(uint8_t ptr_byte, uint8_t config_data) ;
+
+private:
+  I2C *p_i2c;
+  int m_addr;
+  int readRegs(int addr, uint8_t * data, int len);
+  int writeRegs(uint8_t * data, int len);
+
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/MMA8451Q.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,166 @@
+/**
+ * MMA8451Q 3-Axis, 14-bit/8-bit Digital Accelerometer
+ */
+ 
+#include "mbed.h"
+#include "MMA8451Q.h"
+#include "af_mgr.h"
+
+#define REG_STATUS           0x00 // when F_MODE = 00
+#define REG_FIFO_STATUS      0x00 // when F_MODE > 0
+#define REG_XYZ_FIFO         0x01 // Root pointer to XYZ FIFO data
+#define REG_OUT_X_MSB        0x01 // 8 MSBs of 14-bit sample
+#define REG_OUT_X_LSB        0x02 // 6 LSBs of 14-bit sample
+#define REG_OUT_Y_MSB        0x03 
+#define REG_OUT_Y_LSB        0x04
+#define REG_OUT_Z_MSB        0x05
+#define REG_OUT_Z_LSB        0x06
+#define REG_F_SETUP          0x09 // FIFO setup
+#define REG_TRIG_CFG         0x0A // Map of FIFO daa capture events
+#define REG_SYSMOD           0x0B // Current System Mode
+#define REG_INT_SOURCE       0x0C // Interrupt status
+#define REG_WHO_AM_I         0x0D // Device ID (0x1A)
+#define REG_XYZ_DATA_CFG     0x0E // Dynamic Range Settings
+#define REG_HP_FILTER_CUTOFF 0x0F // Cutoff freq is set to 16Hz@800Hz
+#define REG_PL_STATUS        0x10 // Landscape/Portrait orientation status
+#define REG_PL_CFG           0x11 // Landscape/Portrait configuration
+#define REG_PL_COUNT         0x12 // Landscape/Portrait debounce counter 
+#define REG_PL_BF_ZCOMP      0x13 // Back/Front, Z-Lock Trip threshold
+#define REG_P_L_THS_REG      0x14 // Portrait to Landscape Trip Angle is 29 degree
+#define REG_FF_MT_CFG        0x15 // Freefall/Motion function block configuration
+#define REG_FF_MT_SRC        0x16 // Freefall/Motion event source register
+#define REG_FF_MT_THS        0x17 // Freefall/Motion threshold register
+#define REG_FF_MT_COUNT      0x18 // Freefall/Motion debounce counter
+// TRANSIENT
+#define REG_TRANSIENT_CFG    0x1D // Transient functional block configuration
+#define REG_TRANSIENT_SRC    0x1E // Transient event status register
+#define REG_TRANSIENT_THS    0x1F // Transient event threshold
+#define REG_TRANSIENT_COUNT  0x20 // Transient debounce counter
+// PULSE
+#define REG_PULSE_CFG        0x21 // ELE, Double_XYZ or Single_XYZ
+#define REG_PULSE_SRC        0x22 // EA, Double_XYZ or Single_XYZ
+#define REG_PULSE_THSX       0x23 // X pulse threshold
+#define REG_PULSE_THSY       0x24 // Y pulse threshold
+#define REG_PULSE_THSZ       0x25 // Z pulse threshold
+#define REG_PULSE_TMLT       0x26 // Time limit for pulse
+#define REG_PULSE_LTCY       0x27 // Latency time for 2nd pulse
+#define REG_PULSE_WIND       0x28 // Window time for 2nd pulse
+#define REG_ASLP_COUNT       0x29 // Counter setting for Auto-SLEEP
+// Control Registers
+#define REG_CTRL_REG1        0x2A // ODR = 800Hz, STANDBY Mode
+#define REG_CTRL_REG2        0x2B // Sleep Enable, OS Modes, RST, ST
+#define REG_CTRL_REG3        0x2C // Wake from Sleep, IPOL, PP_OD
+#define REG_CTRL_REG4        0x2D // Interrupt enable register
+#define REG_CTRL_REG5        0x2E // Interrupt pin (INT1/INT2) map
+// User Offset
+#define REG_OFF_X            0x2F // X-axis offset adjust
+#define REG_OFF_Y            0x30 // Y-axis offset adjust
+#define REG_OFF_Z            0x31 // Z-axis offset adjust
+
+// Value definitions
+#define BIT_TRIG_TRANS       0x20  // Transient interrupt trigger bit
+#define BIT_TRIG_LNDPRT      0x10  // Landscape/Portrati Orientation
+#define BIT_TRIG_PULSE       0x08  // Pulse interrupt trigger bit
+#define BIT_TRIG_FF_MT       0x04  // Freefall/Motion trigger bit
+
+MMA8451Q::MMA8451Q(I2C *i2c, int addr) : m_addr(addr<<1) {
+    // activate the peripheral
+    p_i2c = i2c ;
+    uint8_t data[2] = {REG_CTRL_REG1, 0x01};
+    writeRegs(data, 2);
+}
+
+MMA8451Q::~MMA8451Q() { }
+
+int MMA8451Q::readRegs(int addr, uint8_t * data, int len) 
+{
+    char t[1] = {addr};
+    int result ;
+    __disable_irq() ; // Disable Interrupts
+    result = p_i2c->write(m_addr, t, 1, true);
+    if (result == 0) {
+        result = p_i2c->read(m_addr, (char *)data, len);
+    }
+    __enable_irq() ; // Enable Interrupts
+    return( result ) ;
+}
+
+int MMA8451Q::writeRegs(uint8_t * data, int len) 
+{
+    int result ;
+    __disable_irq() ; // Disable Interrupts
+    result = p_i2c->write(m_addr, (char *)data, len);
+    __enable_irq() ; // Enable Interrupts
+    return( result ) ;
+}
+
+int MMA8451Q::getAllRawData(int16_t value[])
+{
+    int result ;
+    uint8_t data[6] ;
+    result = readRegs(REG_OUT_X_MSB, data, 6) ;
+    if (result == 0) {
+        value[0] = ((int16_t)((data[0] << 8) | data[1])) >> 2 ;
+        value[1] = ((int16_t)((data[2] << 8) | data[3])) >> 2 ;
+        value[2] = ((int16_t)((data[4] << 8) | data[5])) >> 2 ;
+    }
+    return( result ) ;
+}
+
+int MMA8451Q::getAllData(float fvalue[])
+{
+    int result ;
+    uint8_t data[6] ;
+    result = readRegs(REG_OUT_X_MSB, data, 6) ;
+    if (result == 0) {
+        fvalue[0] = (float)((int16_t)((data[0] << 8) | data[1])) / 16384.0 ;
+        fvalue[1] = (float)((int16_t)((data[2] << 8) | data[3])) / 16384.0 ;
+        fvalue[2] = (float)((int16_t)((data[4] << 8) | data[5])) / 16384.0 ;
+    }
+    return( result ) ;
+}
+
+int16_t MMA8451Q::getRawData(uint8_t addr)
+{
+    int16_t value ;
+    uint8_t data[2] ;
+    readRegs(addr, data, 2) ;
+    value = ((int16_t)((data[0] << 8) | data[1])) >> 2 ;
+    return( value ) ;
+}
+
+int16_t MMA8451Q::getRawX(void) 
+{
+    int16_t value ;
+    value = getRawData(REG_OUT_X_MSB) ;
+    return( value ) ;
+}
+
+int16_t MMA8451Q::getRawY(void) 
+{
+    int16_t value ;
+    value = getRawData(REG_OUT_Y_MSB) ;
+    return( value ) ;
+}
+
+int16_t MMA8451Q::getRawZ(void) 
+{
+    int16_t value ;
+    value = getRawData(REG_OUT_Z_MSB) ;
+    return( value ) ;
+}
+  
+float MMA8451Q::getAccX(void)
+{
+    return(((float)getRawX())/4096.0) ;
+}
+
+float MMA8451Q::getAccY(void) 
+{
+    return(((float)getRawY())/4096.0) ;
+}
+
+float MMA8451Q::getAccZ(void) 
+{
+    return(((float)getRawZ())/4096.0) ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/MMA8451Q.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,53 @@
+#ifndef _MMA8451Q_H_
+#define _MMA8451Q_H_
+
+#include "mbed.h"
+/**
+ * MMA8451Q 3-Axis, 14-bit/8-bit Digital Accelerometer
+ */
+ 
+class MMA8451Q {
+public:
+  /**
+  * MMA8451Q constructor
+  *
+  * @param i2c pointer to the I2C object
+  * @param addr 7bit addr of the I2C peripheral
+  */
+  MMA8451Q(I2C *i2c, int addr);
+
+  /**
+  * MMA8451Q destructor
+  */
+  ~MMA8451Q();
+ 
+  /**
+   * get all x, y, z data as int16_t
+   * @param data[] three int16_t data will be returned
+   * @returns I2C status 0: success others: I2C error
+   */ 
+  int     getAllRawData(int16_t data[]) ;
+  
+  /**
+   * get all x, y, z data as float
+   * @param data three float data will be returned
+   * @returns I2C status 0: success others: I2C error
+   */
+  int     getAllData(float value[]) ;
+  int16_t getRawData(uint8_t addr) ;
+  int16_t getRawX(void) ;
+  int16_t getRawY(void) ;
+  int16_t getRawZ(void) ;
+  
+  float getAccX(void) ;
+  float getAccY(void) ;
+  float getAccZ(void) ;
+  
+private:
+  I2C *p_i2c;
+  int m_addr;
+  int readRegs(int addr, uint8_t * data, int len);
+  int writeRegs(uint8_t * data, int len);
+} ;
+
+#endif /* _MMA8451Q_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/PSE530.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,60 @@
+#include "mbed.h"
+#include "PSE530.h"
+
+/**
+ * SMC PSE530 pressure sensor
+ * analog output 1.0V - 5.0V
+ * 1.0V : 0
+ * 5.0V : 1MPa
+ * (at 0.6V : -0.1MPa)
+ * Our sensor I/F converts 0-5V to 0-3V
+ * So we suppose V = Analog Float Value : Pressure
+ * 0.6V = 0.2 : 0
+ * 3.0V = 1.0 : 1MPa
+ */
+ 
+ /**
+  * conversion from Pa to kgf/cm2
+  * 98,066.5 Pa = 1 kgf/cm2
+  * 1 Pa = 1 / 98066.6 kgf/cm2
+  */
+
+PSE530::PSE530(AnalogIn *ain)
+{
+    _ain = ain ;
+}
+
+PSE530::~PSE530(void) 
+{
+    if (_ain) {
+        delete _ain ;
+    }
+}
+
+/**
+ * On FRDM-KL25Z ADC's AREF is about 3.28V
+ * Where the converted pressure output is 0 to 3.21V
+ * So we must map ADC output 0 to 3.21/3.28 as full scale
+ * 
+ * Then according to the datasheet of PSE530
+ * when full range is 0V to 5V
+ * 1V is 0 and 5V is 1MPa which is converted to
+ * 0.642/3.28 to 3.21/3.28 ~ 0.195731 to 0.9786585.
+ * The linear equation of
+ * y = a x + b
+ * 0 = a * 0.195731 + b
+ * 1 = a * 0.978658 + b
+ * results a = 1.277, b = -0.250
+ */
+float PSE530::getPressure(void)
+{
+    float coef_A = 1.277 ;
+    float coef_B = -0.250 ;
+    float av = 0.0 ;
+    float value = 0.0 ;
+    av = coef_A * _ain->read() + coef_B ;
+//    printf("Pressure ADC = %.4f\n", av) ;
+    value = 1000000 * av  ; /* 1MPa at 1.0 */
+    value = value / 98066.5 ; /* Pa -> kgf/cm2 */
+    return( value ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/PSE530.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,30 @@
+#ifndef _PSE530_H_
+#define _PSE530_H_
+#include "mbed.h"
+
+/**
+ * PSE530 Pressure Sensor
+ */
+
+class PSE530 {
+public:
+/**
+ * Constructor
+ */
+    PSE530(AnalogIn *ain) ;
+
+/**
+ * destructor
+ */
+    ~PSE530(void) ;
+    
+/**
+ * getPressure
+ * @returns float pressure in kgf/cm2
+ */
+    float getPressure(void) ;
+private:
+    AnalogIn *_ain ;
+} ;
+
+#endif /* _PSE530_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/SMTC502AT.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,47 @@
+#include "mbed.h"
+#include "SMTC502AT.h"
+
+SMTC502AT::SMTC502AT(AnalogIn *ain, float R0, float R1, float B, float T0) 
+{
+    _ain = ain ;
+    _r0 = R0 ;
+    _r1 = R1 ;
+    _b  = B ;
+    _t0 = T0 ;
+}
+
+SMTC502AT::~SMTC502AT(void)
+{
+    if (_ain) {
+        delete _ain ;
+    }
+}
+
+/**
+ * getTemp returns the temperature
+ * operational temperature is -50C to +105C
+ */
+float SMTC502AT::getTemp(void)
+{
+    float result = 0.0 ;
+    float f, raw, rr1, t ;
+    if (_ain) {
+        f = _ain->read() ;
+#if 0
+        if (f < 0.087) { /* +105C */
+            printf("Temp is Too high or the sensor is absent\n") ;
+            f = 0.087 ;
+        }
+        if (f > 0.978) { /* -50C */
+            printf("Temp is Too low or the sensor encountered a problem\n") ;
+            f = 0.978 ;
+        }
+#endif
+        raw = f * 3.3 ;
+        rr1 = _r1 * raw / (3.3 - raw) ;
+        t = 1.0 / (log(rr1 / _r0) / _b + (1/_t0)) ;
+        result = t - 273.15 ;
+    }
+    return( result ) ;
+}
+        
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/SMTC502AT.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,40 @@
+#ifndef _SMTC502AT_H_
+#define _SMTC502AT_H_
+
+#include "mbed.h"
+
+/** 
+ * Semitec 502AT-11 temperature sensor 
+ */
+ 
+class SMTC502AT {
+public:
+/**
+ * constructor
+ * @param *ain AnalogIn object
+ * @param R0 5.0 ohm (default)
+ * @param R1 4.95 ohm (default)
+ * @param B 3324 (default)
+ * @param T0 298.15 (default)
+ */
+    SMTC502AT(AnalogIn *ain, float R0=5.0, float R1=4.95, float B=3324, float T0=298.15) ;
+
+/**
+ * destructor
+ */
+    ~SMTC502AT(void) ;
+    
+/**
+ * getTemp get temperature
+ * @returns temperature in float format
+ */
+    float getTemp(void) ;
+private:
+    AnalogIn *_ain ;
+    float _r0 ;
+    float _r1 ;
+    float _b ;
+    float _t0 ;
+} ;
+
+#endif /* _SMTC502AT_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/VEML6040.cpp	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,285 @@
+/*
+ * File description here
+ */
+#include "VEML6040.h"
+#include "af_mgr.h"
+
+/* VEML6075 SLAVE ADDRESS AND FUNCTION DESCRIPTION */
+#define REG_COLOR_CONF  0x00
+#define REG_Reserved1  0x01
+#define REG_Reserved2  0x02
+#define REG_Reserved3  0x03
+#define REG_Reserved4  0x04
+#define REG_Reserved5  0x05
+#define REG_Reserved6  0x06
+#define REG_Reserved7  0x07
+#define REG_R_Data  0x08
+#define REG_G_Data  0x09
+#define REG_B_Data  0x0A
+#define REG_W_Data  0x0B
+
+// Following magic numbers are from 
+// VISHAY VEML6040 Application Note 84331
+// Page 4 
+#define LUX_RESOLUTION_0  (0.25168)
+#define LUX_RESOLUTION_1  (0.12584)
+#define LUX_RESOLUTION_2  (0.06292)
+#define LUX_RESOLUTION_3  (0.03146)
+#define LUX_RESOLUTION_4  (0.01573)
+#define LUX_RESOLUTION_5  (0.007865)
+
+// Following magic numbers are from 
+// VISHAY VEML6040 Application Note 84331
+// Page 9 
+#define CORR_COEFF_M0  (0.048403)
+#define CORR_COEFF_M1  (0.183633)
+#define CORR_COEFF_M2  (-0.253589)
+#define CORR_COEFF_M3  (0.022916)
+#define CORR_COEFF_M4  (0.176388)
+#define CORR_COEFF_M5  (-0.183205)
+#define CORR_COEFF_M6  (-0.077436)
+#define CORR_COEFF_M7  (0.124541)
+#define CORR_COEFF_M8  (0.032081)
+
+// Following magic numbers are from 
+// VISHAY VEML6040 Application Note 84331
+// Page 10
+#define CCT_CONST  (4278.6)
+#define OFFSET_OPEN_AIR  (0.5)
+
+VEML6040::VEML6040(I2C *i2c, int addr) : m_addr(addr<<1) {
+    p_i2c = i2c ;
+    p_i2c->frequency(100000); /* 100kHz */
+    // activate the peripheral
+}
+
+VEML6040::~VEML6040() { }
+
+/**
+ * set COLOR Config
+ * @param colorconf uint8_t 8bit register value
+ * @returns 0: success non-0: failure
+ * @note Command Code 0x00 is used to access CONF register
+ * @note bit[7] (reserved)
+ * @note bit[6:4] = IT[2:0] Integration Time Selector
+ * @note bit[3] (reserved)
+ * @note bit[2] TRIG Proceed one detcting cycle at manual force mode
+ * @note bit[1] AF 0: Auto mode 1: manual force mode
+ * @note bit[0] SD 0: normal 1: chip shutdown setting
+ *
+ * @note IT[2:0] 0=40ms, 1=80ms, 2=160ms, 3=320ms, 4=640ms, 5=1280ms
+ * @note as our WatchDog is set to 1sec, 1280ms is invalid
+ * @note and 640ms may not be practical
+ */
+int VEML6040::setCOLORConf(uint8_t colorconf)
+{
+     int result ;
+     uint8_t data[3] ;
+     data[0] = REG_COLOR_CONF ;
+     data[1] = colorconf ;
+     data[2] = 0 ;
+     result = writeRegs(data, 3) ;
+     return( result ) ;
+}
+
+/**
+ * get COLOR Config
+ * @param *colorconf uint8_t refer to setCOLORConf for the value
+ * @returns 0: success non-0: failure
+ */
+int VEML6040::getCOLORConf(uint8_t *colorconf)
+{
+    int result ;
+    uint8_t data[2] ;
+    result = readRegs(REG_COLOR_CONF, data, 2) ;
+    if (result == 0) {
+        *colorconf = data[0] ;
+    }
+    return( result ) ;
+}
+
+
+
+int VEML6040::getRData(uint16_t *rdata)
+{
+    uint8_t data[2] ;
+    int result ;
+    result = readRegs(REG_R_Data, data, 2) ;
+    *rdata = (data[1]<<8) | data[0] ;
+    return( result ) ;
+}
+
+int VEML6040::getGData(uint16_t *gdata)
+{
+    uint8_t data[2] ;
+    int result ;
+    result = readRegs(REG_G_Data, data, 2) ;
+    *gdata = (data[1]<<8) | data[0] ;
+    return( result ) ;
+}
+
+int VEML6040::getBData(uint16_t *bdata)
+{
+    uint8_t data[2] ;
+    int result ;
+    result = readRegs(REG_B_Data, data, 2) ;
+    *bdata = (data[1]<<8) | data[0] ;
+    return( result ) ;
+}
+
+int VEML6040::getWData(uint16_t *wdata)
+{
+    uint8_t data[2] ;
+    int result ;
+    result = readRegs(REG_W_Data, data, 2) ;
+    *wdata = (data[1]<<8) | data[0] ;
+    return( result ) ;
+}
+
+// usage
+// fvalue = veml->getUVA() ;
+// printf("%f", fvalue) ;
+float VEML6040::getR(void) 
+{
+    uint16_t data ;
+    float value ;
+    getRData(&data) ;
+    value = (float)LUX_RESOLUTION_0 * (float)data ;
+    return( value ) ;
+}
+
+float VEML6040::getG(void) 
+{
+    uint16_t data ;
+    float value ;
+    getGData(&data) ;
+    value = (float)LUX_RESOLUTION_0 * (float)data ;
+    return( value ) ;
+}
+
+float VEML6040::getB(void) 
+{
+    uint16_t data ;
+    float value ;
+    getBData(&data) ;
+    value = (float)LUX_RESOLUTION_0 * (float)data ;
+    return( value ) ;
+}
+
+float VEML6040::getW(void) 
+{
+    uint16_t data ;
+    float value ;
+    getWData(&data) ;
+    value = (float)LUX_RESOLUTION_0 * (float)data ;
+    return( value ) ;
+}
+
+float VEML6040::getX(void) 
+{
+    uint16_t R ;
+    uint16_t G ;
+    uint16_t B ;
+    float value ;
+    getRData(&R) ;
+    getGData(&G) ;
+    getBData(&B) ;
+    value = (float)CORR_COEFF_M0 * (float)R + (float)CORR_COEFF_M1 * (float)G + (float)CORR_COEFF_M2 * (float)B ;
+    return( value ) ;
+}
+
+float VEML6040::getY(void) 
+{
+    uint16_t R ;
+    uint16_t G ;
+    uint16_t B ;
+    float value ;
+    getRData(&R) ;
+    getGData(&G) ;
+    getBData(&B) ;
+    value = (float)CORR_COEFF_M3 * (float)R + (float)CORR_COEFF_M4 * (float)G + (float)CORR_COEFF_M5 * (float)B ;
+    return( value ) ;
+}
+
+float VEML6040::getZ(void) 
+{
+    uint16_t R ;
+    uint16_t G ;
+    uint16_t B ;
+    float value ;
+    getRData(&R) ;
+    getGData(&G) ;
+    getBData(&B) ;
+    value = (float)CORR_COEFF_M6 * (float)R + (float)CORR_COEFF_M7 * (float)G + (float)CORR_COEFF_M8 * (float)B ;
+    return( value ) ;
+}
+
+float VEML6040::getCCTiData(void) 
+{
+    uint16_t rdata ;
+    uint16_t gdata ;
+    uint16_t bdata ;
+    float value ;
+    getRData(&rdata) ;
+    getGData(&gdata) ;
+    getBData(&bdata) ;
+    value = ((float)rdata - (float)bdata) / (float)gdata + (float)OFFSET_OPEN_AIR ;
+    return( value ) ;
+}
+
+float VEML6040::getCCTData(void) 
+{
+//    uint16_t cctidata ;
+    float cctidata ;
+    float value ;
+    cctidata = getCCTiData() ;
+//    getCCTiData(&cctidata) ;
+    value = (float)CCT_CONST * powf( cctidata, -1.2455 ) ;
+    return( value ) ;
+}
+
+float VEML6040::getCIEX(void) 
+{
+    float X ;
+    float Y ;
+    float Z ;
+    float value ;
+    X = getX() ;
+    Y = getY() ;
+    Z = getZ() ; 
+    value = (float)X / ((float)X + (float)Y + (float)Z) ;
+    return( value ) ;
+}
+
+float VEML6040::getCIEY(void) 
+{
+    float X ;
+    float Y ;
+    float Z ;
+    float value ;
+    X = getX() ;
+    Y = getY() ;
+    Z = getZ() ; 
+    value = (float)Y / ((float)X + (float)Y + (float)Z) ;
+    return( value ) ;
+}
+
+int VEML6040::readRegs(int addr, uint8_t * data, int len) {
+    char t[1] = {addr};
+    int result ;
+    __disable_irq() ; // Disable Interrupts
+    result = p_i2c->write(m_addr, t, 1, true);
+    if (result == 0) { // write success
+        result = p_i2c->read(m_addr, (char *)data, len, false);
+    }
+    __enable_irq() ; // Enable Interrupts
+    return(result) ;
+}
+
+int VEML6040::writeRegs(uint8_t * data, int len) {
+    int result ;
+    __disable_irq() ; // Disable Interrupts
+    result = p_i2c->write(m_addr, (char *)data, len);
+    __enable_irq() ; // Enable Interrupts
+    return(result) ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sensors/VEML6040.h	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,155 @@
+#ifndef _VEML6040_H_
+#define _VEML6040_H_
+
+#include "mbed.h"
+
+/**
+ * RGBW Color Sensor with I2C Interface
+ * I2C 7bit address: 0x10
+ *
+ */
+
+class VEML6040 
+{
+public:
+ /**
+ *  constructor
+ *
+ * @param i2c Pointer of the I2C object
+ * @param addr address of the I2C peripheral
+ */
+ VEML6040(I2C *i2c, int addr) ;
+ 
+ /**
+  * destructor
+  */
+ ~VEML6040() ;
+
+/**
+ * get Red
+ * @param none
+ * @returns float value of Red
+ */
+float getR(void) ; // return float value of Red
+
+/**
+ * get Green
+ * @param none
+ * @returns float value of Green
+ */
+float getG(void) ; // return float value of Green
+
+/**
+ * get Blue
+ * @param none
+ * @returns float value of Blue
+ */
+float getB(void) ; // return float value of Blue
+
+/**
+ * get White
+ * @param none
+ * @returns float value of White
+ */
+float getW(void) ; // return float value of White
+
+/**
+ * get CCT(McCAMY FORMULA) value X
+ * @param none
+ * @returns float CCT value X
+ */
+float getX(void) ; // return float value of X
+
+/** 
+ * get CCT(McCAMY FOMULA) value Y
+ * @param none
+ * @returns float CCT value Y
+ */
+float getY(void) ; // return float value of Y
+
+/**
+ * get CCT(McCAMY FOMULA) value Z
+ * @param none
+ * @returns float CCT value Z
+ */
+float getZ(void) ; // return float value of Z
+
+/**
+ * get CIE1931 X
+ * @param none
+ * @returns float CIE1931 X
+ */
+float getCIEX(void) ; // return float value of CIE1931_x
+
+/**
+ * get CIE1931 Y
+ * @param none
+ * @returns float CIE1931 Y
+ */
+float getCIEY(void) ; // return float value of CIE1931_y
+
+/**
+ * get color config data
+ * @param *colorconf uint8_t 
+ * @reutns 0: success non-0: failure
+ */
+int getCOLORConf(uint8_t *colorconf) ;
+
+/**
+ * set color config data
+ * @param *colorconf uint8_t
+ * @returns 0: success non-0: failure
+ */
+int setCOLORConf(uint8_t colorconf) ;
+
+/**
+ * get raw Red data
+ * @param uint16_t *rdata 
+ * @returns i2c status 0: success non-0: failure
+ */
+int getRData(uint16_t *rdata) ;
+
+/**
+ * get raw Green data
+ * @param uint16_t *gdata
+ * @returns i2c status 0: success non-0: failure
+ */
+int getGData(uint16_t *gdata) ;
+
+/**
+ * get raw Blue data
+ * @param uint16_t *bdata
+ * @returns i2c status 0: success non-0: failure
+ */
+int getBData(uint16_t *bdata) ;
+
+/**
+ * get raw White data
+ * @param uint16_t *wdata
+ * @returns i2c status 0: success non-0: failure
+ */
+int getWData(uint16_t *wdata) ;
+
+// void getCCTiData(uint16_t *cctidata) ;
+/**
+ * get CCTi data for CCT (EMPIRICAL APPROACH)
+ * @param none
+ * @returns float CCTi data
+ */ 
+float getCCTiData(void) ;
+// void getCCTData(uint16_t *cctdata) ;
+
+/**
+ * get CCT data (EMPIRICAL APPROACH)
+ * @param none
+ * @returns float CCD data
+ */
+float getCCTData(void) ;
+  
+private:
+  I2C *p_i2c;
+  int m_addr;
+  int readRegs(int addr, uint8_t * data, int len);
+  int writeRegs(uint8_t * data, int len);
+} ;
+#endif /* _VEML6040_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vt100.lib	Fri Apr 13 04:19:23 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Rhyme/code/vt100/#b7229a9eae1c