![](/media/cache/group/1711.jpg.50x50_q85.jpg)
Release candidate version. The pointer in GAS Pressure display is changed to a triangle.
Dependencies: UniGraphic mbed vt100
Please note, at 2-Mar-2018 the current version of mbed-lib has a defect in Ticker.
https://os.mbed.com/forum/bugs-suggestions/topic/29287/
So, mbed lib version 157 is intentionally being used.
Please do not update mbed library until the problem in the above URL is fixed.
In this version, format of GAS Pressure Display has been changed.
moto
Revision 0:774324cbc5a6, committed 2018-03-02
- Comitter:
- Rhyme
- Date:
- Fri Mar 02 07:56:09 2018 +0000
- Commit message:
- Release candidate version. GAS Pressure pointer is now a triangle.; Some source file clean-up was done.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UniGraphic.lib Fri Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 2018 +0000 @@ -0,0 +1,692 @@ +#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) ; + } + } + 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 2018 +0000 @@ -0,0 +1,520 @@ +#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 ; + +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 ; + +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)) ; +} + +void init_sensors(void) +{ + printf("=== Initializing Sensor(s) ===\n") ; + edge_i2c0 = new I2C(PIN_I2C0_SDA, PIN_I2C0_SCL) ; + 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 Mar 02 07:56:09 2018 +0000 @@ -0,0 +1,30 @@ +#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) ; + +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 Mar 02 07:56:09 2018 +0000 @@ -0,0 +1,37 @@ +#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 +#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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 2018 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 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 Mar 02 07:56:09 2018 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/Rhyme/code/vt100/#b7229a9eae1c