Added a GPIO to power on/off for external I2C sensor(s) (with LEDs)

Dependencies:   UniGraphic mbed vt100

18-Jun-2018 外部センサの電源オン・オフ機能は下位互換の為に無効になっていました。 この版で再度有効にしました。

Committer:
Rhyme
Date:
Mon Jun 18 01:56:00 2018 +0000
Revision:
1:8d65cfc3a2e2
Parent:
0:846e2321c637
External sensor power on/off function enabled. (Previously disabled)

Who changed what in which revision?

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