pwm period is now 200us instead of the default 20ms veml6040 config is now AF_BIT | TRIG_BIT
Dependencies: mbed MMA8451Q USBDevice WakeUp vt100
Fork of afero_node_suntory_2017_06_15 by
afLib.cpp
00001 /** 00002 * Copyright 2015 Afero, Inc. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "mbed.h" 00018 #include "afLib.h" 00019 #include "afErrors.h" 00020 #include "msg_types.h" 00021 00022 #define IS_MCU_ATTR(x) (x >= 0 && x < 1024) 00023 00024 static iafLib *_iaflib = NULL; 00025 00026 #define MAX_SYNC_RETRIES 10 00027 static long lastSync = 0; 00028 static int syncRetries = 0; 00029 00030 /** 00031 * create 00032 * 00033 * The public constructor for the afLib. This allows us to create the afLib object once and hold a reference to it. 00034 */ 00035 iafLib *iafLib::create(PinName mcuInterrupt, isr isrWrapper, 00036 onAttributeSet attrSet, onAttributeSetComplete attrSetComplete, afSPI *theSPI) 00037 { 00038 if (_iaflib == NULL) { 00039 _iaflib = new afLib( mcuInterrupt, isrWrapper, attrSet, attrSetComplete, theSPI); 00040 } 00041 00042 return _iaflib; 00043 } 00044 00045 void iafLib::destroy() 00046 { 00047 afLib *p = (afLib*)_iaflib; 00048 delete p; 00049 _iaflib = NULL; 00050 } 00051 /** 00052 * afLib 00053 * 00054 * The private constructor for the afLib. This one actually initializes the afLib and prepares it for use. 00055 */ 00056 afLib::afLib(PinName mcuInterrupt, isr isrWrapper, 00057 onAttributeSet attrSet, onAttributeSetComplete attrSetComplete, afSPI *theSPI) : fco(mcuInterrupt) 00058 { 00059 checkLastSync = new Timer(); 00060 checkLastSync->start(); 00061 queueInit(); 00062 _theSPI= theSPI; 00063 _request.p_value = NULL; 00064 00065 //_spiSettings = SPISettings(1000000, LSBFIRST, SPI_MODE0); 00066 _interrupts_pending = 0; 00067 _state = STATE_IDLE; 00068 00069 _writeCmd = NULL; 00070 _writeCmdOffset = 0; 00071 00072 _outstandingSetGetAttrId = 0; 00073 00074 _readCmd = NULL; 00075 _readCmdOffset = 0; 00076 _readBufferLen = 0; 00077 00078 _txStatus = new StatusCommand(); 00079 _rxStatus = new StatusCommand(); 00080 00081 _onAttrSet = attrSet; 00082 _onAttrSetComplete = attrSetComplete; 00083 _theSPI->begin(); 00084 00085 // AJS where does this get moved to?? 00086 #ifdef ARDUINO 00087 pinMode(mcuInterrupt, INPUT); 00088 attachInterrupt(mcuInterrupt, isrWrapper, FALLING); 00089 #endif 00090 fco.fall(isrWrapper); 00091 SERIAL_PRINT_DBG_ASR("afLib init done!!\n"); 00092 } 00093 //wsugi 20161128 00094 afLib::~afLib() 00095 { 00096 SERIAL_PRINT_DBG_ASR("deleted\n"); 00097 if(_readBuffer != NULL) 00098 { 00099 delete[] (_readBuffer); 00100 _readBuffer = NULL; 00101 } 00102 00103 if(_writeBuffer != NULL) 00104 { 00105 delete[] (_writeBuffer); 00106 _writeBuffer = NULL; 00107 } 00108 00109 if(_readCmd != NULL) 00110 { 00111 delete (_readCmd); 00112 _readCmd = NULL; 00113 } 00114 00115 if(_writeCmd != NULL) 00116 { 00117 delete (_writeCmd); 00118 _writeCmd = NULL; 00119 } 00120 00121 if(_txStatus != NULL) 00122 { 00123 delete (_txStatus); 00124 _txStatus = NULL; 00125 } 00126 00127 if(_rxStatus != NULL) 00128 { 00129 delete (_rxStatus); 00130 _rxStatus = NULL; 00131 } 00132 00133 for (int i = 0; i < REQUEST_QUEUE_SIZE; i++) 00134 { 00135 if (_requestQueue[i].p_value != NULL) 00136 { 00137 delete[] (_requestQueue[i].p_value); 00138 _requestQueue[i].p_value = NULL; 00139 } 00140 } 00141 00142 if(checkLastSync != NULL) 00143 { 00144 delete (checkLastSync); 00145 checkLastSync = NULL; 00146 } 00147 00148 _iaflib = NULL; 00149 } 00150 //wsugi 20161128 00151 /** 00152 * loop 00153 * 00154 * This is how the afLib gets time to run its state machine. This method should be called periodically from the 00155 * loop() function of the Arduino sketch. 00156 * This function pulls pending attribute operations from the queue. It takes approximately 4 calls to loop() to 00157 * complete one attribute operation. 00158 */ 00159 void afLib::loop(void) { 00160 if (isIdle()) 00161 { 00162 deathWish.attach(callback(WatchDogWrapper::getSelf(), &WatchDogWrapper::kick_the_bucket),10); 00163 // deathWish.attach(&afLib::kick_the_bucket,10); 00164 } 00165 if (isIdle() && (queueGet(&_request.messageType, &_request.requestId, &_request.attrId, &_request.valueLen, 00166 &_request.p_value) == afSUCCESS)) { 00167 switch (_request.messageType) { 00168 case MSG_TYPE_GET: 00169 doGetAttribute(_request.requestId, _request.attrId); 00170 break; 00171 00172 case MSG_TYPE_SET: 00173 doSetAttribute(_request.requestId, _request.attrId, _request.valueLen, _request.p_value); 00174 break; 00175 00176 case MSG_TYPE_UPDATE: 00177 doUpdateAttribute(_request.requestId, _request.attrId, 0, _request.valueLen, _request.p_value); 00178 break; 00179 00180 default: 00181 SERIAL_PRINT_DBG_ASR("%s\n","loop: request type!"); 00182 } 00183 } 00184 00185 if (_request.p_value != NULL) { 00186 delete[] (_request.p_value); //wsugi delete (_request.p_value); 00187 _request.p_value = NULL; 00188 } 00189 runStateMachine(); 00190 } 00191 00192 /** 00193 * updateIntsPending 00194 * 00195 * Interrupt-safe method for updating the interrupt count. This is called to increment and decrement the interrupt count 00196 * as interrupts are received and handled. 00197 */ 00198 void afLib::updateIntsPending(int amount) { 00199 fco.disable_irq(); 00200 _interrupts_pending += amount; 00201 fco.enable_irq(); 00202 } 00203 00204 /** 00205 * sendCommand 00206 * 00207 * This increments the interrupt count to kick off the state machine in the next call to loop(). 00208 */ 00209 void afLib::sendCommand(void) { 00210 fco.disable_irq(); 00211 if (_interrupts_pending == 0 && _state == STATE_IDLE) { 00212 updateIntsPending(1); 00213 } 00214 fco.enable_irq(); 00215 } 00216 00217 /** 00218 * getAttribute 00219 * 00220 * The public getAttribute method. This method queues the operation and returns immediately. Applications must call 00221 * loop() for the operation to complete. 00222 */ 00223 int afLib::getAttribute(const uint16_t attrId) { 00224 _requestId++; 00225 uint8_t dummy; // This value isn't actually used. 00226 return queuePut(MSG_TYPE_GET, _requestId++, attrId, 0, &dummy); 00227 } 00228 00229 /** 00230 * The many moods of setAttribute 00231 * 00232 * These are the public versions of the setAttribute method. 00233 * These methods queue the operation and return immediately. Applications must call loop() for the operation to complete. 00234 */ 00235 int afLib::setAttributeBool(const uint16_t attrId, const bool value) { 00236 _requestId++; 00237 uint8_t val = value ? 1 : 0; 00238 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(val), 00239 (uint8_t *)&val); 00240 } 00241 00242 int afLib::setAttribute8(const uint16_t attrId, const int8_t value) { 00243 _requestId++; 00244 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value), 00245 (uint8_t *)&value); 00246 } 00247 00248 int afLib::setAttribute16(const uint16_t attrId, const int16_t value) { 00249 _requestId++; 00250 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value), 00251 (uint8_t *) &value); 00252 } 00253 00254 int afLib::setAttribute32(const uint16_t attrId, const int32_t value) { 00255 _requestId++; 00256 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value), 00257 (uint8_t *) &value); 00258 } 00259 00260 int afLib::setAttribute64(const uint16_t attrId, const int64_t value) { 00261 _requestId++; 00262 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, sizeof(value), 00263 (uint8_t *) &value); 00264 } 00265 00266 int afLib::setAttribute(const uint16_t attrId, const string &value) { 00267 _requestId++; 00268 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, value.length(), 00269 (uint8_t *) value.c_str()); 00270 } 00271 00272 int afLib::setAttribute(const uint16_t attrId, const uint16_t valueLen, const char *value) { 00273 if (valueLen > MAX_ATTRIBUTE_SIZE) { 00274 return afERROR_INVALID_PARAM; 00275 } 00276 00277 if (value == NULL) { 00278 return afERROR_INVALID_PARAM; 00279 } 00280 00281 _requestId++; 00282 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, valueLen, 00283 (const uint8_t *) value); 00284 } 00285 00286 int afLib::setAttribute(const uint16_t attrId, const uint16_t valueLen, const uint8_t *value) { 00287 if (valueLen > MAX_ATTRIBUTE_SIZE) { 00288 return afERROR_INVALID_PARAM; 00289 } 00290 00291 if (value == NULL) { 00292 return afERROR_INVALID_PARAM; 00293 } 00294 00295 _requestId++; 00296 return queuePut(IS_MCU_ATTR(attrId) ? MSG_TYPE_UPDATE : MSG_TYPE_SET, _requestId, attrId, valueLen, value); 00297 } 00298 00299 int afLib::setAttributeComplete(uint8_t requestId, const uint16_t attrId, const uint16_t valueLen, const uint8_t *value) { 00300 if (valueLen > MAX_ATTRIBUTE_SIZE) { 00301 return afERROR_INVALID_PARAM; 00302 } 00303 00304 if (value == NULL) { 00305 return afERROR_INVALID_PARAM; 00306 } 00307 00308 return queuePut(MSG_TYPE_UPDATE, requestId, attrId, valueLen, value); 00309 } 00310 00311 /** 00312 * doGetAttribute 00313 * 00314 * The private version of getAttribute. This version actually calls sendCommand() to kick off the state machine and 00315 * execute the operation. 00316 */ 00317 int afLib::doGetAttribute(uint8_t requestId, uint16_t attrId) { 00318 if (_interrupts_pending > 0 || _writeCmd != NULL) { 00319 return afERROR_BUSY; 00320 } 00321 00322 _writeCmd = new Command(requestId, MSG_TYPE_GET, attrId); 00323 if (!_writeCmd->isValid()) { 00324 SERIAL_PRINT_DBG_ASR("getAttribute invalid command:"); 00325 _writeCmd->dumpBytes(); 00326 _writeCmd->dump(); 00327 delete (_writeCmd); 00328 _writeCmd = NULL; 00329 return afERROR_INVALID_COMMAND; 00330 } 00331 00332 _outstandingSetGetAttrId = attrId; 00333 00334 // Start the transmission. 00335 sendCommand(); 00336 00337 return afSUCCESS; 00338 } 00339 00340 /** 00341 * doSetAttribute 00342 * 00343 * The private version of setAttribute. This version actually calls sendCommand() to kick off the state machine and 00344 * execute the operation. 00345 */ 00346 int afLib::doSetAttribute(uint8_t requestId, uint16_t attrId, uint16_t valueLen, uint8_t *value) { 00347 if (_interrupts_pending > 0 || _writeCmd != NULL) { 00348 return afERROR_BUSY; 00349 } 00350 _writeCmd = new Command(requestId, MSG_TYPE_SET, attrId, valueLen, value); 00351 if (!_writeCmd->isValid()) { 00352 SERIAL_PRINT_DBG_ASR("setAttributeComplete invalid command:"); 00353 _writeCmd->dumpBytes(); 00354 _writeCmd->dump(); 00355 delete (_writeCmd); 00356 _writeCmd = NULL; 00357 return afERROR_INVALID_COMMAND; 00358 } 00359 00360 _outstandingSetGetAttrId = attrId; 00361 00362 // Start the transmission. 00363 sendCommand(); 00364 00365 return afSUCCESS; 00366 } 00367 00368 /** 00369 * doUpdateAttribute 00370 * 00371 * setAttribute calls on MCU attributes turn into updateAttribute calls. See documentation on the SPI protocol for 00372 * more information. This method calls sendCommand() to kick off the state machine and execute the operation. 00373 */ 00374 int afLib::doUpdateAttribute(uint8_t requestId, uint16_t attrId, uint8_t status, uint16_t valueLen, uint8_t *value) { 00375 if (_interrupts_pending > 0 || _writeCmd != NULL) { 00376 return afERROR_BUSY; 00377 } 00378 00379 _writeCmd = new Command(requestId, MSG_TYPE_UPDATE, attrId, status, 3 /* MCU Set it */, valueLen, value); 00380 if (!_writeCmd->isValid()) { 00381 SERIAL_PRINT_DBG_ASR("updateAttribute invalid command:"); 00382 _writeCmd->dumpBytes(); 00383 _writeCmd->dump(); 00384 delete (_writeCmd); 00385 return afERROR_INVALID_COMMAND; 00386 } 00387 00388 // Start the transmission. 00389 sendCommand(); 00390 00391 return afSUCCESS; 00392 } 00393 00394 /** 00395 * parseCommand 00396 * 00397 * A debug method for parsing a string into a command. This is not required for library operation and is only supplied 00398 * as an example of how to execute attribute operations from a command line interface. 00399 */ 00400 #ifdef ATTRIBUTE_CLI 00401 int afLib::parseCommand(const char *cmd) { 00402 if (_interrupts_pending > 0 || _writeCmd != NULL) { 00403 _theLog->print("Busy: "); 00404 _theLog->print(_interrupts_pending); 00405 _theLog->print(", "); 00406 _theLog->println(_writeCmd != NULL); 00407 return afERROR_BUSY; 00408 } 00409 00410 int reqId = _requestId++; 00411 _writeCmd = new Command(_theLog,reqId, cmd); 00412 if (!_writeCmd->isValid()) { 00413 _theLog->print("BAD: "); 00414 _theLog->println(cmd); 00415 _writeCmd->dumpBytes(); 00416 _writeCmd->dump(); 00417 delete (_writeCmd); 00418 _writeCmd = NULL; 00419 return afERROR_INVALID_COMMAND; 00420 } 00421 00422 // Start the transmission. 00423 sendCommand(); 00424 00425 return afSUCCESS; 00426 } 00427 #endif 00428 00429 /** 00430 * runStateMachine 00431 * 00432 * The state machine for afLib. This state machine is responsible for implementing the KSP SPI protocol and executing 00433 * attribute operations. 00434 * This method is run: 00435 * 1. In response to receiving an interrupt from the ASR-1. 00436 * 2. When an attribute operation is pulled out of the queue and executed. 00437 */ 00438 void afLib::runStateMachine(void) { 00439 if (_interrupts_pending > 0) { 00440 switch (_state) { 00441 case STATE_IDLE: 00442 //deathWish.attach(&afLib::kick_the_bucket,10); 00443 onStateIdle(); 00444 return; 00445 00446 case STATE_STATUS_SYNC: 00447 onStateSync(); 00448 break; 00449 00450 case STATE_STATUS_ACK: 00451 onStateAck(); 00452 break; 00453 00454 case STATE_SEND_BYTES: 00455 onStateSendBytes(); 00456 break; 00457 00458 case STATE_RECV_BYTES: 00459 onStateRecvBytes(); 00460 break; 00461 00462 case STATE_CMD_COMPLETE: 00463 onStateCmdComplete(); 00464 break; 00465 } 00466 00467 updateIntsPending(-1); 00468 } else { 00469 if (syncRetries > 0 && syncRetries < MAX_SYNC_RETRIES && checkLastSync->read_ms() - lastSync > 1000) { 00470 updateIntsPending(1); 00471 } else if (syncRetries >= MAX_SYNC_RETRIES) { 00472 SERIAL_PRINT_DBG_ASR("No response from ASR-1 - does profile have MCU enabled?\n"); 00473 #if defined(TARGET_KL25Z) 00474 WatchDogWrapper::getSelf()->kick_the_bucket(); 00475 #endif //TARGET_KL25Z 00476 syncRetries = 0; 00477 _state = STATE_IDLE; 00478 } 00479 } 00480 } 00481 00482 /** 00483 * onStateIdle 00484 * 00485 * If there is a command to be written, update the bytes to send. Otherwise we're sending a zero-sync message. 00486 * Either way advance the state to send a sync message. 00487 */ 00488 void afLib::onStateIdle(void) { 00489 if (_writeCmd != NULL) { 00490 // Include 2 bytes for length 00491 _bytesToSend = _writeCmd->getSize() + 2; 00492 } else { 00493 _bytesToSend = 0; 00494 } 00495 _state = STATE_STATUS_SYNC; 00496 printState(_state); 00497 } 00498 00499 /** 00500 * onStateSync 00501 * 00502 * Write a sync message over SPI to let the ASR-1 know that we want to send some data. 00503 * Check for a "collision" which occurs if the ASR-1 is trying to send us data at the same time. 00504 */ 00505 void afLib::onStateSync(void) { 00506 int result; 00507 00508 _txStatus->setAck(false); 00509 _txStatus->setBytesToSend(_bytesToSend); 00510 _txStatus->setBytesToRecv(0); 00511 00512 result = exchangeStatus(_txStatus, _rxStatus); 00513 00514 if (result == afSUCCESS && _rxStatus->isValid() && inSync(_txStatus, _rxStatus)) { 00515 syncRetries = 0; // Flag that sync completed. 00516 _state = STATE_STATUS_ACK; 00517 if (_txStatus->getBytesToSend() == 0 && _rxStatus->getBytesToRecv() > 0) { 00518 _bytesToRecv = _rxStatus->getBytesToRecv(); 00519 } 00520 } else { 00521 // Try resending the preamble 00522 _state = STATE_STATUS_SYNC; 00523 lastSync = checkLastSync->read_ms(); 00524 syncRetries++; 00525 // _txStatus->dumpBytes(); 00526 // _rxStatus->dumpBytes(); 00527 } 00528 printState(_state); 00529 } 00530 00531 /** 00532 * onStateAck 00533 * 00534 * Acknowledge the previous sync message and advance the state. 00535 * If there are bytes to send, advance to send bytes state. 00536 * If there are bytes to receive, advance to receive bytes state. 00537 * Otherwise it was a zero-sync so advance to command complete. 00538 */ 00539 void afLib::onStateAck(void) { 00540 int result; 00541 00542 _txStatus->setAck(true); 00543 _txStatus->setBytesToRecv(_rxStatus->getBytesToRecv()); 00544 _bytesToRecv = _rxStatus->getBytesToRecv(); 00545 result = writeStatus(_txStatus); 00546 if (result != afSUCCESS) { 00547 _state = STATE_STATUS_SYNC; 00548 printState(_state); 00549 return; 00550 } 00551 if (_bytesToSend > 0) { 00552 _writeBufferLen = (uint16_t) _writeCmd->getSize(); 00553 _writeBuffer = new uint8_t[_bytesToSend]; 00554 memcpy(_writeBuffer, (uint8_t * ) & _writeBufferLen, 2); 00555 _writeCmd->getBytes(&_writeBuffer[2]); 00556 _state = STATE_SEND_BYTES; 00557 } else if (_bytesToRecv > 0) { 00558 _state = STATE_RECV_BYTES; 00559 } else { 00560 _state = STATE_CMD_COMPLETE; 00561 } 00562 printState(_state); 00563 } 00564 00565 /** 00566 * onStateSendBytes 00567 * 00568 * Send the required number of bytes to the ASR-1 and then advance to command complete. 00569 */ 00570 void afLib::onStateSendBytes(void) { 00571 // _theLog->print("send bytes: "); _theLog->println(_bytesToSend); 00572 sendBytes(); 00573 00574 if (_bytesToSend == 0) { 00575 _writeBufferLen = 0; 00576 delete[] (_writeBuffer); //wsugi delete (_writeBuffer); 00577 _writeBuffer = NULL; 00578 _state = STATE_CMD_COMPLETE; 00579 printState(_state); 00580 } 00581 } 00582 00583 /** 00584 * onStateRecvBytes 00585 * 00586 * Receive the required number of bytes from the ASR-1 and then advance to command complete. 00587 */ 00588 void afLib::onStateRecvBytes(void) { 00589 // _theLog->print("receive bytes: "); _theLog->println(_bytesToRecv); 00590 recvBytes(); 00591 if (_bytesToRecv == 0) { 00592 _state = STATE_CMD_COMPLETE; 00593 printState(_state); 00594 _readCmd = new Command(_readBufferLen, &_readBuffer[2]); 00595 delete[] (_readBuffer); //wsugi delete (_readBuffer); 00596 _readBuffer = NULL; 00597 } 00598 } 00599 00600 /** 00601 * onStateCmdComplete 00602 * 00603 * Call the appropriate sketch callback to report the result of the command. 00604 * Clear the command object and go back to waiting for the next interrupt or command. 00605 */ 00606 void afLib::onStateCmdComplete(void) { 00607 _state = STATE_IDLE; 00608 printState(_state); 00609 if (_readCmd != NULL) { 00610 uint8_t *val = new uint8_t[_readCmd->getValueLen()]; 00611 _readCmd->getValue(val); 00612 00613 switch (_readCmd->getCommand()) { 00614 case MSG_TYPE_SET: 00615 _onAttrSet(_readCmd->getReqId(), _readCmd->getAttrId(), _readCmd->getValueLen(), val); 00616 break; 00617 00618 case MSG_TYPE_UPDATE: 00619 if (_readCmd->getAttrId() == _outstandingSetGetAttrId) { 00620 _outstandingSetGetAttrId = 0; 00621 } 00622 _onAttrSetComplete(_readCmd->getReqId(), _readCmd->getAttrId(), _readCmd->getValueLen(), val); 00623 break; 00624 00625 default: 00626 break; 00627 } 00628 delete[] (val); //wsugi delete (val); 00629 delete (_readCmd); 00630 _readCmdOffset = 0; 00631 _readCmd = NULL; 00632 } 00633 00634 if (_writeCmd != NULL) { 00635 // Fake a callback here for MCU attributes as we don't get one from the module. 00636 if (_writeCmd->getCommand() == MSG_TYPE_UPDATE && IS_MCU_ATTR(_writeCmd->getAttrId())) { 00637 _onAttrSetComplete(_writeCmd->getReqId(), _writeCmd->getAttrId(), _writeCmd->getValueLen(), _writeCmd->getValueP()); 00638 } 00639 delete (_writeCmd); 00640 _writeCmdOffset = 0; 00641 _writeCmd = NULL; 00642 } 00643 } 00644 00645 /** 00646 * exchangeStatus 00647 * 00648 * Write a status command object to the ASR-1 and clock in a status object from the ASR-1 at the same time. 00649 */ 00650 int afLib::exchangeStatus(StatusCommand *tx, StatusCommand *rx) { 00651 int result = afSUCCESS; 00652 uint16_t len = tx->getSize(); 00653 int bytes[len]; 00654 char rbytes[len+1]; 00655 int index = 0; 00656 tx->getBytes(bytes); 00657 00658 // _theSPI->beginSPI(); 00659 00660 for (int i=0;i<len;i++) 00661 { 00662 rbytes[i]=bytes[i]; 00663 } 00664 rbytes[len]=tx->getChecksum(); 00665 00666 printTransaction((uint8_t*)rbytes,len+1); 00667 00668 _theSPI->beginSPI(); 00669 _theSPI->transfer(rbytes,len+1); 00670 _theSPI->endSPI(); 00671 00672 printTransaction((uint8_t*)rbytes,len+1); 00673 00674 uint8_t cmd = bytes[index++]; 00675 if (cmd != 0x30 && cmd != 0x31) { 00676 SERIAL_PRINT_DBG_ASR("exchangeStatus bad cmd: 0x%02x\n",cmd); 00677 result = afERROR_INVALID_COMMAND; 00678 } 00679 00680 rx->setBytesToSend(rbytes[index + 0] | (rbytes[index + 1] << 8)); 00681 rx->setBytesToRecv(rbytes[index + 2] | (rbytes[index + 3] << 8)); 00682 rx->setChecksum(rbytes[index+4]); 00683 //_theSPI->endSPI(); 00684 return result; 00685 } 00686 00687 /** 00688 * inSync 00689 * 00690 * Check to make sure the Arduino and the ASR-1 aren't trying to send data at the same time. 00691 * Return true only if there is no collision. 00692 */ 00693 bool afLib::inSync(StatusCommand *tx, StatusCommand *rx) { 00694 return (tx->getBytesToSend() == 0 && rx->getBytesToRecv() == 0) || 00695 (tx->getBytesToSend() > 0 && rx->getBytesToRecv() == 0) || 00696 (tx->getBytesToSend() == 0 && rx->getBytesToRecv() > 0); 00697 } 00698 00699 /** 00700 * writeStatus 00701 * 00702 * Write a status command to the ASR-1 and ignore the result. If you want to read bytes at the same time, use 00703 * exchangeStatus instead. 00704 */ 00705 int afLib::writeStatus(StatusCommand *c) { 00706 int result = afSUCCESS; 00707 uint16_t len = c->getSize(); 00708 int bytes[len]; 00709 char rbytes[len+1]; 00710 int index = 0; 00711 c->getBytes(bytes); 00712 00713 _theSPI->beginSPI(); 00714 00715 for (int i=0;i<len;i++) 00716 { 00717 rbytes[i]=bytes[i]; 00718 } 00719 rbytes[len]=c->getChecksum(); 00720 printTransaction((uint8_t*)rbytes,len+1); 00721 _theSPI->transfer(rbytes,len+1); 00722 printTransaction((uint8_t*)rbytes,len+1); 00723 uint8_t cmd = rbytes[index++]; 00724 if (cmd != 0x30 && cmd != 0x31) { 00725 SERIAL_PRINT_DBG_ASR("writeStatus bad cmd: 0x%02x\n",cmd); 00726 result = afERROR_INVALID_COMMAND; 00727 } 00728 00729 00730 _theSPI->endSPI(); 00731 00732 // c->dump(); 00733 // c->dumpBytes(); 00734 00735 return result; 00736 } 00737 00738 /** 00739 * sendBytes 00740 * 00741 * Send the specified number of data bytes to the ASR-1. Do this in chunks of SPI_FRAME_LEN bytes. 00742 */ 00743 void afLib::sendBytes() { 00744 uint16_t len = _bytesToSend > SPI_FRAME_LEN ? SPI_FRAME_LEN : _bytesToSend; 00745 uint8_t bytes[SPI_FRAME_LEN]; 00746 memset(bytes, 0xff, sizeof(bytes)); 00747 00748 memcpy(bytes, &_writeBuffer[_writeCmdOffset], len); 00749 00750 _theSPI->beginSPI(); 00751 printTransaction(bytes,len+1); 00752 _theSPI->transfer((char *)bytes,len); 00753 printTransaction(bytes,len+1); 00754 _theSPI->endSPI(); 00755 00756 // dumpBytes("Sending:", len, bytes); 00757 00758 _writeCmdOffset += len; 00759 _bytesToSend -= len; 00760 } 00761 00762 /** 00763 * recvBytes 00764 * 00765 * Receive the specified number of data bytes from the ASR-1. Do this in chunks of SPI_FRAME_LEN bytes. 00766 */ 00767 void afLib::recvBytes() { 00768 uint16_t len = _bytesToRecv > SPI_FRAME_LEN ? SPI_FRAME_LEN : _bytesToRecv; 00769 00770 if (_readCmdOffset == 0) { 00771 _readBufferLen = _bytesToRecv; 00772 _readBuffer = new uint8_t[_readBufferLen]; 00773 } 00774 00775 _theSPI->beginSPI(); 00776 00777 00778 char * start =(char*)_readBuffer + _readCmdOffset; 00779 printTransaction((uint8_t*)start,len+1); 00780 _theSPI->transfer(start,len); 00781 printTransaction((uint8_t*)start,len+1); 00782 00783 _theSPI->endSPI(); 00784 00785 // dumpBytes("Receiving:", len, _readBuffer); 00786 00787 _readCmdOffset += len; 00788 _bytesToRecv -= len; 00789 } 00790 00791 /** 00792 * isIdle 00793 * 00794 * Provide a way for the sketch to know if we're idle. Returns true if there are no attribute operations in progress. 00795 */ 00796 bool afLib::isIdle() { 00797 return _interrupts_pending == 0 && _state == STATE_IDLE && _outstandingSetGetAttrId == 0; 00798 } 00799 00800 /** 00801 * These methods are required to disable/enable interrupts for the Linux version of afLib. 00802 * They are no-ops on Arduino. 00803 */ 00804 #ifndef ARDUINO 00805 void noInterrupts(){} 00806 void interrupts(){} 00807 #endif 00808 00809 void afLib::mcuISR() { 00810 // _theLog->println("mcu"); 00811 updateIntsPending(1); 00812 } 00813 00814 /**************************************************************************** 00815 * Queue Methods * 00816 ****************************************************************************/ 00817 /** 00818 * queueInit 00819 * 00820 * Create a small queue to prevent flooding the ASR-1 with attribute operations. 00821 * The initial size is small to allow running on small boards like UNO. 00822 * Size can be increased on larger boards. 00823 */ 00824 void afLib::queueInit() { 00825 for (int i = 0; i < REQUEST_QUEUE_SIZE; i++) { 00826 _requestQueue[i].p_value = NULL; 00827 } 00828 } 00829 00830 /** 00831 * queuePut 00832 * 00833 * Add an item to the end of the queue. Return an error if we're out of space in the queue. 00834 */ 00835 int afLib::queuePut(uint8_t messageType, uint8_t requestId, const uint16_t attributeId, uint16_t valueLen, 00836 const uint8_t *value) { 00837 for (int i = 0; i < REQUEST_QUEUE_SIZE; i++) { 00838 if (_requestQueue[i].p_value == NULL) { 00839 _requestQueue[i].messageType = messageType; 00840 _requestQueue[i].attrId = attributeId; 00841 _requestQueue[i].requestId = requestId; 00842 _requestQueue[i].valueLen = valueLen; 00843 _requestQueue[i].p_value = new uint8_t[valueLen]; 00844 memcpy(_requestQueue[i].p_value, value, valueLen); 00845 return afSUCCESS; 00846 } 00847 } 00848 00849 return afERROR_QUEUE_OVERFLOW; 00850 } 00851 00852 /** 00853 * queueGet 00854 * 00855 * Pull and return the oldest item from the queue. Return an error if the queue is empty. 00856 */ 00857 int afLib::queueGet(uint8_t *messageType, uint8_t *requestId, uint16_t *attributeId, uint16_t *valueLen, 00858 uint8_t **value) { 00859 for (int i = 0; i < REQUEST_QUEUE_SIZE; i++) { 00860 if (_requestQueue[i].p_value != NULL) { 00861 *messageType = _requestQueue[i].messageType; 00862 *attributeId = _requestQueue[i].attrId; 00863 *requestId = _requestQueue[i].requestId; 00864 *valueLen = _requestQueue[i].valueLen; 00865 *value = new uint8_t[*valueLen]; 00866 memcpy(*value, _requestQueue[i].p_value, *valueLen); 00867 delete[] (_requestQueue[i].p_value); //wsugi delete (_requestQueue[i].p_value); 00868 _requestQueue[i].p_value = NULL; 00869 return afSUCCESS; 00870 } 00871 } 00872 00873 return afERROR_QUEUE_UNDERFLOW; 00874 } 00875 00876 /**************************************************************************** 00877 * Debug Methods * 00878 ****************************************************************************/ 00879 /** 00880 * dumpBytes 00881 * 00882 * Dump a byte buffer to the debug log. 00883 */ 00884 void afLib::dumpBytes(char *label, int len, uint8_t *bytes) { 00885 SERIAL_PRINT_DBG_ASR("%s\n",label); 00886 for (int i = 0; i < len; i++) { 00887 if (i > 0) { 00888 SERIAL_PRINT_DBG_ASR(", "); 00889 } 00890 uint8_t b = bytes[i] & 0xff; 00891 00892 if (b < 0x10) { 00893 SERIAL_PRINT_DBG_ASR("0x02x", b); 00894 } else { 00895 //_theLog->print("0x"); 00896 SERIAL_PRINT_DBG_ASR("0x02x",b);//, HEX); 00897 } 00898 } 00899 SERIAL_PRINT_DBG_ASR("\n"); 00900 } 00901 00902 /** 00903 * printState 00904 * 00905 * Print the current state of the afLib state machine. For debugging, just remove the return statement. 00906 */ 00907 void afLib::printState(int state) { 00908 // return; 00909 switch (state) { 00910 case STATE_IDLE: 00911 SERIAL_PRINT_DBG_ASR("STATE_IDLE\n"); 00912 break; 00913 case STATE_STATUS_SYNC: 00914 SERIAL_PRINT_DBG_ASR("STATE_STATUS_SYNC\n"); 00915 break; 00916 case STATE_STATUS_ACK: 00917 SERIAL_PRINT_DBG_ASR("STATE_STATUS_ACK\n"); 00918 break; 00919 case STATE_SEND_BYTES: 00920 SERIAL_PRINT_DBG_ASR("STATE_SEND_BYTES\n"); 00921 break; 00922 case STATE_RECV_BYTES: 00923 SERIAL_PRINT_DBG_ASR("STATE_RECV_BYTES\n"); 00924 break; 00925 case STATE_CMD_COMPLETE: 00926 SERIAL_PRINT_DBG_ASR("STATE_CMD_COMPLETE\n"); 00927 break; 00928 default: 00929 SERIAL_PRINT_DBG_ASR("Unknown State!\n"); 00930 break; 00931 } 00932 } 00933 00934 void afLib::printTransaction(uint8_t *rbytes, int len) 00935 { 00936 //return; 00937 int i = 0; 00938 for(;i<=len;++i) 00939 { 00940 SERIAL_PRINT_DBG_ASR("0x%02x:",rbytes[i]); 00941 } 00942 SERIAL_PRINT_DBG_ASR("\n"); 00943 }
Generated on Thu Jul 14 2022 06:24:36 by 1.7.2