Gas Pressure Display Updated Power control for Pressure sensor added
Dependencies: UniGraphic mbed vt100
Revision 0:37c8ecde13c2, committed 2018-02-16
- Comitter:
- Rhyme
- Date:
- Fri Feb 16 08:27:50 2018 +0000
- Commit message:
- control PSE530 power via PTC5 (pse530_en)
Changed in this revision
diff -r 000000000000 -r 37c8ecde13c2 UniGraphic.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UniGraphic.lib Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/teams/La-Suno/code/UniGraphic/#1a148973febe
diff -r 000000000000 -r 37c8ecde13c2 afLib/Command.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/afLib/Command.cpp Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,264 @@ +/** + * 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" +#include "DebugIO.hpp" + +#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() { + 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); + } + SERIAL_PRINT_DBG_ASR("%s\n",_printBuf); +} + +void Command::dump() { + _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); + } + } + SERIAL_PRINT_DBG_ASR("%s\n",_printBuf); +} + +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); + + SERIAL_PRINT_DBG_ASR("bad hex char: %c\n",c); + + return 0; +}
diff -r 000000000000 -r 37c8ecde13c2 afLib/Command.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/afLib/Command.h Fri Feb 16 08:27:50 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__
diff -r 000000000000 -r 37c8ecde13c2 afLib/StatusCommand.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/afLib/StatusCommand.cpp Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,133 @@ +/** + * 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" + +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() { + int len = getSize(); + int bytes[len]; + getBytes(bytes); + + SERIAL_PRINT_DBG_ASR("len : %d\n",len); + SERIAL_PRINT_DBG_ASR("data : "); + for (int i = 0; i < len; i++) { + if (i > 0) { + SERIAL_PRINT_DBG_ASR(", "); + } + int b = bytes[i] & 0xff; + if (b < 0x10) { + SERIAL_PRINT_DBG_ASR("0x%08x",b); + } else { + SERIAL_PRINT_DBG_ASR("0x%08x",b); + } + } + SERIAL_PRINT_DBG_ASR("\n"); +} + +void StatusCommand::dump() { + SERIAL_PRINT_DBG_ASR("cmd : %s\n",_cmd == 0x30 ? "STATUS" : "STATUS_ACK"); + SERIAL_PRINT_DBG_ASR("bytes to send : %d\n",_bytesToSend); + SERIAL_PRINT_DBG_ASR("bytes to receive : %d\n",_bytesToRecv); +} +
diff -r 000000000000 -r 37c8ecde13c2 afLib/StatusCommand.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/afLib/StatusCommand.h Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,68 @@ +/** + * 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" +#include "DebugIO.hpp" + +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__
diff -r 000000000000 -r 37c8ecde13c2 afLib/afErrors.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/afLib/afErrors.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 afLib/afLib.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/afLib/afLib.cpp Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,957 @@ +/** + * 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); + SERIAL_PRINT_DBG_ASR("afLib init done!!\n"); +} +//wsugi 20161128 +afLib::~afLib() +{ + SERIAL_PRINT_DBG_ASR("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: + SERIAL_PRINT_DBG_ASR("%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()) { + SERIAL_PRINT_DBG_ASR("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()) { + SERIAL_PRINT_DBG_ASR("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()) { + SERIAL_PRINT_DBG_ASR("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) { + SERIAL_PRINT_DBG_ASR("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) { + SERIAL_PRINT_DBG_ASR("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) { + SERIAL_PRINT_DBG_ASR("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) { + SERIAL_PRINT_DBG_ASR("%s\n",label); + for (int i = 0; i < len; i++) { + if (i > 0) { + SERIAL_PRINT_DBG_ASR(", "); + } + uint8_t b = bytes[i] & 0xff; + + if (b < 0x10) { + SERIAL_PRINT_DBG_ASR("0x02x", b); + } else { + //_theLog->print("0x"); + SERIAL_PRINT_DBG_ASR("0x02x",b);//, HEX); + } + } + SERIAL_PRINT_DBG_ASR("\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: + SERIAL_PRINT_DBG_ASR("STATE_IDLE\n"); + break; + case STATE_STATUS_SYNC: + SERIAL_PRINT_DBG_ASR("STATE_STATUS_SYNC\n"); + break; + case STATE_STATUS_ACK: + SERIAL_PRINT_DBG_ASR("STATE_STATUS_ACK\n"); + break; + case STATE_SEND_BYTES: + SERIAL_PRINT_DBG_ASR("STATE_SEND_BYTES\n"); + break; + case STATE_RECV_BYTES: + SERIAL_PRINT_DBG_ASR("STATE_RECV_BYTES\n"); + break; + case STATE_CMD_COMPLETE: + SERIAL_PRINT_DBG_ASR("STATE_CMD_COMPLETE\n"); + break; + default: + SERIAL_PRINT_DBG_ASR("Unknown State!\n"); + break; + } +} + +void afLib::printTransaction(uint8_t *rbytes, int len) +{ + //return; + int i = 0; + for(;i<=len;++i) + { + SERIAL_PRINT_DBG_ASR("0x%02x:",rbytes[i]); + } + SERIAL_PRINT_DBG_ASR("\n"); +} \ No newline at end of file
diff -r 000000000000 -r 37c8ecde13c2 afLib/afLib.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/afLib/afLib.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 afLib/afSPI.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/afLib/afSPI.h Fri Feb 16 08:27:50 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 +
diff -r 000000000000 -r 37c8ecde13c2 afLib/iafLib.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/afLib/iafLib.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 afLib/msg_types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/afLib/msg_types.h Fri Feb 16 08:27:50 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__
diff -r 000000000000 -r 37c8ecde13c2 af_utils/DebugIO.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/af_utils/DebugIO.hpp Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,26 @@ +#ifndef _MARUSOL_DEBUG_IO_HPP_ +#define _MARUSOL_DEBUG_IO_HPP_ + +#if defined (TARGET_TEENSY3_1) + #include "USBSerial.h" +#else + #include "mbed.h" +#endif + +// #define SERIAL_PRINT_DBG_ON +#ifdef SERIAL_PRINT_DBG_ON + #define SERIAL_PRINT_DBG(...) (printf(__VA_ARGS__)) + #define SERIAL_PRINT_DBG_FUNCNAME() (printf("%s,%d,%s\n",__FILE__,__LINE__,__PRETTY_FUNCTION__)) +#else + #define SERIAL_PRINT_DBG(...) + #define SERIAL_PRINT_DBG_FUNCNAME() +#endif //SERIAL_PRINT_DBG_ON + +// #define SERIAL_PRINT_DBG_ASR_ON +#ifdef SERIAL_PRINT_DBG_ASR_ON + #define SERIAL_PRINT_DBG_ASR(...) (printf(__VA_ARGS__)) +#else + #define SERIAL_PRINT_DBG_ASR(...) +#endif //SERIAL_PRINT_DBG_ASR_ON + +#endif //_MARUSOL_DEBUG_IO_HPP_ \ No newline at end of file
diff -r 000000000000 -r 37c8ecde13c2 af_utils/af_attriburtes.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/af_utils/af_attriburtes.cpp Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,685 @@ +#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[0]) { + if (value[0]) { + sensor[0]->reset() ; + sensor[0]->enable() ; + } else if (sensor[0]){ + sensor[0]->disable() ; + } + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_ACCEL_INTERVAL: + if (sensor[0]) { + sensor[0]->setInterval((value[1] << 8) | value[0]) ; + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_COLOR0_ENABLE: /* color0 enable */ + if (sensor[1]) { + if (value[0]) { + sensor[1]->reset() ; + sensor[1]->enable() ; + } else { + sensor[1]->disable() ; + } + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_COLOR0_INTERVAL: + if (sensor[1]) { + sensor[1]->setInterval((value[1] << 8) | value[0]) ; + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_COLOR0_TRIGMODE: /* color0 config */ + if (sensor[1]) { + uint8_t config = ((edge_color*)sensor[1])->getConfig() & 0x70 ; + if (value[0]) { + config = config | 0x06 ; + } + ((edge_color*)sensor[1])->setConfig(config) ; + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_COLOR0_ITIME: /* color0 config */ + if (sensor[1]) { + uint8_t config = ((edge_color*)sensor[1])->getConfig() & 0x07 ; + config = (value[0] << 4) | config ; + ((edge_color*)sensor[1])->setConfig(config) ; + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_COLOR0_PWM_PERIOD: /* color0 pwm period */ + if (sensor[1]) { + ((edge_color*)sensor[1])->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[1]) { + 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[1] && value[0] && fromRequest) { /* do calibration */ + ((edge_color*)sensor[1])->request_calibration() ; + } + break ; +#endif + case ATTR_COLOR0_PWM_R: + if (sensor[1]) { + ((edge_color*)sensor[1])->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[1]) { + ((edge_color*)sensor[1])->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[1]) { + ((edge_color*)sensor[1])->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[2]) { + if (value[0]) { + sensor[2]->reset() ; + sensor[2]->enable() ; + } else { + sensor[2]->disable() ; + } + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_COLOR1_INTERVAL: + if (sensor[2]) { + sensor[2]->setInterval((value[1] << 8) | value[0]) ; + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_COLOR1_TRIGMODE: /* color0 config */ + if (sensor[2]) { + uint8_t config = ((edge_color*)sensor[2])->getConfig() & 0x70 ; + if (value[0]) { + config = config | 0x06 ; + } + ((edge_color*)sensor[2])->setConfig(config) ; + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_COLOR1_ITIME: /* color0 config */ + if (sensor[2]) { + uint8_t config = ((edge_color*)sensor[2])->getConfig() & 0x07 ; + config = (value[0] << 4) | config ; + ((edge_color*)sensor[2])->setConfig(config) ; + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_COLOR1_PWM_PERIOD: /* color0 pwm period */ + if (sensor[2]) { + ((edge_color*)sensor[2])->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[2]) { + 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[2] && value[0] && fromRequest) { /* do calibration! */ + ((edge_color*)sensor[2])->request_calibration() ; + } + break ; +#endif + case ATTR_COLOR1_PWM_R: + if (sensor[2]) { + ((edge_color*)sensor[2])->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[2]) { + ((edge_color*)sensor[2])->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[2]) { + ((edge_color*)sensor[2])->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[3]) { + if (value[0]) { + sensor[3]->reset() ; + sensor[3]->enable() ; + } else { + sensor[3]->disable() ; + } + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_TEMP0_INTERVAL: + if (sensor[3]) { + sensor[3]->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[4]) { + if (value[0]) { + sensor[4]->reset() ; + sensor[4]->enable() ; + } else { + sensor[4]->disable() ; + } + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_GAS_INTERVAL: + if (sensor[4]) { + sensor[4]->setInterval((value[1] << 8) | value[0]) ; + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_GAS_THR_MODE: + if (sensor[4]) { + ((edge_pressure*)sensor[4])->set_thr_mode(value[0]) ; + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_GAS_THR_HIGH: + if (sensor[4]) { + ((edge_pressure*)sensor[4])->set_thr_high((value[1] << 8) | value[0]) ; + if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ; + } + break ; + case ATTR_GAS_THR_LOW: + if (sensor[4]) { + ((edge_pressure*)sensor[4])->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 ; + } + 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) { + 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
diff -r 000000000000 -r 37c8ecde13c2 af_utils/af_attributes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/af_utils/af_attributes.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 af_utils/af_mgr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/af_utils/af_mgr.cpp Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 af_utils/af_mgr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/af_utils/af_mgr.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 af_utils/mbedSPI.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/af_utils/mbedSPI.cpp Fri Feb 16 08:27:50 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 + } +} +
diff -r 000000000000 -r 37c8ecde13c2 af_utils/mbedSPI.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/af_utils/mbedSPI.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 af_utils/pending.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/af_utils/pending.cpp Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 af_utils/pending.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/af_utils/pending.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_sensor/edge_accel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_sensor/edge_accel.cpp Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_sensor/edge_accel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_sensor/edge_accel.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_sensor/edge_color.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_sensor/edge_color.cpp Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,421 @@ +#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 ; + + 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") ; + } + _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 ; + + 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") ; + } + _calibration_request = 0 ; + _status = EDGE_SENSOR_INACTIVE ; +reset_watch_dog() ; +} +#endif /* calibration double version */
diff -r 000000000000 -r 37c8ecde13c2 edge_sensor/edge_color.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_sensor/edge_color.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_sensor/edge_pressure.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_sensor/edge_pressure.cpp Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,319 @@ +#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(40) ; + _value = get_value() ; + *_en = 0 ; /* disable pressure sensor */ + _sampled_time = edge_time ; + 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->max - p->min)) ; + return( y ) ; +} + +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 ; + 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 ; + } else if (_value < _lower) { + sprintf(str_buf, "LOW") ; + color = Yellow ; + } else { + sprintf(str_buf, "GOOD") ; + color = Green ; + } + 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->fillcircle(c, 75, 10, White) ; + + /* print status */ + display->locate(30, 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() ; +}
diff -r 000000000000 -r 37c8ecde13c2 edge_sensor/edge_pressure.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_sensor/edge_pressure.h Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,109 @@ +#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) ; + +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
diff -r 000000000000 -r 37c8ecde13c2 edge_sensor/edge_sensor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_sensor/edge_sensor.cpp Fri Feb 16 08:27:50 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) { // initail 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 0: printf("Accel (MMA8451Q) ") ; break ; + case 1: printf("Color1 (VEML6040) ") ; break ; + case 2: printf("Color2 (VEML6040) ") ; break ; + case 3: printf("Temp (LM75B) ") ; break ; + case 4: 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) ; +} +
diff -r 000000000000 -r 37c8ecde13c2 edge_sensor/edge_sensor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_sensor/edge_sensor.h Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,148 @@ +#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) ; + +/** + * 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 + +/* 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
diff -r 000000000000 -r 37c8ecde13c2 edge_sensor/edge_temp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_sensor/edge_temp.cpp Fri Feb 16 08:27:50 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->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() ; +} +
diff -r 000000000000 -r 37c8ecde13c2 edge_sensor/edge_temp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_sensor/edge_temp.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_utils/KL25Z_SystemInit.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_utils/KL25Z_SystemInit.c Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_utils/edge_chart.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_utils/edge_chart.cpp Fri Feb 16 08:27:50 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", 0, 120, 160, 120, 0, 0.0, 10000.0 }, + { "Color2", 160, 120, 160, 120, 0, 0.0, 10000.0 }, + { "Temp", 160, 0, 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
diff -r 000000000000 -r 37c8ecde13c2 edge_utils/edge_chart.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_utils/edge_chart.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_utils/edge_mgr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_utils/edge_mgr.cpp Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,517 @@ +#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 ; + +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 = 1 ; + if ((sensor[sensor_index])&&(sensor[sensor_index]->isEnabled())) { + switch(sensor_index) { + case 1: /* color0 */ + if (((edge_color*)sensor[1])->calibration_requested()) { + ((edge_color*)sensor[1])->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 2: /* color1 */ + if (((edge_color*)sensor[2])->calibration_requested()) { + ((edge_color*)sensor[2])->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->cls() ; + 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->set_font_zoom(3, 3) ; + display->locate(30, 100) ; + display->foreground(Red) ; + display->printf("Preparing...") ; + display->BusEnable(true) ; +// display->fillrect(200,50,250, 150, Green) ; + 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) ; +// 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[0] = accel ; + num_sensor++ ; + } else { + sensor[0] = 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[1] = color[0] ; + num_sensor++ ; + } else { + sensor[1] = 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[2] = color[1] ; + num_sensor++ ; + } else { + sensor[2] = 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[3] = 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[4] = pressure ; + 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
diff -r 000000000000 -r 37c8ecde13c2 edge_utils/edge_mgr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_utils/edge_mgr.h Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,29 @@ +#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 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
diff -r 000000000000 -r 37c8ecde13c2 edge_utils/edge_pin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_utils/edge_pin.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_utils/edge_reset_mgr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_utils/edge_reset_mgr.cpp Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_utils/edge_reset_mgr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_utils/edge_reset_mgr.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_utils/edge_time.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_utils/edge_time.cpp Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 edge_utils/edge_time.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/edge_utils/edge_time.h Fri Feb 16 08:27:50 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_ */
diff -r 000000000000 -r 37c8ecde13c2 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Feb 16 08:27:50 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) ; + } +}
diff -r 000000000000 -r 37c8ecde13c2 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/7130f322cb7e \ No newline at end of file
diff -r 000000000000 -r 37c8ecde13c2 sensors/LM75B.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors/LM75B.cpp Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 sensors/LM75B.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors/LM75B.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 sensors/MMA8451Q.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors/MMA8451Q.cpp Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 sensors/MMA8451Q.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors/MMA8451Q.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 sensors/PSE530.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors/PSE530.cpp Fri Feb 16 08:27:50 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 ) ; +}
diff -r 000000000000 -r 37c8ecde13c2 sensors/PSE530.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors/PSE530.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 sensors/SMTC502AT.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors/SMTC502AT.cpp Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 sensors/SMTC502AT.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors/SMTC502AT.h Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 sensors/VEML6040.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors/VEML6040.cpp Fri Feb 16 08:27:50 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
diff -r 000000000000 -r 37c8ecde13c2 sensors/VEML6040.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensors/VEML6040.h Fri Feb 16 08:27:50 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_ */
diff -r 000000000000 -r 37c8ecde13c2 vt100.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vt100.lib Fri Feb 16 08:27:50 2018 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/Rhyme/code/vt100/#b7229a9eae1c