Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: UniGraphic mbed vt100
Revision 0:846e2321c637, committed 2018-04-13
- 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
--- /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(¤t_time) ;
+// print_time(¤t_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, ¤t_time) ; /* 12 us */
+ if (verbos) {
+ print_time(¤t_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, ¤t_time) ; /* 12us */
+ if (verbos) {
+ print_time(¤t_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(¤t_time) ;
+// print_time(¤t_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, ×truct) ;
+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, ¤t_time) ;
+// ts2time(edge_time, ¤t_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, ×truct) ;
+ print_time(×truct) ;
+}
+
+void print_time(void)
+{
+ struct tm timestruct ;
+ ts2time(edge_time, ×truct) ;
+ print_time(×truct) ;
+}
+
+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, ×truct) ;
+ time2str(×truct, timestr) ;
+}
+
+int32_t time2seq(uint32_t timestamp)
+{
+ struct tm timestruct ;
+ int32_t result ;
+ ts2time(timestamp, ×truct) ;
+ 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, ×truct) ;
+ 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