Release candidate version. The pointer in GAS Pressure display is changed to a triangle.

Dependencies:   UniGraphic mbed vt100

Please note, at 2-Mar-2018 the current version of mbed-lib has a defect in Ticker.
https://os.mbed.com/forum/bugs-suggestions/topic/29287/

So, mbed lib version 157 is intentionally being used.
Please do not update mbed library until the problem in the above URL is fixed.

In this version, format of GAS Pressure Display has been changed.
/media/uploads/Rhyme/low.jpg

/media/uploads/Rhyme/good.jpg

/media/uploads/Rhyme/high.jpg

moto

Committer:
Rhyme
Date:
Fri Mar 02 07:56:09 2018 +0000
Revision:
0:774324cbc5a6
Release candidate version. GAS Pressure pointer is now a triangle.; Some source file clean-up was done.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Rhyme 0:774324cbc5a6 1 /**
Rhyme 0:774324cbc5a6 2 * Copyright 2015 Afero, Inc.
Rhyme 0:774324cbc5a6 3 *
Rhyme 0:774324cbc5a6 4 * Licensed under the Apache License, Version 2.0 (the "License");
Rhyme 0:774324cbc5a6 5 * you may not use this file except in compliance with the License.
Rhyme 0:774324cbc5a6 6 * You may obtain a copy of the License at
Rhyme 0:774324cbc5a6 7 *
Rhyme 0:774324cbc5a6 8 * http://www.apache.org/licenses/LICENSE-2.0
Rhyme 0:774324cbc5a6 9 *
Rhyme 0:774324cbc5a6 10 * Unless required by applicable law or agreed to in writing, software
Rhyme 0:774324cbc5a6 11 * distributed under the License is distributed on an "AS IS" BASIS,
Rhyme 0:774324cbc5a6 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Rhyme 0:774324cbc5a6 13 * See the License for the specific language governing permissions and
Rhyme 0:774324cbc5a6 14 * limitations under the License.
Rhyme 0:774324cbc5a6 15 */
Rhyme 0:774324cbc5a6 16
Rhyme 0:774324cbc5a6 17 #include "mbed.h"
Rhyme 0:774324cbc5a6 18 #include "afLib.h"
Rhyme 0:774324cbc5a6 19 #include "afErrors.h"
Rhyme 0:774324cbc5a6 20 #include "msg_types.h"
Rhyme 0:774324cbc5a6 21 /* added by Motoo Tanaka on 26-Dec-2017 for watchdog */
Rhyme 0:774324cbc5a6 22 #include "edge_reset_mgr.h"
Rhyme 0:774324cbc5a6 23
Rhyme 0:774324cbc5a6 24 #define IS_MCU_ATTR(x) (x >= 0 && x < 1024)
Rhyme 0:774324cbc5a6 25
Rhyme 0:774324cbc5a6 26 static iafLib *_iaflib = NULL;
Rhyme 0:774324cbc5a6 27
Rhyme 0:774324cbc5a6 28 #define MAX_SYNC_RETRIES 10
Rhyme 0:774324cbc5a6 29 static long lastSync = 0;
Rhyme 0:774324cbc5a6 30 static int syncRetries = 0;
Rhyme 0:774324cbc5a6 31
Rhyme 0:774324cbc5a6 32 /**
Rhyme 0:774324cbc5a6 33 * create
Rhyme 0:774324cbc5a6 34 *
Rhyme 0:774324cbc5a6 35 * The public constructor for the afLib. This allows us to create the afLib object once and hold a reference to it.
Rhyme 0:774324cbc5a6 36 */
Rhyme 0:774324cbc5a6 37 iafLib *iafLib::create(PinName mcuInterrupt, isr isrWrapper,
Rhyme 0:774324cbc5a6 38 onAttributeSet attrSet, onAttributeSetComplete attrSetComplete, afSPI *theSPI)
Rhyme 0:774324cbc5a6 39 {
Rhyme 0:774324cbc5a6 40 if (_iaflib == NULL) {
Rhyme 0:774324cbc5a6 41 _iaflib = new afLib( mcuInterrupt, isrWrapper, attrSet, attrSetComplete, theSPI);
Rhyme 0:774324cbc5a6 42 }
Rhyme 0:774324cbc5a6 43
Rhyme 0:774324cbc5a6 44 return _iaflib;
Rhyme 0:774324cbc5a6 45 }
Rhyme 0:774324cbc5a6 46
Rhyme 0:774324cbc5a6 47 void iafLib::destroy()
Rhyme 0:774324cbc5a6 48 {
Rhyme 0:774324cbc5a6 49 afLib *p = (afLib*)_iaflib;
Rhyme 0:774324cbc5a6 50 delete p;
Rhyme 0:774324cbc5a6 51 _iaflib = NULL;
Rhyme 0:774324cbc5a6 52 }
Rhyme 0:774324cbc5a6 53
Rhyme 0:774324cbc5a6 54 /**
Rhyme 0:774324cbc5a6 55 * getRequestId
Rhyme 0:774324cbc5a6 56 * by Motoo Tanaka on 16-Nov-2017
Rhyme 0:774324cbc5a6 57 */
Rhyme 0:774324cbc5a6 58 int afLib::getRequestId(void)
Rhyme 0:774324cbc5a6 59 {
Rhyme 0:774324cbc5a6 60 return( _requestId ) ;
Rhyme 0:774324cbc5a6 61 }
Rhyme 0:774324cbc5a6 62
Rhyme 0:774324cbc5a6 63 /**
Rhyme 0:774324cbc5a6 64 * afLib
Rhyme 0:774324cbc5a6 65 *
Rhyme 0:774324cbc5a6 66 * The private constructor for the afLib. This one actually initializes the afLib and prepares it for use.
Rhyme 0:774324cbc5a6 67 */
Rhyme 0:774324cbc5a6 68 afLib::afLib(PinName mcuInterrupt, isr isrWrapper,
Rhyme 0:774324cbc5a6 69 onAttributeSet attrSet, onAttributeSetComplete attrSetComplete, afSPI *theSPI) : fco(mcuInterrupt)
Rhyme 0:774324cbc5a6 70 {
Rhyme 0:774324cbc5a6 71 checkLastSync = new Timer();
Rhyme 0:774324cbc5a6 72 checkLastSync->start();
Rhyme 0:774324cbc5a6 73 queueInit();
Rhyme 0:774324cbc5a6 74 _theSPI= theSPI;
Rhyme 0:774324cbc5a6 75 _request.p_value = NULL;
Rhyme 0:774324cbc5a6 76
Rhyme 0:774324cbc5a6 77 //_spiSettings = SPISettings(1000000, LSBFIRST, SPI_MODE0);
Rhyme 0:774324cbc5a6 78 _interrupts_pending = 0;
Rhyme 0:774324cbc5a6 79 _state = STATE_IDLE;
Rhyme 0:774324cbc5a6 80
Rhyme 0:774324cbc5a6 81 _writeCmd = NULL;
Rhyme 0:774324cbc5a6 82 _writeCmdOffset = 0;
Rhyme 0:774324cbc5a6 83
Rhyme 0:774324cbc5a6 84 _outstandingSetGetAttrId = 0;
Rhyme 0:774324cbc5a6 85
Rhyme 0:774324cbc5a6 86 _readCmd = NULL;
Rhyme 0:774324cbc5a6 87 _readCmdOffset = 0;
Rhyme 0:774324cbc5a6 88 _readBufferLen = 0;
Rhyme 0:774324cbc5a6 89
Rhyme 0:774324cbc5a6 90 _txStatus = new StatusCommand();
Rhyme 0:774324cbc5a6 91 _rxStatus = new StatusCommand();
Rhyme 0:774324cbc5a6 92
Rhyme 0:774324cbc5a6 93 _onAttrSet = attrSet;
Rhyme 0:774324cbc5a6 94 _onAttrSetComplete = attrSetComplete;
Rhyme 0:774324cbc5a6 95 _theSPI->begin();
Rhyme 0:774324cbc5a6 96
Rhyme 0:774324cbc5a6 97 // AJS where does this get moved to??
Rhyme 0:774324cbc5a6 98 #ifdef ARDUINO
Rhyme 0:774324cbc5a6 99 pinMode(mcuInterrupt, INPUT);
Rhyme 0:774324cbc5a6 100 attachInterrupt(mcuInterrupt, isrWrapper, FALLING);
Rhyme 0:774324cbc5a6 101 #endif
Rhyme 0:774324cbc5a6 102 fco.fall(isrWrapper);
Rhyme 0:774324cbc5a6 103 printf("afLib init done!!\n");
Rhyme 0:774324cbc5a6 104 }
Rhyme 0:774324cbc5a6 105 //wsugi 20161128
Rhyme 0:774324cbc5a6 106 afLib::~afLib()
Rhyme 0:774324cbc5a6 107 {
Rhyme 0:774324cbc5a6 108 printf("deleted\n");
Rhyme 0:774324cbc5a6 109 if(_readBuffer != NULL)
Rhyme 0:774324cbc5a6 110 {
Rhyme 0:774324cbc5a6 111 delete[] (_readBuffer);
Rhyme 0:774324cbc5a6 112 _readBuffer = NULL;
Rhyme 0:774324cbc5a6 113 }
Rhyme 0:774324cbc5a6 114
Rhyme 0:774324cbc5a6 115 if(_writeBuffer != NULL)
Rhyme 0:774324cbc5a6 116 {
Rhyme 0:774324cbc5a6 117 delete[] (_writeBuffer);
Rhyme 0:774324cbc5a6 118 _writeBuffer = NULL;
Rhyme 0:774324cbc5a6 119 }
Rhyme 0:774324cbc5a6 120
Rhyme 0:774324cbc5a6 121 if(_readCmd != NULL)
Rhyme 0:774324cbc5a6 122 {
Rhyme 0:774324cbc5a6 123 delete (_readCmd);
Rhyme 0:774324cbc5a6 124 _readCmd = NULL;
Rhyme 0:774324cbc5a6 125 }
Rhyme 0:774324cbc5a6 126
Rhyme 0:774324cbc5a6 127 if(_writeCmd != NULL)
Rhyme 0:774324cbc5a6 128 {
Rhyme 0:774324cbc5a6 129 delete (_writeCmd);
Rhyme 0:774324cbc5a6 130 _writeCmd = NULL;
Rhyme 0:774324cbc5a6 131 }
Rhyme 0:774324cbc5a6 132
Rhyme 0:774324cbc5a6 133 if(_txStatus != NULL)
Rhyme 0:774324cbc5a6 134 {
Rhyme 0:774324cbc5a6 135 delete (_txStatus);
Rhyme 0:774324cbc5a6 136 _txStatus = NULL;
Rhyme 0:774324cbc5a6 137 }
Rhyme 0:774324cbc5a6 138
Rhyme 0:774324cbc5a6 139 if(_rxStatus != NULL)
Rhyme 0:774324cbc5a6 140 {
Rhyme 0:774324cbc5a6 141 delete (_rxStatus);
Rhyme 0:774324cbc5a6 142 _rxStatus = NULL;
Rhyme 0:774324cbc5a6 143 }
Rhyme 0:774324cbc5a6 144
Rhyme 0:774324cbc5a6 145 for (int i = 0; i < REQUEST_QUEUE_SIZE; i++)
Rhyme 0:774324cbc5a6 146 {
Rhyme 0:774324cbc5a6 147 if (_requestQueue[i].p_value != NULL)
Rhyme 0:774324cbc5a6 148 {
Rhyme 0:774324cbc5a6 149 delete[] (_requestQueue[i].p_value);
Rhyme 0:774324cbc5a6 150 _requestQueue[i].p_value = NULL;
Rhyme 0:774324cbc5a6 151 }
Rhyme 0:774324cbc5a6 152 }
Rhyme 0:774324cbc5a6 153
Rhyme 0:774324cbc5a6 154 if(checkLastSync != NULL)
Rhyme 0:774324cbc5a6 155 {
Rhyme 0:774324cbc5a6 156 delete (checkLastSync);
Rhyme 0:774324cbc5a6 157 checkLastSync = NULL;
Rhyme 0:774324cbc5a6 158 }
Rhyme 0:774324cbc5a6 159
Rhyme 0:774324cbc5a6 160 _iaflib = NULL;
Rhyme 0:774324cbc5a6 161 }
Rhyme 0:774324cbc5a6 162 //wsugi 20161128
Rhyme 0:774324cbc5a6 163 /**
Rhyme 0:774324cbc5a6 164 * loop
Rhyme 0:774324cbc5a6 165 *
Rhyme 0:774324cbc5a6 166 * This is how the afLib gets time to run its state machine. This method should be called periodically from the
Rhyme 0:774324cbc5a6 167 * loop() function of the Arduino sketch.
Rhyme 0:774324cbc5a6 168 * This function pulls pending attribute operations from the queue. It takes approximately 4 calls to loop() to
Rhyme 0:774324cbc5a6 169 * complete one attribute operation.
Rhyme 0:774324cbc5a6 170 */
Rhyme 0:774324cbc5a6 171 void afLib::loop(void) {
Rhyme 0:774324cbc5a6 172 reset_watch_dog() ; /* 26-Dec-2017 by Motoo Tanaka */
Rhyme 0:774324cbc5a6 173 if (isIdle() && (queueGet(&_request.messageType, &_request.requestId, &_request.attrId, &_request.valueLen,
Rhyme 0:774324cbc5a6 174 &_request.p_value) == afSUCCESS)) {
Rhyme 0:774324cbc5a6 175 switch (_request.messageType) {
Rhyme 0:774324cbc5a6 176 case MSG_TYPE_GET:
Rhyme 0:774324cbc5a6 177 doGetAttribute(_request.requestId, _request.attrId);
Rhyme 0:774324cbc5a6 178 break;
Rhyme 0:774324cbc5a6 179
Rhyme 0:774324cbc5a6 180 case MSG_TYPE_SET:
Rhyme 0:774324cbc5a6 181 doSetAttribute(_request.requestId, _request.attrId, _request.valueLen, _request.p_value);
Rhyme 0:774324cbc5a6 182 break;
Rhyme 0:774324cbc5a6 183
Rhyme 0:774324cbc5a6 184 case MSG_TYPE_UPDATE:
Rhyme 0:774324cbc5a6 185 doUpdateAttribute(_request.requestId, _request.attrId, 0, _request.valueLen, _request.p_value);
Rhyme 0:774324cbc5a6 186 break;
Rhyme 0:774324cbc5a6 187
Rhyme 0:774324cbc5a6 188 default:
Rhyme 0:774324cbc5a6 189 printf("%s\n","loop: request type!");
Rhyme 0:774324cbc5a6 190 }
Rhyme 0:774324cbc5a6 191 }
Rhyme 0:774324cbc5a6 192
Rhyme 0:774324cbc5a6 193 if (_request.p_value != NULL) {
Rhyme 0:774324cbc5a6 194 delete[] (_request.p_value); //wsugi delete (_request.p_value);
Rhyme 0:774324cbc5a6 195 _request.p_value = NULL;
Rhyme 0:774324cbc5a6 196 }
Rhyme 0:774324cbc5a6 197 runStateMachine();
Rhyme 0:774324cbc5a6 198 }
Rhyme 0:774324cbc5a6 199
Rhyme 0:774324cbc5a6 200 /**
Rhyme 0:774324cbc5a6 201 * updateIntsPending
Rhyme 0:774324cbc5a6 202 *
Rhyme 0:774324cbc5a6 203 * Interrupt-safe method for updating the interrupt count. This is called to increment and decrement the interrupt count
Rhyme 0:774324cbc5a6 204 * as interrupts are received and handled.
Rhyme 0:774324cbc5a6 205 */
Rhyme 0:774324cbc5a6 206 void afLib::updateIntsPending(int amount) {
Rhyme 0:774324cbc5a6 207 // fco.disable_irq();
Rhyme 0:774324cbc5a6 208 __disable_irq() ; // Disable Interrupts
Rhyme 0:774324cbc5a6 209 _interrupts_pending += amount;
Rhyme 0:774324cbc5a6 210 __enable_irq() ; // Enable Interrupts
Rhyme 0:774324cbc5a6 211 // fco.enable_irq();
Rhyme 0:774324cbc5a6 212 }
Rhyme 0:774324cbc5a6 213
Rhyme 0:774324cbc5a6 214 /**
Rhyme 0:774324cbc5a6 215 * sendCommand
Rhyme 0:774324cbc5a6 216 *
Rhyme 0:774324cbc5a6 217 * This increments the interrupt count to kick off the state machine in the next call to loop().
Rhyme 0:774324cbc5a6 218 */
Rhyme 0:774324cbc5a6 219 /**
Rhyme 0:774324cbc5a6 220 * In this fucntion, only disable/enable fco irq is enough
Rhyme 0:774324cbc5a6 221 */
Rhyme 0:774324cbc5a6 222 void afLib::sendCommand(void) {
Rhyme 0:774324cbc5a6 223 fco.disable_irq();
Rhyme 0:774324cbc5a6 224 if (_interrupts_pending == 0 && _state == STATE_IDLE) {
Rhyme 0:774324cbc5a6 225 updateIntsPending(1);
Rhyme 0:774324cbc5a6 226 }
Rhyme 0:774324cbc5a6 227 fco.enable_irq();
Rhyme 0:774324cbc5a6 228 }
Rhyme 0:774324cbc5a6 229
Rhyme 0:774324cbc5a6 230 /**
Rhyme 0:774324cbc5a6 231 * getAttribute
Rhyme 0:774324cbc5a6 232 *
Rhyme 0:774324cbc5a6 233 * The public getAttribute method. This method queues the operation and returns immediately. Applications must call
Rhyme 0:774324cbc5a6 234 * loop() for the operation to complete.
Rhyme 0:774324cbc5a6 235 */
Rhyme 0:774324cbc5a6 236 int afLib::getAttribute(const uint16_t attrId) {
Rhyme 0:774324cbc5a6 237 _requestId++;
Rhyme 0:774324cbc5a6 238 uint8_t dummy; // This value isn't actually used.
Rhyme 0:774324cbc5a6 239 // return queuePut(MSG_TYPE_GET, _requestId++, attrId, 0, &dummy);
Rhyme 0:774324cbc5a6 240 return queuePut(MSG_TYPE_GET, _requestId, attrId, 0, &dummy); /* by moto on 17-Nov-2017 */
Rhyme 0:774324cbc5a6 241 }
Rhyme 0:774324cbc5a6 242
Rhyme 0:774324cbc5a6 243 /**
Rhyme 0:774324cbc5a6 244 * The many moods of setAttribute
Rhyme 0:774324cbc5a6 245 *
Rhyme 0:774324cbc5a6 246 * These are the public versions of the setAttribute method.
Rhyme 0:774324cbc5a6 247 * These methods queue the operation and return immediately. Applications must call loop() for the operation to complete.
Rhyme 0:774324cbc5a6 248 */
Rhyme 0:774324cbc5a6 249 int afLib::setAttributeBool(const uint16_t attrId, const bool value) {
Rhyme 0:774324cbc5a6 250 _requestId++;
Rhyme 0:774324cbc5a6 251 uint8_t val = value ? 1 : 0;
Rhyme 0:774324cbc5a6 252 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(val),
Rhyme 0:774324cbc5a6 253 (uint8_t *)&val);
Rhyme 0:774324cbc5a6 254 }
Rhyme 0:774324cbc5a6 255
Rhyme 0:774324cbc5a6 256 int afLib::setAttribute8(const uint16_t attrId, const int8_t value) {
Rhyme 0:774324cbc5a6 257 _requestId++;
Rhyme 0:774324cbc5a6 258 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value),
Rhyme 0:774324cbc5a6 259 (uint8_t *)&value);
Rhyme 0:774324cbc5a6 260 }
Rhyme 0:774324cbc5a6 261
Rhyme 0:774324cbc5a6 262 int afLib::setAttribute16(const uint16_t attrId, const int16_t value) {
Rhyme 0:774324cbc5a6 263 _requestId++;
Rhyme 0:774324cbc5a6 264 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value),
Rhyme 0:774324cbc5a6 265 (uint8_t *) &value);
Rhyme 0:774324cbc5a6 266 }
Rhyme 0:774324cbc5a6 267
Rhyme 0:774324cbc5a6 268 int afLib::setAttribute32(const uint16_t attrId, const int32_t value) {
Rhyme 0:774324cbc5a6 269 _requestId++;
Rhyme 0:774324cbc5a6 270 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value),
Rhyme 0:774324cbc5a6 271 (uint8_t *) &value);
Rhyme 0:774324cbc5a6 272 }
Rhyme 0:774324cbc5a6 273
Rhyme 0:774324cbc5a6 274 int afLib::setAttribute64(const uint16_t attrId, const int64_t value) {
Rhyme 0:774324cbc5a6 275 _requestId++;
Rhyme 0:774324cbc5a6 276 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value),
Rhyme 0:774324cbc5a6 277 (uint8_t *) &value);
Rhyme 0:774324cbc5a6 278 }
Rhyme 0:774324cbc5a6 279
Rhyme 0:774324cbc5a6 280 int afLib::setAttribute(const uint16_t attrId, const string &value) {
Rhyme 0:774324cbc5a6 281 _requestId++;
Rhyme 0:774324cbc5a6 282 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, value.length(),
Rhyme 0:774324cbc5a6 283 (uint8_t *) value.c_str());
Rhyme 0:774324cbc5a6 284 }
Rhyme 0:774324cbc5a6 285
Rhyme 0:774324cbc5a6 286 int afLib::setAttribute(const uint16_t attrId, const uint16_t valueLen, const char *value) {
Rhyme 0:774324cbc5a6 287 if (valueLen > MAX_ATTRIBUTE_SIZE) {
Rhyme 0:774324cbc5a6 288 return afERROR_INVALID_PARAM;
Rhyme 0:774324cbc5a6 289 }
Rhyme 0:774324cbc5a6 290
Rhyme 0:774324cbc5a6 291 if (value == NULL) {
Rhyme 0:774324cbc5a6 292 return afERROR_INVALID_PARAM;
Rhyme 0:774324cbc5a6 293 }
Rhyme 0:774324cbc5a6 294
Rhyme 0:774324cbc5a6 295 _requestId++;
Rhyme 0:774324cbc5a6 296 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, valueLen,
Rhyme 0:774324cbc5a6 297 (const uint8_t *) value);
Rhyme 0:774324cbc5a6 298 }
Rhyme 0:774324cbc5a6 299
Rhyme 0:774324cbc5a6 300 int afLib::setAttribute(const uint16_t attrId, const uint16_t valueLen, const uint8_t *value) {
Rhyme 0:774324cbc5a6 301 if (valueLen > MAX_ATTRIBUTE_SIZE) {
Rhyme 0:774324cbc5a6 302 return afERROR_INVALID_PARAM;
Rhyme 0:774324cbc5a6 303 }
Rhyme 0:774324cbc5a6 304
Rhyme 0:774324cbc5a6 305 if (value == NULL) {
Rhyme 0:774324cbc5a6 306 return afERROR_INVALID_PARAM;
Rhyme 0:774324cbc5a6 307 }
Rhyme 0:774324cbc5a6 308
Rhyme 0:774324cbc5a6 309 _requestId++;
Rhyme 0:774324cbc5a6 310 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, valueLen, value);
Rhyme 0:774324cbc5a6 311 }
Rhyme 0:774324cbc5a6 312
Rhyme 0:774324cbc5a6 313 int afLib::setAttributeComplete(uint8_t requestId, const uint16_t attrId, const uint16_t valueLen, const uint8_t *value) {
Rhyme 0:774324cbc5a6 314 if (valueLen > MAX_ATTRIBUTE_SIZE) {
Rhyme 0:774324cbc5a6 315 return afERROR_INVALID_PARAM;
Rhyme 0:774324cbc5a6 316 }
Rhyme 0:774324cbc5a6 317
Rhyme 0:774324cbc5a6 318 if (value == NULL) {
Rhyme 0:774324cbc5a6 319 return afERROR_INVALID_PARAM;
Rhyme 0:774324cbc5a6 320 }
Rhyme 0:774324cbc5a6 321
Rhyme 0:774324cbc5a6 322 return queuePut(MSG_TYPE_UPDATE, requestId, attrId, valueLen, value);
Rhyme 0:774324cbc5a6 323 }
Rhyme 0:774324cbc5a6 324
Rhyme 0:774324cbc5a6 325 /**
Rhyme 0:774324cbc5a6 326 * doGetAttribute
Rhyme 0:774324cbc5a6 327 *
Rhyme 0:774324cbc5a6 328 * The private version of getAttribute. This version actually calls sendCommand() to kick off the state machine and
Rhyme 0:774324cbc5a6 329 * execute the operation.
Rhyme 0:774324cbc5a6 330 */
Rhyme 0:774324cbc5a6 331 int afLib::doGetAttribute(uint8_t requestId, uint16_t attrId) {
Rhyme 0:774324cbc5a6 332 if (_interrupts_pending > 0 || _writeCmd != NULL) {
Rhyme 0:774324cbc5a6 333 return afERROR_BUSY;
Rhyme 0:774324cbc5a6 334 }
Rhyme 0:774324cbc5a6 335
Rhyme 0:774324cbc5a6 336 _writeCmd = new Command(requestId, MSG_TYPE_GET, attrId);
Rhyme 0:774324cbc5a6 337 if (!_writeCmd->isValid()) {
Rhyme 0:774324cbc5a6 338 printf("getAttribute invalid command:");
Rhyme 0:774324cbc5a6 339 _writeCmd->dumpBytes();
Rhyme 0:774324cbc5a6 340 _writeCmd->dump();
Rhyme 0:774324cbc5a6 341 delete (_writeCmd);
Rhyme 0:774324cbc5a6 342 _writeCmd = NULL;
Rhyme 0:774324cbc5a6 343 return afERROR_INVALID_COMMAND;
Rhyme 0:774324cbc5a6 344 }
Rhyme 0:774324cbc5a6 345
Rhyme 0:774324cbc5a6 346 _outstandingSetGetAttrId = attrId;
Rhyme 0:774324cbc5a6 347
Rhyme 0:774324cbc5a6 348 // Start the transmission.
Rhyme 0:774324cbc5a6 349 sendCommand();
Rhyme 0:774324cbc5a6 350
Rhyme 0:774324cbc5a6 351 return afSUCCESS;
Rhyme 0:774324cbc5a6 352 }
Rhyme 0:774324cbc5a6 353
Rhyme 0:774324cbc5a6 354 /**
Rhyme 0:774324cbc5a6 355 * doSetAttribute
Rhyme 0:774324cbc5a6 356 *
Rhyme 0:774324cbc5a6 357 * The private version of setAttribute. This version actually calls sendCommand() to kick off the state machine and
Rhyme 0:774324cbc5a6 358 * execute the operation.
Rhyme 0:774324cbc5a6 359 */
Rhyme 0:774324cbc5a6 360 int afLib::doSetAttribute(uint8_t requestId, uint16_t attrId, uint16_t valueLen, uint8_t *value) {
Rhyme 0:774324cbc5a6 361 if (_interrupts_pending > 0 || _writeCmd != NULL) {
Rhyme 0:774324cbc5a6 362 return afERROR_BUSY;
Rhyme 0:774324cbc5a6 363 }
Rhyme 0:774324cbc5a6 364 _writeCmd = new Command(requestId, MSG_TYPE_SET, attrId, valueLen, value);
Rhyme 0:774324cbc5a6 365 if (!_writeCmd->isValid()) {
Rhyme 0:774324cbc5a6 366 printf("setAttributeComplete invalid command:");
Rhyme 0:774324cbc5a6 367 _writeCmd->dumpBytes();
Rhyme 0:774324cbc5a6 368 _writeCmd->dump();
Rhyme 0:774324cbc5a6 369 delete (_writeCmd);
Rhyme 0:774324cbc5a6 370 _writeCmd = NULL;
Rhyme 0:774324cbc5a6 371 return afERROR_INVALID_COMMAND;
Rhyme 0:774324cbc5a6 372 }
Rhyme 0:774324cbc5a6 373
Rhyme 0:774324cbc5a6 374 _outstandingSetGetAttrId = attrId;
Rhyme 0:774324cbc5a6 375
Rhyme 0:774324cbc5a6 376 // Start the transmission.
Rhyme 0:774324cbc5a6 377 sendCommand();
Rhyme 0:774324cbc5a6 378
Rhyme 0:774324cbc5a6 379 return afSUCCESS;
Rhyme 0:774324cbc5a6 380 }
Rhyme 0:774324cbc5a6 381
Rhyme 0:774324cbc5a6 382 /**
Rhyme 0:774324cbc5a6 383 * doUpdateAttribute
Rhyme 0:774324cbc5a6 384 *
Rhyme 0:774324cbc5a6 385 * setAttribute calls on MCU attributes turn into updateAttribute calls. See documentation on the SPI protocol for
Rhyme 0:774324cbc5a6 386 * more information. This method calls sendCommand() to kick off the state machine and execute the operation.
Rhyme 0:774324cbc5a6 387 */
Rhyme 0:774324cbc5a6 388 int afLib::doUpdateAttribute(uint8_t requestId, uint16_t attrId, uint8_t status, uint16_t valueLen, uint8_t *value) {
Rhyme 0:774324cbc5a6 389 if (_interrupts_pending > 0 || _writeCmd != NULL) {
Rhyme 0:774324cbc5a6 390 return afERROR_BUSY;
Rhyme 0:774324cbc5a6 391 }
Rhyme 0:774324cbc5a6 392
Rhyme 0:774324cbc5a6 393 _writeCmd = new Command(requestId, MSG_TYPE_UPDATE, attrId, status, 3 /* MCU Set it */, valueLen, value);
Rhyme 0:774324cbc5a6 394 if (!_writeCmd->isValid()) {
Rhyme 0:774324cbc5a6 395 printf("updateAttribute invalid command:");
Rhyme 0:774324cbc5a6 396 _writeCmd->dumpBytes();
Rhyme 0:774324cbc5a6 397 _writeCmd->dump();
Rhyme 0:774324cbc5a6 398 delete (_writeCmd);
Rhyme 0:774324cbc5a6 399 return afERROR_INVALID_COMMAND;
Rhyme 0:774324cbc5a6 400 }
Rhyme 0:774324cbc5a6 401
Rhyme 0:774324cbc5a6 402 // Start the transmission.
Rhyme 0:774324cbc5a6 403 sendCommand();
Rhyme 0:774324cbc5a6 404
Rhyme 0:774324cbc5a6 405 return afSUCCESS;
Rhyme 0:774324cbc5a6 406 }
Rhyme 0:774324cbc5a6 407
Rhyme 0:774324cbc5a6 408 /**
Rhyme 0:774324cbc5a6 409 * parseCommand
Rhyme 0:774324cbc5a6 410 *
Rhyme 0:774324cbc5a6 411 * A debug method for parsing a string into a command. This is not required for library operation and is only supplied
Rhyme 0:774324cbc5a6 412 * as an example of how to execute attribute operations from a command line interface.
Rhyme 0:774324cbc5a6 413 */
Rhyme 0:774324cbc5a6 414 #ifdef ATTRIBUTE_CLI
Rhyme 0:774324cbc5a6 415 int afLib::parseCommand(const char *cmd) {
Rhyme 0:774324cbc5a6 416 if (_interrupts_pending > 0 || _writeCmd != NULL) {
Rhyme 0:774324cbc5a6 417 _theLog->print("Busy: ");
Rhyme 0:774324cbc5a6 418 _theLog->print(_interrupts_pending);
Rhyme 0:774324cbc5a6 419 _theLog->print(", ");
Rhyme 0:774324cbc5a6 420 _theLog->println(_writeCmd != NULL);
Rhyme 0:774324cbc5a6 421 return afERROR_BUSY;
Rhyme 0:774324cbc5a6 422 }
Rhyme 0:774324cbc5a6 423
Rhyme 0:774324cbc5a6 424 int reqId = _requestId++;
Rhyme 0:774324cbc5a6 425 _writeCmd = new Command(_theLog,reqId, cmd);
Rhyme 0:774324cbc5a6 426 if (!_writeCmd->isValid()) {
Rhyme 0:774324cbc5a6 427 _theLog->print("BAD: ");
Rhyme 0:774324cbc5a6 428 _theLog->println(cmd);
Rhyme 0:774324cbc5a6 429 _writeCmd->dumpBytes();
Rhyme 0:774324cbc5a6 430 _writeCmd->dump();
Rhyme 0:774324cbc5a6 431 delete (_writeCmd);
Rhyme 0:774324cbc5a6 432 _writeCmd = NULL;
Rhyme 0:774324cbc5a6 433 return afERROR_INVALID_COMMAND;
Rhyme 0:774324cbc5a6 434 }
Rhyme 0:774324cbc5a6 435
Rhyme 0:774324cbc5a6 436 // Start the transmission.
Rhyme 0:774324cbc5a6 437 sendCommand();
Rhyme 0:774324cbc5a6 438
Rhyme 0:774324cbc5a6 439 return afSUCCESS;
Rhyme 0:774324cbc5a6 440 }
Rhyme 0:774324cbc5a6 441 #endif
Rhyme 0:774324cbc5a6 442
Rhyme 0:774324cbc5a6 443 /**
Rhyme 0:774324cbc5a6 444 * runStateMachine
Rhyme 0:774324cbc5a6 445 *
Rhyme 0:774324cbc5a6 446 * The state machine for afLib. This state machine is responsible for implementing the KSP SPI protocol and executing
Rhyme 0:774324cbc5a6 447 * attribute operations.
Rhyme 0:774324cbc5a6 448 * This method is run:
Rhyme 0:774324cbc5a6 449 * 1. In response to receiving an interrupt from the ASR-1.
Rhyme 0:774324cbc5a6 450 * 2. When an attribute operation is pulled out of the queue and executed.
Rhyme 0:774324cbc5a6 451 */
Rhyme 0:774324cbc5a6 452 void afLib::runStateMachine(void) {
Rhyme 0:774324cbc5a6 453 if (_interrupts_pending > 0) {
Rhyme 0:774324cbc5a6 454 switch (_state) {
Rhyme 0:774324cbc5a6 455 case STATE_IDLE:
Rhyme 0:774324cbc5a6 456 //deathWish.attach(&afLib::kick_the_bucket,10);
Rhyme 0:774324cbc5a6 457 onStateIdle();
Rhyme 0:774324cbc5a6 458 return;
Rhyme 0:774324cbc5a6 459
Rhyme 0:774324cbc5a6 460 case STATE_STATUS_SYNC:
Rhyme 0:774324cbc5a6 461 onStateSync();
Rhyme 0:774324cbc5a6 462 break;
Rhyme 0:774324cbc5a6 463
Rhyme 0:774324cbc5a6 464 case STATE_STATUS_ACK:
Rhyme 0:774324cbc5a6 465 onStateAck();
Rhyme 0:774324cbc5a6 466 break;
Rhyme 0:774324cbc5a6 467
Rhyme 0:774324cbc5a6 468 case STATE_SEND_BYTES:
Rhyme 0:774324cbc5a6 469 onStateSendBytes();
Rhyme 0:774324cbc5a6 470 break;
Rhyme 0:774324cbc5a6 471
Rhyme 0:774324cbc5a6 472 case STATE_RECV_BYTES:
Rhyme 0:774324cbc5a6 473 onStateRecvBytes();
Rhyme 0:774324cbc5a6 474 break;
Rhyme 0:774324cbc5a6 475
Rhyme 0:774324cbc5a6 476 case STATE_CMD_COMPLETE:
Rhyme 0:774324cbc5a6 477 onStateCmdComplete();
Rhyme 0:774324cbc5a6 478 break;
Rhyme 0:774324cbc5a6 479 }
Rhyme 0:774324cbc5a6 480
Rhyme 0:774324cbc5a6 481 updateIntsPending(-1);
Rhyme 0:774324cbc5a6 482 } else {
Rhyme 0:774324cbc5a6 483 if (syncRetries > 0 && syncRetries < MAX_SYNC_RETRIES && checkLastSync->read_ms() - lastSync > 1000) {
Rhyme 0:774324cbc5a6 484 updateIntsPending(1);
Rhyme 0:774324cbc5a6 485 } else if (syncRetries >= MAX_SYNC_RETRIES) {
Rhyme 0:774324cbc5a6 486 printf("No response from ASR-1 - does profile have MCU enabled?\n");
Rhyme 0:774324cbc5a6 487 #if defined(TARGET_KL25Z)
Rhyme 0:774324cbc5a6 488 // WatchDogWrapper::getSelf()->kick_the_bucket();
Rhyme 0:774324cbc5a6 489 #endif //TARGET_KL25Z
Rhyme 0:774324cbc5a6 490 syncRetries = 0;
Rhyme 0:774324cbc5a6 491 _state = STATE_IDLE;
Rhyme 0:774324cbc5a6 492 }
Rhyme 0:774324cbc5a6 493 }
Rhyme 0:774324cbc5a6 494 }
Rhyme 0:774324cbc5a6 495
Rhyme 0:774324cbc5a6 496 /**
Rhyme 0:774324cbc5a6 497 * onStateIdle
Rhyme 0:774324cbc5a6 498 *
Rhyme 0:774324cbc5a6 499 * If there is a command to be written, update the bytes to send. Otherwise we're sending a zero-sync message.
Rhyme 0:774324cbc5a6 500 * Either way advance the state to send a sync message.
Rhyme 0:774324cbc5a6 501 */
Rhyme 0:774324cbc5a6 502 void afLib::onStateIdle(void) {
Rhyme 0:774324cbc5a6 503 if (_writeCmd != NULL) {
Rhyme 0:774324cbc5a6 504 // Include 2 bytes for length
Rhyme 0:774324cbc5a6 505 _bytesToSend = _writeCmd->getSize() + 2;
Rhyme 0:774324cbc5a6 506 } else {
Rhyme 0:774324cbc5a6 507 _bytesToSend = 0;
Rhyme 0:774324cbc5a6 508 }
Rhyme 0:774324cbc5a6 509 _state = STATE_STATUS_SYNC;
Rhyme 0:774324cbc5a6 510 printState(_state);
Rhyme 0:774324cbc5a6 511 }
Rhyme 0:774324cbc5a6 512
Rhyme 0:774324cbc5a6 513 /**
Rhyme 0:774324cbc5a6 514 * onStateSync
Rhyme 0:774324cbc5a6 515 *
Rhyme 0:774324cbc5a6 516 * Write a sync message over SPI to let the ASR-1 know that we want to send some data.
Rhyme 0:774324cbc5a6 517 * Check for a "collision" which occurs if the ASR-1 is trying to send us data at the same time.
Rhyme 0:774324cbc5a6 518 */
Rhyme 0:774324cbc5a6 519 void afLib::onStateSync(void) {
Rhyme 0:774324cbc5a6 520 int result;
Rhyme 0:774324cbc5a6 521
Rhyme 0:774324cbc5a6 522 _txStatus->setAck(false);
Rhyme 0:774324cbc5a6 523 _txStatus->setBytesToSend(_bytesToSend);
Rhyme 0:774324cbc5a6 524 _txStatus->setBytesToRecv(0);
Rhyme 0:774324cbc5a6 525
Rhyme 0:774324cbc5a6 526 result = exchangeStatus(_txStatus, _rxStatus);
Rhyme 0:774324cbc5a6 527
Rhyme 0:774324cbc5a6 528 if (result == afSUCCESS && _rxStatus->isValid() && inSync(_txStatus, _rxStatus)) {
Rhyme 0:774324cbc5a6 529 syncRetries = 0; // Flag that sync completed.
Rhyme 0:774324cbc5a6 530 _state = STATE_STATUS_ACK;
Rhyme 0:774324cbc5a6 531 if (_txStatus->getBytesToSend() == 0 && _rxStatus->getBytesToRecv() > 0) {
Rhyme 0:774324cbc5a6 532 _bytesToRecv = _rxStatus->getBytesToRecv();
Rhyme 0:774324cbc5a6 533 }
Rhyme 0:774324cbc5a6 534 } else {
Rhyme 0:774324cbc5a6 535 // Try resending the preamble
Rhyme 0:774324cbc5a6 536 _state = STATE_STATUS_SYNC;
Rhyme 0:774324cbc5a6 537 lastSync = checkLastSync->read_ms();
Rhyme 0:774324cbc5a6 538 syncRetries++;
Rhyme 0:774324cbc5a6 539 // _txStatus->dumpBytes();
Rhyme 0:774324cbc5a6 540 // _rxStatus->dumpBytes();
Rhyme 0:774324cbc5a6 541 }
Rhyme 0:774324cbc5a6 542 printState(_state);
Rhyme 0:774324cbc5a6 543 }
Rhyme 0:774324cbc5a6 544
Rhyme 0:774324cbc5a6 545 /**
Rhyme 0:774324cbc5a6 546 * onStateAck
Rhyme 0:774324cbc5a6 547 *
Rhyme 0:774324cbc5a6 548 * Acknowledge the previous sync message and advance the state.
Rhyme 0:774324cbc5a6 549 * If there are bytes to send, advance to send bytes state.
Rhyme 0:774324cbc5a6 550 * If there are bytes to receive, advance to receive bytes state.
Rhyme 0:774324cbc5a6 551 * Otherwise it was a zero-sync so advance to command complete.
Rhyme 0:774324cbc5a6 552 */
Rhyme 0:774324cbc5a6 553 void afLib::onStateAck(void) {
Rhyme 0:774324cbc5a6 554 int result;
Rhyme 0:774324cbc5a6 555
Rhyme 0:774324cbc5a6 556 _txStatus->setAck(true);
Rhyme 0:774324cbc5a6 557 _txStatus->setBytesToRecv(_rxStatus->getBytesToRecv());
Rhyme 0:774324cbc5a6 558 _bytesToRecv = _rxStatus->getBytesToRecv();
Rhyme 0:774324cbc5a6 559 result = writeStatus(_txStatus);
Rhyme 0:774324cbc5a6 560 if (result != afSUCCESS) {
Rhyme 0:774324cbc5a6 561 _state = STATE_STATUS_SYNC;
Rhyme 0:774324cbc5a6 562 printState(_state);
Rhyme 0:774324cbc5a6 563 return;
Rhyme 0:774324cbc5a6 564 }
Rhyme 0:774324cbc5a6 565 if (_bytesToSend > 0) {
Rhyme 0:774324cbc5a6 566 _writeBufferLen = (uint16_t) _writeCmd->getSize();
Rhyme 0:774324cbc5a6 567 _writeBuffer = new uint8_t[_bytesToSend];
Rhyme 0:774324cbc5a6 568 memcpy(_writeBuffer, (uint8_t * ) & _writeBufferLen, 2);
Rhyme 0:774324cbc5a6 569 _writeCmd->getBytes(&_writeBuffer[2]);
Rhyme 0:774324cbc5a6 570 _state = STATE_SEND_BYTES;
Rhyme 0:774324cbc5a6 571 } else if (_bytesToRecv > 0) {
Rhyme 0:774324cbc5a6 572 _state = STATE_RECV_BYTES;
Rhyme 0:774324cbc5a6 573 } else {
Rhyme 0:774324cbc5a6 574 _state = STATE_CMD_COMPLETE;
Rhyme 0:774324cbc5a6 575 }
Rhyme 0:774324cbc5a6 576 printState(_state);
Rhyme 0:774324cbc5a6 577 }
Rhyme 0:774324cbc5a6 578
Rhyme 0:774324cbc5a6 579 /**
Rhyme 0:774324cbc5a6 580 * onStateSendBytes
Rhyme 0:774324cbc5a6 581 *
Rhyme 0:774324cbc5a6 582 * Send the required number of bytes to the ASR-1 and then advance to command complete.
Rhyme 0:774324cbc5a6 583 */
Rhyme 0:774324cbc5a6 584 void afLib::onStateSendBytes(void) {
Rhyme 0:774324cbc5a6 585 // _theLog->print("send bytes: "); _theLog->println(_bytesToSend);
Rhyme 0:774324cbc5a6 586 sendBytes();
Rhyme 0:774324cbc5a6 587
Rhyme 0:774324cbc5a6 588 if (_bytesToSend == 0) {
Rhyme 0:774324cbc5a6 589 _writeBufferLen = 0;
Rhyme 0:774324cbc5a6 590 delete[] (_writeBuffer); //wsugi delete (_writeBuffer);
Rhyme 0:774324cbc5a6 591 _writeBuffer = NULL;
Rhyme 0:774324cbc5a6 592 _state = STATE_CMD_COMPLETE;
Rhyme 0:774324cbc5a6 593 printState(_state);
Rhyme 0:774324cbc5a6 594 }
Rhyme 0:774324cbc5a6 595 }
Rhyme 0:774324cbc5a6 596
Rhyme 0:774324cbc5a6 597 /**
Rhyme 0:774324cbc5a6 598 * onStateRecvBytes
Rhyme 0:774324cbc5a6 599 *
Rhyme 0:774324cbc5a6 600 * Receive the required number of bytes from the ASR-1 and then advance to command complete.
Rhyme 0:774324cbc5a6 601 */
Rhyme 0:774324cbc5a6 602 void afLib::onStateRecvBytes(void) {
Rhyme 0:774324cbc5a6 603 // _theLog->print("receive bytes: "); _theLog->println(_bytesToRecv);
Rhyme 0:774324cbc5a6 604 recvBytes();
Rhyme 0:774324cbc5a6 605 if (_bytesToRecv == 0) {
Rhyme 0:774324cbc5a6 606 _state = STATE_CMD_COMPLETE;
Rhyme 0:774324cbc5a6 607 printState(_state);
Rhyme 0:774324cbc5a6 608 _readCmd = new Command(_readBufferLen, &_readBuffer[2]);
Rhyme 0:774324cbc5a6 609 delete[] (_readBuffer); //wsugi delete (_readBuffer);
Rhyme 0:774324cbc5a6 610 _readBuffer = NULL;
Rhyme 0:774324cbc5a6 611 }
Rhyme 0:774324cbc5a6 612 }
Rhyme 0:774324cbc5a6 613
Rhyme 0:774324cbc5a6 614 /**
Rhyme 0:774324cbc5a6 615 * onStateCmdComplete
Rhyme 0:774324cbc5a6 616 *
Rhyme 0:774324cbc5a6 617 * Call the appropriate sketch callback to report the result of the command.
Rhyme 0:774324cbc5a6 618 * Clear the command object and go back to waiting for the next interrupt or command.
Rhyme 0:774324cbc5a6 619 */
Rhyme 0:774324cbc5a6 620 void afLib::onStateCmdComplete(void) {
Rhyme 0:774324cbc5a6 621 _state = STATE_IDLE;
Rhyme 0:774324cbc5a6 622 printState(_state);
Rhyme 0:774324cbc5a6 623 if (_readCmd != NULL) {
Rhyme 0:774324cbc5a6 624 uint8_t *val = new uint8_t[_readCmd->getValueLen()];
Rhyme 0:774324cbc5a6 625 _readCmd->getValue(val);
Rhyme 0:774324cbc5a6 626
Rhyme 0:774324cbc5a6 627 switch (_readCmd->getCommand()) {
Rhyme 0:774324cbc5a6 628 case MSG_TYPE_SET:
Rhyme 0:774324cbc5a6 629 _onAttrSet(_readCmd->getReqId(), _readCmd->getAttrId(), _readCmd->getValueLen(), val);
Rhyme 0:774324cbc5a6 630 break;
Rhyme 0:774324cbc5a6 631
Rhyme 0:774324cbc5a6 632 case MSG_TYPE_UPDATE:
Rhyme 0:774324cbc5a6 633 if (_readCmd->getAttrId() == _outstandingSetGetAttrId) {
Rhyme 0:774324cbc5a6 634 _outstandingSetGetAttrId = 0;
Rhyme 0:774324cbc5a6 635 }
Rhyme 0:774324cbc5a6 636 _onAttrSetComplete(_readCmd->getReqId(), _readCmd->getAttrId(), _readCmd->getValueLen(), val);
Rhyme 0:774324cbc5a6 637 break;
Rhyme 0:774324cbc5a6 638
Rhyme 0:774324cbc5a6 639 default:
Rhyme 0:774324cbc5a6 640 break;
Rhyme 0:774324cbc5a6 641 }
Rhyme 0:774324cbc5a6 642 delete[] (val); //wsugi delete (val);
Rhyme 0:774324cbc5a6 643 delete (_readCmd);
Rhyme 0:774324cbc5a6 644 _readCmdOffset = 0;
Rhyme 0:774324cbc5a6 645 _readCmd = NULL;
Rhyme 0:774324cbc5a6 646 }
Rhyme 0:774324cbc5a6 647
Rhyme 0:774324cbc5a6 648 if (_writeCmd != NULL) {
Rhyme 0:774324cbc5a6 649 // Fake a callback here for MCU attributes as we don't get one from the module.
Rhyme 0:774324cbc5a6 650 if (_writeCmd->getCommand() == MSG_TYPE_UPDATE && IS_MCU_ATTR(_writeCmd->getAttrId())) {
Rhyme 0:774324cbc5a6 651 _onAttrSetComplete(_writeCmd->getReqId(), _writeCmd->getAttrId(), _writeCmd->getValueLen(), _writeCmd->getValueP());
Rhyme 0:774324cbc5a6 652 }
Rhyme 0:774324cbc5a6 653 delete (_writeCmd);
Rhyme 0:774324cbc5a6 654 _writeCmdOffset = 0;
Rhyme 0:774324cbc5a6 655 _writeCmd = NULL;
Rhyme 0:774324cbc5a6 656 }
Rhyme 0:774324cbc5a6 657 }
Rhyme 0:774324cbc5a6 658
Rhyme 0:774324cbc5a6 659 /**
Rhyme 0:774324cbc5a6 660 * exchangeStatus
Rhyme 0:774324cbc5a6 661 *
Rhyme 0:774324cbc5a6 662 * Write a status command object to the ASR-1 and clock in a status object from the ASR-1 at the same time.
Rhyme 0:774324cbc5a6 663 */
Rhyme 0:774324cbc5a6 664 int afLib::exchangeStatus(StatusCommand *tx, StatusCommand *rx) {
Rhyme 0:774324cbc5a6 665 int result = afSUCCESS;
Rhyme 0:774324cbc5a6 666 uint16_t len = tx->getSize();
Rhyme 0:774324cbc5a6 667 int bytes[len];
Rhyme 0:774324cbc5a6 668 char rbytes[len+1];
Rhyme 0:774324cbc5a6 669 int index = 0;
Rhyme 0:774324cbc5a6 670 tx->getBytes(bytes);
Rhyme 0:774324cbc5a6 671
Rhyme 0:774324cbc5a6 672 // _theSPI->beginSPI();
Rhyme 0:774324cbc5a6 673
Rhyme 0:774324cbc5a6 674 for (int i=0;i<len;i++)
Rhyme 0:774324cbc5a6 675 {
Rhyme 0:774324cbc5a6 676 rbytes[i]=bytes[i];
Rhyme 0:774324cbc5a6 677 }
Rhyme 0:774324cbc5a6 678 rbytes[len]=tx->getChecksum();
Rhyme 0:774324cbc5a6 679
Rhyme 0:774324cbc5a6 680 printTransaction((uint8_t*)rbytes,len+1);
Rhyme 0:774324cbc5a6 681
Rhyme 0:774324cbc5a6 682 _theSPI->beginSPI();
Rhyme 0:774324cbc5a6 683 _theSPI->transfer(rbytes,len+1);
Rhyme 0:774324cbc5a6 684 _theSPI->endSPI();
Rhyme 0:774324cbc5a6 685
Rhyme 0:774324cbc5a6 686 printTransaction((uint8_t*)rbytes,len+1);
Rhyme 0:774324cbc5a6 687
Rhyme 0:774324cbc5a6 688 uint8_t cmd = bytes[index++];
Rhyme 0:774324cbc5a6 689 if (cmd != 0x30 && cmd != 0x31) {
Rhyme 0:774324cbc5a6 690 printf("exchangeStatus bad cmd: 0x%02x\n",cmd);
Rhyme 0:774324cbc5a6 691 result = afERROR_INVALID_COMMAND;
Rhyme 0:774324cbc5a6 692 }
Rhyme 0:774324cbc5a6 693
Rhyme 0:774324cbc5a6 694 rx->setBytesToSend(rbytes[index + 0] | (rbytes[index + 1] << 8));
Rhyme 0:774324cbc5a6 695 rx->setBytesToRecv(rbytes[index + 2] | (rbytes[index + 3] << 8));
Rhyme 0:774324cbc5a6 696 rx->setChecksum(rbytes[index+4]);
Rhyme 0:774324cbc5a6 697 //_theSPI->endSPI();
Rhyme 0:774324cbc5a6 698 return result;
Rhyme 0:774324cbc5a6 699 }
Rhyme 0:774324cbc5a6 700
Rhyme 0:774324cbc5a6 701 /**
Rhyme 0:774324cbc5a6 702 * inSync
Rhyme 0:774324cbc5a6 703 *
Rhyme 0:774324cbc5a6 704 * Check to make sure the Arduino and the ASR-1 aren't trying to send data at the same time.
Rhyme 0:774324cbc5a6 705 * Return true only if there is no collision.
Rhyme 0:774324cbc5a6 706 */
Rhyme 0:774324cbc5a6 707 bool afLib::inSync(StatusCommand *tx, StatusCommand *rx) {
Rhyme 0:774324cbc5a6 708 return (tx->getBytesToSend() == 0 && rx->getBytesToRecv() == 0) ||
Rhyme 0:774324cbc5a6 709 (tx->getBytesToSend() > 0 && rx->getBytesToRecv() == 0) ||
Rhyme 0:774324cbc5a6 710 (tx->getBytesToSend() == 0 && rx->getBytesToRecv() > 0);
Rhyme 0:774324cbc5a6 711 }
Rhyme 0:774324cbc5a6 712
Rhyme 0:774324cbc5a6 713 /**
Rhyme 0:774324cbc5a6 714 * writeStatus
Rhyme 0:774324cbc5a6 715 *
Rhyme 0:774324cbc5a6 716 * Write a status command to the ASR-1 and ignore the result. If you want to read bytes at the same time, use
Rhyme 0:774324cbc5a6 717 * exchangeStatus instead.
Rhyme 0:774324cbc5a6 718 */
Rhyme 0:774324cbc5a6 719 int afLib::writeStatus(StatusCommand *c) {
Rhyme 0:774324cbc5a6 720 int result = afSUCCESS;
Rhyme 0:774324cbc5a6 721 uint16_t len = c->getSize();
Rhyme 0:774324cbc5a6 722 int bytes[len];
Rhyme 0:774324cbc5a6 723 char rbytes[len+1];
Rhyme 0:774324cbc5a6 724 int index = 0;
Rhyme 0:774324cbc5a6 725 c->getBytes(bytes);
Rhyme 0:774324cbc5a6 726
Rhyme 0:774324cbc5a6 727 _theSPI->beginSPI();
Rhyme 0:774324cbc5a6 728
Rhyme 0:774324cbc5a6 729 for (int i=0;i<len;i++)
Rhyme 0:774324cbc5a6 730 {
Rhyme 0:774324cbc5a6 731 rbytes[i]=bytes[i];
Rhyme 0:774324cbc5a6 732 }
Rhyme 0:774324cbc5a6 733 rbytes[len]=c->getChecksum();
Rhyme 0:774324cbc5a6 734 printTransaction((uint8_t*)rbytes,len+1);
Rhyme 0:774324cbc5a6 735 _theSPI->transfer(rbytes,len+1);
Rhyme 0:774324cbc5a6 736 printTransaction((uint8_t*)rbytes,len+1);
Rhyme 0:774324cbc5a6 737 uint8_t cmd = rbytes[index++];
Rhyme 0:774324cbc5a6 738 if (cmd != 0x30 && cmd != 0x31) {
Rhyme 0:774324cbc5a6 739 printf("writeStatus bad cmd: 0x%02x\n",cmd);
Rhyme 0:774324cbc5a6 740 result = afERROR_INVALID_COMMAND;
Rhyme 0:774324cbc5a6 741 }
Rhyme 0:774324cbc5a6 742
Rhyme 0:774324cbc5a6 743
Rhyme 0:774324cbc5a6 744 _theSPI->endSPI();
Rhyme 0:774324cbc5a6 745
Rhyme 0:774324cbc5a6 746 // c->dump();
Rhyme 0:774324cbc5a6 747 // c->dumpBytes();
Rhyme 0:774324cbc5a6 748
Rhyme 0:774324cbc5a6 749 return result;
Rhyme 0:774324cbc5a6 750 }
Rhyme 0:774324cbc5a6 751
Rhyme 0:774324cbc5a6 752 /**
Rhyme 0:774324cbc5a6 753 * sendBytes
Rhyme 0:774324cbc5a6 754 *
Rhyme 0:774324cbc5a6 755 * Send the specified number of data bytes to the ASR-1. Do this in chunks of SPI_FRAME_LEN bytes.
Rhyme 0:774324cbc5a6 756 */
Rhyme 0:774324cbc5a6 757 void afLib::sendBytes() {
Rhyme 0:774324cbc5a6 758 uint16_t len = _bytesToSend > SPI_FRAME_LEN ? SPI_FRAME_LEN : _bytesToSend;
Rhyme 0:774324cbc5a6 759 uint8_t bytes[SPI_FRAME_LEN];
Rhyme 0:774324cbc5a6 760 memset(bytes, 0xff, sizeof(bytes));
Rhyme 0:774324cbc5a6 761
Rhyme 0:774324cbc5a6 762 memcpy(bytes, &_writeBuffer[_writeCmdOffset], len);
Rhyme 0:774324cbc5a6 763
Rhyme 0:774324cbc5a6 764 _theSPI->beginSPI();
Rhyme 0:774324cbc5a6 765 printTransaction(bytes,len+1);
Rhyme 0:774324cbc5a6 766 _theSPI->transfer((char *)bytes,len);
Rhyme 0:774324cbc5a6 767 printTransaction(bytes,len+1);
Rhyme 0:774324cbc5a6 768 _theSPI->endSPI();
Rhyme 0:774324cbc5a6 769
Rhyme 0:774324cbc5a6 770 // dumpBytes("Sending:", len, bytes);
Rhyme 0:774324cbc5a6 771
Rhyme 0:774324cbc5a6 772 _writeCmdOffset += len;
Rhyme 0:774324cbc5a6 773 _bytesToSend -= len;
Rhyme 0:774324cbc5a6 774 }
Rhyme 0:774324cbc5a6 775
Rhyme 0:774324cbc5a6 776 /**
Rhyme 0:774324cbc5a6 777 * recvBytes
Rhyme 0:774324cbc5a6 778 *
Rhyme 0:774324cbc5a6 779 * Receive the specified number of data bytes from the ASR-1. Do this in chunks of SPI_FRAME_LEN bytes.
Rhyme 0:774324cbc5a6 780 */
Rhyme 0:774324cbc5a6 781 void afLib::recvBytes() {
Rhyme 0:774324cbc5a6 782 uint16_t len = _bytesToRecv > SPI_FRAME_LEN ? SPI_FRAME_LEN : _bytesToRecv;
Rhyme 0:774324cbc5a6 783
Rhyme 0:774324cbc5a6 784 if (_readCmdOffset == 0) {
Rhyme 0:774324cbc5a6 785 _readBufferLen = _bytesToRecv;
Rhyme 0:774324cbc5a6 786 _readBuffer = new uint8_t[_readBufferLen];
Rhyme 0:774324cbc5a6 787 }
Rhyme 0:774324cbc5a6 788
Rhyme 0:774324cbc5a6 789 _theSPI->beginSPI();
Rhyme 0:774324cbc5a6 790
Rhyme 0:774324cbc5a6 791
Rhyme 0:774324cbc5a6 792 char * start =(char*)_readBuffer + _readCmdOffset;
Rhyme 0:774324cbc5a6 793 printTransaction((uint8_t*)start,len+1);
Rhyme 0:774324cbc5a6 794 _theSPI->transfer(start,len);
Rhyme 0:774324cbc5a6 795 printTransaction((uint8_t*)start,len+1);
Rhyme 0:774324cbc5a6 796
Rhyme 0:774324cbc5a6 797 _theSPI->endSPI();
Rhyme 0:774324cbc5a6 798
Rhyme 0:774324cbc5a6 799 // dumpBytes("Receiving:", len, _readBuffer);
Rhyme 0:774324cbc5a6 800
Rhyme 0:774324cbc5a6 801 _readCmdOffset += len;
Rhyme 0:774324cbc5a6 802 _bytesToRecv -= len;
Rhyme 0:774324cbc5a6 803 }
Rhyme 0:774324cbc5a6 804
Rhyme 0:774324cbc5a6 805 /**
Rhyme 0:774324cbc5a6 806 * isIdle
Rhyme 0:774324cbc5a6 807 *
Rhyme 0:774324cbc5a6 808 * Provide a way for the sketch to know if we're idle. Returns true if there are no attribute operations in progress.
Rhyme 0:774324cbc5a6 809 */
Rhyme 0:774324cbc5a6 810 bool afLib::isIdle() {
Rhyme 0:774324cbc5a6 811 return _interrupts_pending == 0 && _state == STATE_IDLE && _outstandingSetGetAttrId == 0;
Rhyme 0:774324cbc5a6 812 }
Rhyme 0:774324cbc5a6 813
Rhyme 0:774324cbc5a6 814 /**
Rhyme 0:774324cbc5a6 815 * These methods are required to disable/enable interrupts for the Linux version of afLib.
Rhyme 0:774324cbc5a6 816 * They are no-ops on Arduino.
Rhyme 0:774324cbc5a6 817 */
Rhyme 0:774324cbc5a6 818 #ifndef ARDUINO
Rhyme 0:774324cbc5a6 819 void noInterrupts(){}
Rhyme 0:774324cbc5a6 820 void interrupts(){}
Rhyme 0:774324cbc5a6 821 #endif
Rhyme 0:774324cbc5a6 822
Rhyme 0:774324cbc5a6 823 void afLib::mcuISR() {
Rhyme 0:774324cbc5a6 824 // _theLog->println("mcu");
Rhyme 0:774324cbc5a6 825 updateIntsPending(1);
Rhyme 0:774324cbc5a6 826 }
Rhyme 0:774324cbc5a6 827
Rhyme 0:774324cbc5a6 828 /****************************************************************************
Rhyme 0:774324cbc5a6 829 * Queue Methods *
Rhyme 0:774324cbc5a6 830 ****************************************************************************/
Rhyme 0:774324cbc5a6 831 /**
Rhyme 0:774324cbc5a6 832 * queueInit
Rhyme 0:774324cbc5a6 833 *
Rhyme 0:774324cbc5a6 834 * Create a small queue to prevent flooding the ASR-1 with attribute operations.
Rhyme 0:774324cbc5a6 835 * The initial size is small to allow running on small boards like UNO.
Rhyme 0:774324cbc5a6 836 * Size can be increased on larger boards.
Rhyme 0:774324cbc5a6 837 */
Rhyme 0:774324cbc5a6 838 void afLib::queueInit() {
Rhyme 0:774324cbc5a6 839 for (int i = 0; i < REQUEST_QUEUE_SIZE; i++) {
Rhyme 0:774324cbc5a6 840 _requestQueue[i].p_value = NULL;
Rhyme 0:774324cbc5a6 841 }
Rhyme 0:774324cbc5a6 842 }
Rhyme 0:774324cbc5a6 843
Rhyme 0:774324cbc5a6 844 /**
Rhyme 0:774324cbc5a6 845 * queuePut
Rhyme 0:774324cbc5a6 846 *
Rhyme 0:774324cbc5a6 847 * Add an item to the end of the queue. Return an error if we're out of space in the queue.
Rhyme 0:774324cbc5a6 848 */
Rhyme 0:774324cbc5a6 849 int afLib::queuePut(uint8_t messageType, uint8_t requestId, const uint16_t attributeId, uint16_t valueLen,
Rhyme 0:774324cbc5a6 850 const uint8_t *value) {
Rhyme 0:774324cbc5a6 851 for (int i = 0; i < REQUEST_QUEUE_SIZE; i++) {
Rhyme 0:774324cbc5a6 852 if (_requestQueue[i].p_value == NULL) {
Rhyme 0:774324cbc5a6 853 _requestQueue[i].messageType = messageType;
Rhyme 0:774324cbc5a6 854 _requestQueue[i].attrId = attributeId;
Rhyme 0:774324cbc5a6 855 _requestQueue[i].requestId = requestId;
Rhyme 0:774324cbc5a6 856 _requestQueue[i].valueLen = valueLen;
Rhyme 0:774324cbc5a6 857 _requestQueue[i].p_value = new uint8_t[valueLen];
Rhyme 0:774324cbc5a6 858 memcpy(_requestQueue[i].p_value, value, valueLen);
Rhyme 0:774324cbc5a6 859 return afSUCCESS;
Rhyme 0:774324cbc5a6 860 }
Rhyme 0:774324cbc5a6 861 }
Rhyme 0:774324cbc5a6 862
Rhyme 0:774324cbc5a6 863 return afERROR_QUEUE_OVERFLOW;
Rhyme 0:774324cbc5a6 864 }
Rhyme 0:774324cbc5a6 865
Rhyme 0:774324cbc5a6 866 /**
Rhyme 0:774324cbc5a6 867 * queueGet
Rhyme 0:774324cbc5a6 868 *
Rhyme 0:774324cbc5a6 869 * Pull and return the oldest item from the queue. Return an error if the queue is empty.
Rhyme 0:774324cbc5a6 870 */
Rhyme 0:774324cbc5a6 871 int afLib::queueGet(uint8_t *messageType, uint8_t *requestId, uint16_t *attributeId, uint16_t *valueLen,
Rhyme 0:774324cbc5a6 872 uint8_t **value) {
Rhyme 0:774324cbc5a6 873 for (int i = 0; i < REQUEST_QUEUE_SIZE; i++) {
Rhyme 0:774324cbc5a6 874 if (_requestQueue[i].p_value != NULL) {
Rhyme 0:774324cbc5a6 875 *messageType = _requestQueue[i].messageType;
Rhyme 0:774324cbc5a6 876 *attributeId = _requestQueue[i].attrId;
Rhyme 0:774324cbc5a6 877 *requestId = _requestQueue[i].requestId;
Rhyme 0:774324cbc5a6 878 *valueLen = _requestQueue[i].valueLen;
Rhyme 0:774324cbc5a6 879 *value = new uint8_t[*valueLen];
Rhyme 0:774324cbc5a6 880 memcpy(*value, _requestQueue[i].p_value, *valueLen);
Rhyme 0:774324cbc5a6 881 delete[] (_requestQueue[i].p_value); //wsugi delete (_requestQueue[i].p_value);
Rhyme 0:774324cbc5a6 882 _requestQueue[i].p_value = NULL;
Rhyme 0:774324cbc5a6 883 return afSUCCESS;
Rhyme 0:774324cbc5a6 884 }
Rhyme 0:774324cbc5a6 885 }
Rhyme 0:774324cbc5a6 886
Rhyme 0:774324cbc5a6 887 return afERROR_QUEUE_UNDERFLOW;
Rhyme 0:774324cbc5a6 888 }
Rhyme 0:774324cbc5a6 889
Rhyme 0:774324cbc5a6 890 /****************************************************************************
Rhyme 0:774324cbc5a6 891 * Debug Methods *
Rhyme 0:774324cbc5a6 892 ****************************************************************************/
Rhyme 0:774324cbc5a6 893 /**
Rhyme 0:774324cbc5a6 894 * dumpBytes
Rhyme 0:774324cbc5a6 895 *
Rhyme 0:774324cbc5a6 896 * Dump a byte buffer to the debug log.
Rhyme 0:774324cbc5a6 897 */
Rhyme 0:774324cbc5a6 898 void afLib::dumpBytes(char *label, int len, uint8_t *bytes) {
Rhyme 0:774324cbc5a6 899 return ;
Rhyme 0:774324cbc5a6 900 printf("%s\n",label);
Rhyme 0:774324cbc5a6 901 for (int i = 0; i < len; i++) {
Rhyme 0:774324cbc5a6 902 if (i > 0) {
Rhyme 0:774324cbc5a6 903 printf(", ");
Rhyme 0:774324cbc5a6 904 }
Rhyme 0:774324cbc5a6 905 uint8_t b = bytes[i] & 0xff;
Rhyme 0:774324cbc5a6 906
Rhyme 0:774324cbc5a6 907 if (b < 0x10) {
Rhyme 0:774324cbc5a6 908 printf("0x02x", b);
Rhyme 0:774324cbc5a6 909 } else {
Rhyme 0:774324cbc5a6 910 //_theLog->print("0x");
Rhyme 0:774324cbc5a6 911 printf("0x02x",b);//, HEX);
Rhyme 0:774324cbc5a6 912 }
Rhyme 0:774324cbc5a6 913 }
Rhyme 0:774324cbc5a6 914 printf("\n");
Rhyme 0:774324cbc5a6 915 }
Rhyme 0:774324cbc5a6 916
Rhyme 0:774324cbc5a6 917 /**
Rhyme 0:774324cbc5a6 918 * printState
Rhyme 0:774324cbc5a6 919 *
Rhyme 0:774324cbc5a6 920 * Print the current state of the afLib state machine. For debugging, just remove the return statement.
Rhyme 0:774324cbc5a6 921 */
Rhyme 0:774324cbc5a6 922 void afLib::printState(int state) {
Rhyme 0:774324cbc5a6 923 return;
Rhyme 0:774324cbc5a6 924 switch (state) {
Rhyme 0:774324cbc5a6 925 case STATE_IDLE:
Rhyme 0:774324cbc5a6 926 printf("STATE_IDLE\n");
Rhyme 0:774324cbc5a6 927 break;
Rhyme 0:774324cbc5a6 928 case STATE_STATUS_SYNC:
Rhyme 0:774324cbc5a6 929 printf("STATE_STATUS_SYNC\n");
Rhyme 0:774324cbc5a6 930 break;
Rhyme 0:774324cbc5a6 931 case STATE_STATUS_ACK:
Rhyme 0:774324cbc5a6 932 printf("STATE_STATUS_ACK\n");
Rhyme 0:774324cbc5a6 933 break;
Rhyme 0:774324cbc5a6 934 case STATE_SEND_BYTES:
Rhyme 0:774324cbc5a6 935 printf("STATE_SEND_BYTES\n");
Rhyme 0:774324cbc5a6 936 break;
Rhyme 0:774324cbc5a6 937 case STATE_RECV_BYTES:
Rhyme 0:774324cbc5a6 938 printf("STATE_RECV_BYTES\n");
Rhyme 0:774324cbc5a6 939 break;
Rhyme 0:774324cbc5a6 940 case STATE_CMD_COMPLETE:
Rhyme 0:774324cbc5a6 941 printf("STATE_CMD_COMPLETE\n");
Rhyme 0:774324cbc5a6 942 break;
Rhyme 0:774324cbc5a6 943 default:
Rhyme 0:774324cbc5a6 944 printf("Unknown State!\n");
Rhyme 0:774324cbc5a6 945 break;
Rhyme 0:774324cbc5a6 946 }
Rhyme 0:774324cbc5a6 947 }
Rhyme 0:774324cbc5a6 948
Rhyme 0:774324cbc5a6 949 void afLib::printTransaction(uint8_t *rbytes, int len)
Rhyme 0:774324cbc5a6 950 {
Rhyme 0:774324cbc5a6 951 return;
Rhyme 0:774324cbc5a6 952 int i = 0;
Rhyme 0:774324cbc5a6 953 for(;i<=len;++i)
Rhyme 0:774324cbc5a6 954 {
Rhyme 0:774324cbc5a6 955 printf("0x%02x:",rbytes[i]);
Rhyme 0:774324cbc5a6 956 }
Rhyme 0:774324cbc5a6 957 printf("\n");
Rhyme 0:774324cbc5a6 958 }