pwm period is now 200us instead of the default 20ms veml6040 config is now AF_BIT | TRIG_BIT

Dependencies:   mbed MMA8451Q USBDevice WakeUp vt100

Fork of afero_node_suntory_2017_06_15 by Orefatoi

Committer:
wataloh
Date:
Fri Jun 09 01:49:53 2017 +0000
Revision:
21:d03c7bbb9f37
Parent:
6:88cc04eb613a
Added the following process; When VEML6040 library returns NACK, forces software reset

Who changed what in which revision?

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