Example #1
0
/*
 * @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++;
    }
}
Example #2
0
void APP_Reset() {
  Transceiver_Reset();
  SysLog_Message(SYSLOG_INFO, "Reset Device");
  USBTransport_SoftReset();
}
Example #3
0
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;
        }
    }
}