diff --git a/dmx.c b/dmx.c index 7bfcce4..cb1b372 100644 --- a/dmx.c +++ b/dmx.c @@ -51,6 +51,7 @@ void dmx_init(uint8_t *data, uint32_t universe_length, GPIO_TypeDef *tx_port, ui dmx_tx_pin = tx_pin; dmx_tx_port = tx_port; dmx_data_ptr = data; + dmx_universe_length = universe_length; dmx_tx_break_len = dmx_break_len; dmx_tx_break_pause = break_pause; @@ -67,8 +68,9 @@ void dmx_init(uint8_t *data, uint32_t universe_length, GPIO_TypeDef *tx_port, ui /* Two stop bits */ USART1->CR2 = USART_CR2_STOP_1; - /* Transmitter enable, USART enable */ - USART1->CR1 = USART_CR1_TE | USART_CR1_UE; + /* Transmitter enable, USART enable, trawsnmission complete interrupt */ + USART1->CR1 = USART_CR1_TE | USART_CR1_UE | USART_CR1_TCIE; + /* Configure TIM14 to count in 10 us steps */ TIM14->PSC = 480u; @@ -82,6 +84,10 @@ void dmx_init(uint8_t *data, uint32_t universe_length, GPIO_TypeDef *tx_port, ui TIM14->DIER = TIM_DIER_UIE | TIM_DIER_CC1IE; NVIC_EnableIRQ(TIM14_IRQn); + /* Enable Interrupts for USART and DMA */ + NVIC_EnableIRQ(USART1_IRQn); + NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); + } @@ -103,12 +109,18 @@ void dmx_stream_stop(void) void TIM14_IRQHandler(void) { + uint32_t sr; + + sr = TIM14->SR; + /* Clear interrupt sources */ TIM14->SR = 0; /* Start the break sequence if idle */ switch (tx_state) { case DMX_TX_IDLE: + if (!(sr & TIM_SR_UIF)) + break; tx_state = DMX_TX_BREAK; /* Disable the DMA transfer */ USART1->CR3 = 0ul; @@ -126,9 +138,49 @@ void TIM14_IRQHandler(void) tx_state = DMX_TX_BREAK_PAUSE; break; case DMX_TX_BREAK_PAUSE: - tx_state = DMX_TX_IDLE; + /* Send null byte */ + tx_state = DMX_TX_NULLBYTE; + USART1->TDR = 0x00; break; default: break; } +} + +void USART1_IRQHandler(void) +{ + uint32_t isr; + + isr = USART1->ISR; + + /* Clear interrupt flag */ + USART1->ICR = USART_ICR_TCCF; + + if (isr & USART_ISR_TC) { + if (tx_state == DMX_TX_NULLBYTE) { + /* Null byte transferred. Go to data state and setup DMA */ + tx_state = DMX_TX_DATA; + USART1->CR3 |= USART_CR3_DMAT; + + DMA1_Channel2->CPAR = (uint32_t)&USART1->TDR; + DMA1_Channel2->CMAR = (uint32_t)dmx_data_ptr; + DMA1_Channel2->CNDTR = dmx_universe_length & 0xFFFF; + DMA1_Channel2->CCR = DMA_CCR_PL_1 | DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE | DMA_CCR_EN; + } + } +} + +void DMA_CH2_3_DMA2_CH1_2_IRQHandler(void) +{ + uint32_t isr; + + isr = DMA1->ISR; + DMA1->IFCR = isr; + + if (isr & DMA_ISR_TCIF2) { + /* Channnel 2 trasnfer complete. Universe trasnferred */ + tx_state = DMX_TX_IDLE; + DMA1_Channel2->CCR = 0u; + USART1->CR3 &= ~USART_CR3_DMAT; + } } \ No newline at end of file diff --git a/main.c b/main.c index 3eb0b90..3ec2bea 100644 --- a/main.c +++ b/main.c @@ -58,6 +58,15 @@ static void setup_pins(void) GPIOB->PUPDR = PULLUP(1); } +static void zero_dmx_universe(void) +{ + int i; + + for (i = 0; i < sizeof(dmx_universe); i++) { + dmx_universe[i] = 0; + } +} + int main(void) { uint8_t i2c_command[2]; @@ -84,6 +93,9 @@ int main(void) dmx_stream_start(); + dmx_universe[0] = 0x55; + dmx_universe[1] = 0x50; + /* Blink the LEDs */ while (1) { systick_wait_ms(3); @@ -93,13 +105,22 @@ int main(void) odr = GPIOA->ODR; odr &= ~((1<<5) | (1<<6) | (1<<7)); if (port & (1<<0)) { - odr |= (1<<5); + zero_dmx_universe(); + for (int i = 0; i < 32; i++) { + dmx_universe[i*4] = 0xFF; + } } if (port & (1<<1)) { - odr |= (1<<6); + zero_dmx_universe(); + for (int i = 0; i < 32; i++) { + dmx_universe[i*4+1] = 0xFF; + } } if (port & (1<<2)) { - odr |= (1<<7); + zero_dmx_universe(); + for (int i = 0; i < 32; i++) { + dmx_universe[i*4+2] = 0xFF; + } } GPIOA->ODR = odr;