I2C hang recover function added

Dependencies:   UniGraphic mbed vt100

In this version, check_i2c_pins function was added in edge_mgr.cpp.

プログラムの起動時、I2Cモジュールを初期化する前に、I2Cに使用するピンの電位を確認し
もし一方でも Low に張り付いていた場合、SCL を GPIO 出力に設定して 
所定回数 (I2C_UNLOCK_TRIAL_CYCLE) 反転させることにより、疑似リセットクロックを生成します。

その後は、通常の起動手順に復帰し、以降はこれまでと同様の動作をします。

Committer:
Rhyme
Date:
Tue Apr 03 08:30:29 2018 +0000
Revision:
0:d895cd1cd897
Initial I2C Pin force reset function added

Who changed what in which revision?

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