Implement DMX reciever and add more advanced failure mode #1
@@ -1 +1,65 @@
 | 
				
			|||||||
#include <ring-light/dmx.h>
 | 
					#include <ring-light/dmx.h>
 | 
				
			||||||
 | 
					#include <stm32f0xx.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static volatile bool dmx_new_data_avail = false;
 | 
				
			||||||
 | 
					static uint32_t dmx_base_channel;
 | 
				
			||||||
 | 
					static uint8_t dmx_channel_data[DMX_USED_CHANNEL_COUNT];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void dmx_init(uint32_t base_channel)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						uint8_t *ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dmx_new_data_avail = false;
 | 
				
			||||||
 | 
						for (i = 0, ptr = dmx_channel_data; i < DMX_USED_CHANNEL_COUNT; i++, ptr++) {
 | 
				
			||||||
 | 
							*ptr = 0u;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dmx_base_channel = base_channel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Enable GPIOA and USART1 clock */
 | 
				
			||||||
 | 
						RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NVIC_EnableIRQ(USART1_IRQn);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool dmx_new_data_available()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return dmx_new_data_avail;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const uint8_t *dmx_get_data()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return dmx_channel_data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void USART1_IRQHandler(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t isr;
 | 
				
			||||||
 | 
						volatile uint8_t dreg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						isr = USART1->ISR;
 | 
				
			||||||
 | 
						USART1->ICR = USART_ICR_ORECF | USART_ICR_NCF | USART_ICR_FECF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (isr & USART_ISR_RXNE) {
 | 
				
			||||||
 | 
							dreg = (uint8_t)USART1->RDR;
 | 
				
			||||||
 | 
							dmx_channel_data[0] = dreg;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__DSB();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,43 @@
 | 
				
			|||||||
#ifndef _DMX_H_
 | 
					#ifndef _DMX_H_
 | 
				
			||||||
#define _DMX_H_
 | 
					#define _DMX_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DMX_UNIVERSE_SIZE (255u)
 | 
				
			||||||
 | 
					#define DMX_USED_CHANNEL_COUNT (129u)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Init DMX reception
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * DMX data is received from the base channel onwards:
 | 
				
			||||||
 | 
					 * - R LED1
 | 
				
			||||||
 | 
					 * - G LED1
 | 
				
			||||||
 | 
					 * - B LED1
 | 
				
			||||||
 | 
					 * - W LED1
 | 
				
			||||||
 | 
					 * - R LED2
 | 
				
			||||||
 | 
					 * ...
 | 
				
			||||||
 | 
					 * - W LED32
 | 
				
			||||||
 | 
					 * - W DISCRETE
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * In Sum: 129 8 bit channels
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base_channel Base channel the ring light will listen on
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void dmx_init(uint32_t base_channel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Has new DMX data been received?
 | 
				
			||||||
 | 
					 * @return true if new data is available
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool dmx_new_data_available(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Returns the array of the 129 DMX channels
 | 
				
			||||||
 | 
					 * @return
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const uint8_t *dmx_get_data(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _DMX_H_ */
 | 
					#endif /* _DMX_H_ */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
#include <cmsis/core_cm0.h>
 | 
					#include <cmsis/core_cm0.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <ring-light/temp-adc.h>
 | 
					#include <ring-light/temp-adc.h>
 | 
				
			||||||
 | 
					#include <ring-light/dmx.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define RING_MAX_LED	32u
 | 
					#define RING_MAX_LED	32u
 | 
				
			||||||
#define MAX_TEMP_CELSIUS 70
 | 
					#define MAX_TEMP_CELSIUS 70
 | 
				
			||||||
@@ -37,7 +38,7 @@ int main(void)
 | 
				
			|||||||
	uint8_t led_pwm_val = 0u;
 | 
						uint8_t led_pwm_val = 0u;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool button_pressed = false;
 | 
						bool button_pressed = false;
 | 
				
			||||||
	enum ring_modes mode = RING_MODE_ALL;
 | 
						enum ring_modes mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN;
 | 
						RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN;
 | 
				
			||||||
	RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN;
 | 
						RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN;
 | 
				
			||||||
@@ -83,6 +84,7 @@ int main(void)
 | 
				
			|||||||
	mode    = RING_MODE_WHITE_DISCRETE;
 | 
						mode    = RING_MODE_WHITE_DISCRETE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	temperature_adc_init();
 | 
						temperature_adc_init();
 | 
				
			||||||
 | 
						dmx_init(0u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SysTick_Config(800000);
 | 
						SysTick_Config(800000);
 | 
				
			||||||
	while(1) {
 | 
						while(1) {
 | 
				
			||||||
@@ -171,11 +173,16 @@ int main(void)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		TIM14->CCR1 = led_pwm_val;
 | 
							TIM14->CCR1 = led_pwm_val;
 | 
				
			||||||
		__disable_irq();
 | 
					
 | 
				
			||||||
		for(int i = 0; i < RING_MAX_LED; i ++) {
 | 
							for(int i = 0; i < RING_MAX_LED; i ++) {
 | 
				
			||||||
 | 
								/* Allow interrupts in between LEDs.
 | 
				
			||||||
 | 
								 * They must not exceed the reset length of 80us of SK6812.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								__disable_irq();
 | 
				
			||||||
			sk6812_send_led(led_calc_val[i]);
 | 
								sk6812_send_led(led_calc_val[i]);
 | 
				
			||||||
 | 
								__enable_irq();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		__enable_irq();
 | 
					
 | 
				
			||||||
		wait_for_ticks(5);
 | 
							wait_for_ticks(5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if((int16_t)TIM3->CNT > (int16_t)led_val) {
 | 
							if((int16_t)TIM3->CNT > (int16_t)led_val) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user