Ecode_t COM_ReadDataTimeout(COM_Port_t port, uint8_t *data, uint16_t length, uint16_t *bytesRead, uint16_t firstByteTimeout, uint16_t subsequentByteTimeout) { if (checkValidPort(port)==false) { return EMBER_ERR_FATAL; } uint16_t bytesReadInternal = 0; Ecode_t status; uint16_t timeout = firstByteTimeout; uint16_t startTime = halCommonGetInt16uMillisecondTick(); // loop until we read the max number of bytes or the timeout elapses while (bytesReadInternal < length && elapsedTimeInt16u(startTime,halCommonGetInt16uMillisecondTick()) < timeout) { status = COM_ReadByte(port, data); switch (status) { case EMBER_SUCCESS: ++data; ++bytesReadInternal; // reset timer and timeout for next character startTime = halCommonGetInt16uMillisecondTick(); timeout = subsequentByteTimeout; break; case EMBER_SERIAL_RX_EMPTY: // empty queue is not an error for us, we just want to keep waiting break; default: // only store number of bytes read if the caller provided a non-NULL pointer if (bytesRead) { *bytesRead = bytesReadInternal; } return status; } } // only store number of bytes read if the caller provided a non-NULL pointer if (bytesRead) { *bytesRead = bytesReadInternal; } return bytesReadInternal == length ? EMBER_SUCCESS : EMBER_SERIAL_RX_EMPTY; }
static void rescheduleUserControlEvent(void) { // Look at all the active records and figure out when to schedule the event. // If any record should have been sent in the past, we immediately schedule // the event to send it as soon as possible. Otherwise, we find the record // that has to be repeated soonest and schedule based on that. If there are // no active records, we are done and cancel the event. uint16_t nowMs = halCommonGetInt16uMillisecondTick(); uint16_t delayMs = MAX_INT16U_VALUE; uint8_t i; for (i = 0; i < COUNTOF(records); i++) { if (records[i].pairingIndex != 0xFF) { if (timeGTorEqualInt16u(nowMs, records[i].timeMs)) { delayMs = 0; break; } else { uint16_t remainingMs = elapsedTimeInt16u(nowMs, records[i].timeMs); if (remainingMs < delayMs) { delayMs = remainingMs; } } } } if (delayMs == MAX_INT16U_VALUE) { emberEventControlSetInactive(emberAfPluginRf4ceZrc11OutgoingUserControlEventControl); } else if (delayMs == 0) { emberEventControlSetActive(emberAfPluginRf4ceZrc11OutgoingUserControlEventControl); } else { emberEventControlSetDelayMS(emberAfPluginRf4ceZrc11OutgoingUserControlEventControl, delayMs); } }
static EmberStatus sendAndReschedule(UserControlRecord *record) { // Construct the message and send it. EmberStatus status; emAfRf4ceZrc11BufferLength = 0; emAfRf4ceZrc11Buffer[emAfRf4ceZrc11BufferLength++] = record->commandCode; emAfRf4ceZrc11Buffer[emAfRf4ceZrc11BufferLength++] = record->rcCommandCode; MEMCOPY(emAfRf4ceZrc11Buffer + emAfRf4ceZrc11BufferLength, record->rcCommandPayload, record->rcCommandPayloadLength); emAfRf4ceZrc11BufferLength += record->rcCommandPayloadLength; status = emAfRf4ceZrc11Send(record->pairingIndex); // If this was a release, we are done and clear the record. Otherwise, a // press becomes a repeat (and a repeat stays a repeat). The next time to // send this record depends on the key repeat interval. Once we adjust this // record, we reschedule. if (record->commandCode == EMBER_AF_RF4CE_ZRC_COMMAND_USER_CONTROL_RELEASED) { record->pairingIndex = 0xFF; } else { record->commandCode = EMBER_AF_RF4CE_ZRC_COMMAND_USER_CONTROL_REPEATED; record->timeMs = (halCommonGetInt16uMillisecondTick() + EMBER_AF_PLUGIN_RF4CE_ZRC11_KEY_REPEAT_INTERVAL_MS); } rescheduleUserControlEvent(); return status; }
// Hal Button ISR Callback // This callback is called by the framework whenever a button is pressed on the // device. This callback is called within ISR context. void emberAfHalButtonIsrCallback(int8u button, int8u state) { if ((button == BUTTON0 || button == BUTTON1) && state == BUTTON_PRESSED && !emberEventControlGetActive(buttonEventControl)) { buttonPressTime = halCommonGetInt16uMillisecondTick(); emberEventControlSetActive(buttonEventControl); } }
void buttonEventHandler(void) { emberEventControlSetInactive(buttonEventControl); EmberNetworkStatus state = emberNetworkState(); if (state == EMBER_JOINED_NETWORK) { emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_CLIENT_TO_SERVER), ZCL_ON_OFF_CLUSTER_ID, (on ? ZCL_OFF_COMMAND_ID : ZCL_ON_COMMAND_ID), ""); emberAfGetCommandApsFrame()->profileId = emberAfProfileIdFromIndex(0); emberAfGetCommandApsFrame()->sourceEndpoint = emberAfEndpointFromIndex(0); emberAfGetCommandApsFrame()->destinationEndpoint = EMBER_BROADCAST_ENDPOINT; if (emberAfSendCommandBroadcast(EMBER_SLEEPY_BROADCAST_ADDRESS) == EMBER_SUCCESS) { on = !on; } else { halPlayTune_P(sadTune, TRUE); } } else if (state == EMBER_NO_NETWORK) { halPlayTune_P((emberAfZllInitiateTouchLink() == EMBER_SUCCESS ? waitTune : sadTune), TRUE); } else { int16u elapsed = elapsedTimeInt16u(buttonPressTime, halCommonGetInt16uMillisecondTick()); if (REPAIR_LIMIT_MS < elapsedTimeInt16u(buttonPressTime, halCommonGetInt16uMillisecondTick())) { halPlayTune_P(sadTune, TRUE); } else { if (state == EMBER_JOINED_NETWORK_NO_PARENT && !emberStackIsPerformingRejoin()) { halPlayTune_P((emberFindAndRejoinNetwork(TRUE, 0) == EMBER_SUCCESS ? waitTune : sadTune), TRUE); } emberEventControlSetDelayMS(buttonEventControl, REPAIR_DELAY_MS); } } }
void emberAfPluginRf4ceZrc11OutgoingUserControlEventHandler(void) { // We expect the user control event to fire only when there is something to // send. We find it, send it, and reschedule. uint16_t nowMs = halCommonGetInt16uMillisecondTick(); uint8_t i, index = 0xFF; for (i = 0; i < COUNTOF(records); i++) { if (records[i].pairingIndex != 0xFF && timeGTorEqualInt16u(nowMs, records[i].timeMs)) { index = i; break; } } assert(index != 0xFF); sendAndReschedule(&records[index]); }
void buttonEventHandler(void) { emberEventControlSetInactive(buttonEventControl); if (halButtonState(BUTTON0) == BUTTON_PRESSED) { EmberNetworkStatus state = emberNetworkState(); if (state == EMBER_JOINED_NETWORK) { emberAfFillExternalBuffer((ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_CLIENT_TO_SERVER), ZCL_ON_OFF_CLUSTER_ID, (on ? ZCL_OFF_COMMAND_ID : ZCL_ON_COMMAND_ID), ""); emberAfGetCommandApsFrame()->profileId = emberAfPrimaryProfileId(); emberAfGetCommandApsFrame()->sourceEndpoint = emberAfPrimaryEndpoint(); emberAfGetCommandApsFrame()->destinationEndpoint = EMBER_BROADCAST_ENDPOINT; if (emberAfSendCommandUnicastToBindings() == EMBER_SUCCESS) { on = !on; } else { halPlayTune_P(sadTune, TRUE); } } else if (state == EMBER_NO_NETWORK) { halPlayTune_P((emberAfStartSearchForJoinableNetwork() == EMBER_SUCCESS ? waitTune : sadTune), TRUE); } else { if (REPAIR_LIMIT_MS < elapsedTimeInt16u(buttonPressTime, halCommonGetInt16uMillisecondTick())) { halPlayTune_P(sadTune, TRUE); } else { if (state == EMBER_JOINED_NETWORK_NO_PARENT && !emberStackIsPerformingRejoin()) { halPlayTune_P((emberFindAndRejoinNetwork(TRUE, 0) == EMBER_SUCCESS ? waitTune : sadTune), TRUE); } emberEventControlSetDelayMS(buttonEventControl, REPAIR_DELAY_MS); } } } else if (halButtonState(BUTTON1) == BUTTON_PRESSED) { emberAfEzmodeClientCommission(emberAfPrimaryEndpoint(), EMBER_AF_EZMODE_COMMISSIONING_CLIENT_TO_SERVER, clusterIds, COUNTOF(clusterIds)); } }
EzspStatus serialSendCommand() { EzspStatus status; if (!checkConnection()) { ezspTraceEzspVerbose("serialSendCommand(): EZSP_NOT_CONNECTED"); return EZSP_NOT_CONNECTED; } ezspTraceEzspFrameId("send command", ezspFrameContents); status = usbSend(ezspFrameLength, ezspFrameContents); if (status != EZSP_SUCCESS) { ezspTraceEzspVerbose("serialSendCommand(): usbSend(): 0x%x", status); return status; } waitingForResponse = true; ezspTraceEzspVerbose("serialSendCommand(): ID=0x%x Seq=0x%x", ezspFrameContents[EZSP_FRAME_ID_INDEX], ezspFrameContents[EZSP_SEQUENCE_INDEX]); waitStartTime = halCommonGetInt16uMillisecondTick(); return status; }
EzspStatus serialResponseReceived(void) { EzspStatus status; EzspBuffer *buffer; EzspBuffer *dropBuffer = NULL; if (!checkConnection()) { ezspTraceEzspVerbose("serialResponseReceived(): EZSP_NOT_CONNECTED"); return EZSP_NOT_CONNECTED; } // ashSendExec(); // status = ashReceiveExec(); status = usbReceive(); if (status != EZSP_SUCCESS && status != EZSP_ASH_IN_PROGRESS && status != EZSP_NO_RX_DATA) { ezspTraceEzspVerbose("serialResponseReceived(): 0x%x", status); return status; } if (waitingForResponse && elapsedTimeInt16u(waitStartTime, halCommonGetInt16uMillisecondTick()) > WAIT_FOR_RESPONSE_TIMEOUT) { waitingForResponse = false; ezspTraceEzspFrameId("no response", ezspFrameContents); ezspTraceEzspVerbose("serialResponseReceived(): EZSP_ERROR_NO_RESPONSE"); return EZSP_ERROR_NO_RESPONSE; } status = EZSP_NO_RX_DATA; buffer = ezspQueuePrecedingEntry(&rxQueue, NULL); while (buffer != NULL) { // While we are waiting for a response to a command, we use the asynch // callback flag to ignore asynchronous callbacks. This allows our caller // to assume that no callbacks will appear between sending a command and // receiving its response. if (waitingForResponse && (buffer->data[EZSP_FRAME_CONTROL_INDEX] & EZSP_FRAME_CONTROL_ASYNCH_CB) ) { if (ezspFreeListLength(&rxFree) == 0) { dropBuffer = buffer; } buffer = ezspQueuePrecedingEntry(&rxQueue, buffer); } else { ezspTraceEzspVerbose("serialResponseReceived(): ID=0x%x Seq=0x%x Buffer=%u", buffer->data[EZSP_FRAME_ID_INDEX], buffer->data[EZSP_SEQUENCE_INDEX], buffer); ezspRemoveQueueEntry(&rxQueue, buffer); memcpy(ezspFrameContents, buffer->data, buffer->len); ezspTraceEzspFrameId("got response", buffer->data); ezspFrameLength = buffer->len; ezspFreeBuffer(&rxFree, buffer); ezspTraceEzspVerbose("serialResponseReceived(): ezspFreeBuffer(): %u", buffer); buffer = NULL; status = EZSP_SUCCESS; waitingForResponse = false; } } if (dropBuffer != NULL) { ezspRemoveQueueEntry(&rxQueue, dropBuffer); ezspFreeBuffer(&rxFree, dropBuffer); ezspTraceEzspFrameId("dropping", dropBuffer->data); ezspTraceEzspVerbose("serialResponseReceived(): ezspFreeBuffer(): drop %u", dropBuffer); ezspTraceEzspVerbose("serialResponseReceived(): ezspErrorHandler(): EZSP_ERROR_QUEUE_FULL"); ezspErrorHandler(EZSP_ERROR_QUEUE_FULL); } return status; }