Beispiel #1
0
void APP_Initialize(void) {
#ifdef PRE_APP_INIT_HOOK
  PRE_APP_INIT_HOOK();
#endif

  // We can do this after USB_DEVICE_Initialize() has been called since it's
  // not used until we reach the tasks function.
  UIDStore_AsUnicodeString(USBDescriptor_UnicodeUID());

  CoarseTimer_Settings timer_settings = {
    .timer_id = AS_TIMER_ID(COARSE_TIMER_ID),
    .interrupt_source = AS_TIMER_INTERRUPT_SOURCE(COARSE_TIMER_ID)
  };
  SYS_INT_VectorPrioritySet(AS_TIMER_INTERRUPT_VECTOR(COARSE_TIMER_ID),
                            INT_PRIORITY_LEVEL6);
  CoarseTimer_Initialize(&timer_settings);

  // Initialize the Logging system, bottom up
  USBTransport_Initialize(NULL);
  USBConsole_Initialize();
  SysLog_Initialize(NULL);

  // Initialize the DMX / RDM Transceiver
  TransceiverHardwareSettings transceiver_settings = {
    .usart = AS_USART_ID(TRANSCEIVER_UART),
    .usart_vector = AS_USART_INTERRUPT_VECTOR(TRANSCEIVER_UART),
    .usart_tx_source = AS_USART_INTERRUPT_TX_SOURCE(TRANSCEIVER_UART),
    .usart_rx_source = AS_USART_INTERRUPT_RX_SOURCE(TRANSCEIVER_UART),
    .usart_error_source = AS_USART_INTERRUPT_ERROR_SOURCE(TRANSCEIVER_UART),
    .port = TRANSCEIVER_PORT,
    .break_bit = TRANSCEIVER_PORT_BIT,
    .tx_enable_bit = TRANSCEIVER_TX_ENABLE_PORT_BIT,
    .rx_enable_bit = TRANSCEIVER_RX_ENABLE_PORT_BIT,
    .input_capture_module = AS_IC_ID(TRANSCEIVER_IC),
    .input_capture_vector = AS_IC_INTERRUPT_VECTOR(TRANSCEIVER_IC),
    .input_capture_source = AS_IC_INTERRUPT_SOURCE(TRANSCEIVER_IC),
    .timer_module_id = AS_TIMER_ID(TRANSCEIVER_TIMER),
    .timer_vector = AS_TIMER_INTERRUPT_VECTOR(TRANSCEIVER_TIMER),
    .timer_source = AS_TIMER_INTERRUPT_SOURCE(TRANSCEIVER_TIMER),
    .input_capture_timer = AS_IC_TMR_ID(TRANSCEIVER_TIMER),
  };
  Transceiver_Initialize(&transceiver_settings, NULL, NULL);

  // Base RDM Responder
  RDMResponderSettings responder_settings = {
    .identify_port = RDM_RESPONDER_IDENTIFY_PORT,
    .identify_bit = RDM_RESPONDER_IDENTIFY_PORT_BIT,
    .mute_port = RDM_RESPONDER_MUTE_PORT,
    .mute_bit = RDM_RESPONDER_MUTE_PORT_BIT,
  };
  memcpy(responder_settings.uid, UIDStore_GetUID(), UID_LENGTH);
  RDMResponder_Initialize(&responder_settings);
  ReceiverCounters_ResetCounters();

  // RDM Handler
  RDMHandlerSettings rdm_handler_settings = {
    .default_model = LED_MODEL_ID,
    .send_callback = NULL
  };
  RDMHandler_Initialize(&rdm_handler_settings);

  // Initialize RDM Models, keep these in Model ID order.
  LEDModel_Initialize();
  RDMHandler_AddModel(&LED_MODEL_ENTRY);

  ProxyModel_Initialize();
  RDMHandler_AddModel(&PROXY_MODEL_ENTRY);

  MovingLightModel_Initialize();
  RDMHandler_AddModel(&MOVING_LIGHT_MODEL_ENTRY);

  SensorModel_Initialize();
  RDMHandler_AddModel(&SENSOR_MODEL_ENTRY);

  NetworkModel_Initialize();
  RDMHandler_AddModel(&NETWORK_MODEL_ENTRY);

  DimmerModel_Initialize();
  RDMHandler_AddModel(&DIMMER_MODEL_ENTRY);

  // Initialize the Host message layers.
  MessageHandler_Initialize(NULL);
  StreamDecoder_Initialize(NULL);

  Flags_Initialize();

  // SPI DMX Output
  SPIRGBConfiguration spi_config;
  spi_config.module_id = SPI_MODULE_ID;
  spi_config.baud_rate = SPI_BAUD_RATE;
  spi_config.use_enhanced_buffering = SPI_USE_ENHANCED_BUFFERING;
  SPIRGB_Init(&spi_config);

  // Send a frame with all pixels set to 0.
  SPIRGB_BeginUpdate();
  SPIRGB_CompleteUpdate();
}
Beispiel #2
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;
        }
    }
}