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