Orefatoi / Mbed 2 deprecated afero_poc15_171201

Dependencies:   mbed vt100

Committer:
Rhyme
Date:
Fri Dec 01 06:16:31 2017 +0000
Revision:
0:f0de320e23ac
OLED display for GAS pressure started working

Who changed what in which revision?

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