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