Color sensor reset at the end of calibration added. sensor id auto assignment was changed to be a fixed value assignment to avoid sensor id shift when some sensor is absent.

Dependencies:   UniGraphic mbed vt100

Committer:
Rhyme
Date:
Fri Feb 23 05:40:22 2018 +0000
Revision:
0:ce97f6d34336
color sensor reset was added at the end of calibration

Who changed what in which revision?

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