/* * @brief Increment the bad-checksum counter if the frame was for us. */ static inline void PossiblyIncrementChecksumCounter(const uint8_t *frame) { uint8_t uid[UID_LENGTH]; RDMHandler_GetUID(uid); RDMHeader *header = (RDMHeader*) frame; if (RDMUtil_RequiresAction(uid, header->dest_uid)) { SysLog_Message(SYSLOG_ERROR, "Checksum mismatch"); g_responder_counters.rdm_checksum_invalid++; } }
void APP_Reset() { Transceiver_Reset(); SysLog_Message(SYSLOG_INFO, "Reset Device"); USBTransport_SoftReset(); }
void Responder_Receive(const TransceiverEvent *event) { // While this function is running, UART interrupts are disabled. // Try to keep things short. if (event->op != T_OP_RX) { return; } if (event->result == T_RESULT_RX_START_FRAME) { // Right now we can only tell a DMX frame ended when the next one starts. // TODO(simon): get some clarity on this. It needs to be discussed and // explained in E1.37-5. if (g_state == STATE_DMX_DATA && (g_responder_counters.dmx_min_slot_count == UNINITIALIZED_COUNTER || g_responder_counters.dmx_last_slot_count < g_responder_counters.dmx_min_slot_count)) { g_responder_counters.dmx_min_slot_count = g_responder_counters.dmx_last_slot_count; } if (g_state == STATE_RDM_SUB_START_CODE || g_state == STATE_RDM_MESSAGE_LENGTH || (g_state == STATE_RDM_BODY && g_offset < 9)) { // COMMS_STATUS, short frame g_responder_counters.rdm_short_frame++; } g_offset = 0u; g_state = STATE_START_CODE; if (event->timing) { g_timing = *event->timing; } } if (event->result == T_RESULT_RX_FRAME_TIMEOUT) { SPIRGB_CompleteUpdate(); return; } for (; g_offset < event->length; g_offset++) { uint8_t b = event->data[g_offset]; switch (g_state) { case STATE_START_CODE: if (b == NULL_START_CODE) { g_responder_counters.dmx_last_checksum = 0u; g_responder_counters.dmx_last_slot_count = 0u; SysLog_Message(SYSLOG_DEBUG, "DMX frame"); g_responder_counters.dmx_frames++; g_state = STATE_DMX_DATA; SPIRGB_BeginUpdate(); } else if (b == RDM_START_CODE) { g_responder_counters.rdm_frames++; g_state = STATE_RDM_SUB_START_CODE; } else { SysLog_Print(SYSLOG_DEBUG, "ASC frame: %d", (int) b); g_responder_counters.asc_frames++; g_state = STATE_DISCARD; } break; case STATE_RDM_SUB_START_CODE: if (b != RDM_SUB_START_CODE) { SysLog_Print(SYSLOG_ERROR, "RDM sub-start-code mismatch: %d", (int) b); g_responder_counters.rdm_sub_start_code_invalid++; g_state = STATE_DISCARD; } else { g_state = STATE_RDM_MESSAGE_LENGTH; } break; case STATE_RDM_MESSAGE_LENGTH: if (b < sizeof(RDMHeader)) { SysLog_Print(SYSLOG_INFO, "RDM msg len too short: %d", (int) b); g_responder_counters.rdm_msg_len_invalid++; g_state = STATE_DISCARD; } else { g_state = STATE_RDM_BODY; } break; // data[2] is at least 24 case STATE_RDM_BODY: if (g_offset == RDM_PARAM_DATA_LENGTH_OFFSET) { if (b != event->data[MESSAGE_LENGTH_OFFSET] - sizeof(RDMHeader)) { SysLog_Print(SYSLOG_INFO, "Invalid RDM PDL: %d, msg len: %d", (int) b, event->data[MESSAGE_LENGTH_OFFSET]); g_state = STATE_DISCARD; g_responder_counters.rdm_param_data_len_invalid++; continue; } } if (g_offset + 1u == event->data[MESSAGE_LENGTH_OFFSET]) { g_state = STATE_RDM_CHECKSUM_LO; } break; case STATE_RDM_CHECKSUM_LO: g_state = STATE_RDM_CHECKSUM_HI; break; case STATE_RDM_CHECKSUM_HI: if (RDMUtil_VerifyChecksum(event->data, event->length)) { DispatchRDMRequest(event->data); } else { PossiblyIncrementChecksumCounter(event->data); } g_state = STATE_RDM_POST_CHECKSUM; break; case STATE_RDM_POST_CHECKSUM: PossiblyIncrementLengthMismatchCounter(event->data); g_state = STATE_DISCARD; break; case STATE_DMX_DATA: // TODO(simon): configure this with DMX_START_ADDRESS and footprints. if (g_offset - 1u < 6u) { SPIRGB_SetPixel((g_offset - 1u) / 3u, (g_offset - 1u) % 3u, b); } else if (g_offset - 1u == 6u) { SPIRGB_CompleteUpdate(); } g_responder_counters.dmx_last_checksum += b; g_responder_counters.dmx_last_slot_count++; if (g_responder_counters.dmx_max_slot_count == UNINITIALIZED_COUNTER || g_responder_counters.dmx_last_slot_count > g_responder_counters.dmx_max_slot_count) { g_responder_counters.dmx_max_slot_count = g_responder_counters.dmx_last_slot_count; } break; case STATE_DISCARD: break; } } }