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