#include #include static uint32_t dmx_base_channel; enum dmx_rx_state_enum { DMX_RX_WAIT_FOR_BREAK = 0, DMX_RX_DATA, }; static volatile bool break_received; /** * @brief DMX data received. Contains the whole DMX universe including the first 0 byte. * The controller does check the first byte to be zero. */ static volatile uint8_t dmx_channel_data[DMX_UNIVERSE_SIZE + 1]; void dmx_init(uint32_t base_channel) { int i; volatile uint8_t *ptr; for (i = 0, ptr = dmx_channel_data; i < DMX_USED_CHANNEL_COUNT; i++, ptr++) { *ptr = 0u; } dmx_base_channel = base_channel; break_received = false; /* Enable GPIOA and USART1 clock */ RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_DMAEN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN; /* Switch RXTX pin low, activating permanent READ mode */ GPIOA->MODER |= (0x1<<(2*5)); GPIOA->BRR |= (1<<5); /* Switch PA10 to RX alternate function of USART1 (AF1) */ GPIOA->MODER |= (0x2<<(2*10)); GPIOA->AFR[1] |=(0x1<<(4*2)); /* Set baudrate: 48MHz / 250k = 129 */ USART1->BRR = 192u; USART1->CR3 = USART_CR3_EIE; USART1->CR2 = USART_CR2_STOP_1; USART1->CR1 = USART_CR1_RXNEIE | USART_CR1_RE | USART_CR1_UE; /* Map USART1 RX to DMA Channel 3 */ SYSCFG->CFGR1 &= ~SYSCFG_CFGR1_USART1RX_DMA_RMP; DMA1_Channel3->CCR = DMA_CCR_PL_1 | DMA_CCR_MINC | DMA_CCR_TCIE; NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); NVIC_EnableIRQ(USART1_IRQn); } const uint8_t *dmx_get_data() { return (const uint8_t *)dmx_channel_data; } void USART1_IRQHandler(void) { uint32_t isr; isr = USART1->ISR; USART1->ICR = USART_ICR_ORECF | USART_ICR_NCF | USART_ICR_FECF; if (isr & USART_ISR_FE) { /* Frame error received. Start of DMX frame */ /* Flush RX data */ USART1->RQR = USART_RQR_RXFRQ; USART1->CR3 |= USART_CR3_DMAR; DMA1_Channel3->CCR &= ~DMA_CCR_EN; DMA1_Channel3->CMAR = (uint32_t)dmx_channel_data; DMA1_Channel3->CPAR = (uint32_t)&USART1->RDR; DMA1_Channel3->CNDTR = DMX_UNIVERSE_SIZE + 1; DMA1_Channel3->CCR |= DMA_CCR_EN; USART1->CR3 |= USART_CR3_DMAR; break_received = true; } else if (isr & USART_ISR_RXNE) { } __DSB(); } void DMA_CH2_3_DMA2_CH1_2_IRQHandler(void) { uint32_t isr; isr = DMA1->ISR; /* Only clear the interupts of channel 2 (bits 11:9) */ DMA1->IFCR = isr & 0xF00; if (isr & DMA_ISR_TCIF3) { DMA1->ISR; } __DSB(); } bool dmx_poll_break_received(void) { bool ret; /* Atomically reset the flag */ __disable_irq(); ret = break_received; break_received = false; __enable_irq(); return ret; } bool dmx_enough_data_received() { uint32_t received_count = (DMX_UNIVERSE_SIZE + 1) - DMA1_Channel3->CNDTR; if (received_count > (dmx_base_channel + DMX_USED_CHANNEL_COUNT)) { return true; } return false; }