LED iffy (unstable timer?)

This commit is contained in:
Ben V. Brown
2021-05-02 21:39:47 +10:00
parent e4f7946dcb
commit 5128602335
4 changed files with 470 additions and 493 deletions

View File

@@ -77,8 +77,7 @@ void SystemClock_Config(void) {
/**Initializes the CPU, AHB and APB busses clocks /**Initializes the CPU, AHB and APB busses clocks
*/ */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSI;
| RCC_OSCILLATORTYPE_LSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.LSIState = RCC_LSI_ON; RCC_OscInitStruct.LSIState = RCC_LSI_ON;
@@ -89,8 +88,7 @@ void SystemClock_Config(void) {
/**Initializes the CPU, AHB and APB busses clocks /**Initializes the CPU, AHB and APB busses clocks
*/ */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV16; // TIM RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV16; // TIM
@@ -231,10 +229,10 @@ void MX_TIM1_Init(void) {
/* USER CODE END TIM1_Init 0 */ /* USER CODE END TIM1_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = { 0 }; TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = { 0 }; TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = { 0 }; TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = { 0 }; TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN TIM1_Init 1 */ /* USER CODE BEGIN TIM1_Init 1 */
@@ -242,7 +240,7 @@ void MX_TIM1_Init(void) {
htim1.Instance = TIM1; htim1.Instance = TIM1;
htim1.Init.Prescaler = 0; htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 40; htim1.Init.Period = 42;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0; htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
@@ -418,15 +416,11 @@ static void MX_GPIO_Init(void) {
/* /*
* Configure All pins as analog by default * Configure All pins as analog by default
*/ */
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_10 | GPIO_PIN_15;
| GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8
| GPIO_PIN_10 | GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12
| GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
| GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13
| GPIO_PIN_14 | GPIO_PIN_15;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : KEY_B_Pin KEY_A_Pin */ /*Configure GPIO pins : KEY_B_Pin KEY_A_Pin */
@@ -450,7 +444,6 @@ static void MX_GPIO_Init(void) {
HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_RESET);
HAL_Delay(30); HAL_Delay(30);
HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET);
} }
#ifdef USE_FULL_ASSERT #ifdef USE_FULL_ASSERT

View File

@@ -14,11 +14,11 @@
// Initialisation to be performed with scheduler active // Initialisation to be performed with scheduler active
void postRToSInit() { void postRToSInit() {
WS2812::init(); WS2812::init();
WS2812::led_set_color(0, 0xAA, 0x55, 0x00); WS2812::led_set_color(0, 0xAA, 0x00, 0x00);
while (true) { while (true) {
// osDelay(1); // osDelay(1);
// WS2812::led_set_color(0, 0xFF, 0xFF, 0xFF); // WS2812::led_set_color(0, 0xFF, 0xFF, 0xFF);
// WS2812::led_update(1); // WS2812::led_update(1);
osDelay(10); osDelay(10);
WS2812::led_update(1); WS2812::led_update(1);
} }

View File

@@ -52,35 +52,28 @@ void WS2812::led_set_color_all(uint8_t r, uint8_t g, uint8_t b) {
} }
} }
uint8_t WS2812::led_is_update_finished(void) { uint8_t WS2812::led_is_update_finished(void) { return !is_updating; }
return !is_updating;
}
void WS2812::led_start_reset_pulse(uint8_t num) { void WS2812::led_start_reset_pulse(uint8_t num) {
is_reset_pulse = num; /* Set reset pulse flag */ is_reset_pulse = num; /* Set reset pulse flag */
memset((void*)tmp_led_data, 0, sizeof(tmp_led_data)); /* Set all bytes to 0 to achieve 50us pulse */ memset((void *)tmp_led_data, 0, sizeof(tmp_led_data)); /* Set all bytes to 0 to achieve 50us pulse */
if (num == 1) { if (num == 1) {
tmp_led_data[0] = htim1.Instance->ARR / 2; // start with half width pulse tmp_led_data[0] = (htim1.Instance->ARR * 2) / 3; // start with half width pulse
} }
/* Set DMA to normal mode, set memory to beginning of data and length to 40 elements */ /* Set DMA to normal mode, set memory to beginning of data and length to 40 elements */
/* 800kHz PWM x 40 samples = ~50us pulse low */ /* 800kHz PWM x 40 samples = ~50us pulse low */
hdma_tim1_ch1.Instance->CCR &= (~DMA_CCR_CIRC); // clear circular flag -> normal mode hdma_tim1_ch1.Instance->CCR &= (~DMA_CCR_CIRC); // clear circular flag -> normal mode
hdma_tim1_ch1.State = HAL_DMA_STATE_READY; hdma_tim1_ch1.State = HAL_DMA_STATE_READY;
HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t) tmp_led_data, HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t)tmp_led_data, (uint32_t)&htim1.Instance->CCR1, 2 * WS2812_RAW_BYTES_PER_LED);
(uint32_t) &htim1.Instance->CCR1, 40);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
} }
void WS2812::DMAHalfComplete(DMA_HandleTypeDef *hdma) { void WS2812::DMAHalfComplete(DMA_HandleTypeDef *hdma) { led_update_sequence(0); }
led_update_sequence(0);
}
void WS2812::DMAComplete(DMA_HandleTypeDef *hdma) { void WS2812::DMAComplete(DMA_HandleTypeDef *hdma) { led_update_sequence(1); }
led_update_sequence(1);
}
void WS2812::led_update_sequence(uint8_t tc) { void WS2812::led_update_sequence(uint8_t tc) {
tc = !!tc; /* Convert to 1 or 0 value only */ tc = !!tc; /* Convert to 1 or 0 value only */
@@ -134,8 +127,7 @@ void WS2812::led_update_sequence(uint8_t tc) {
if (current_led == 0 || !tc) { if (current_led == 0 || !tc) {
led_fill_led_pwm_data(current_led, &tmp_led_data[0]); led_fill_led_pwm_data(current_led, &tmp_led_data[0]);
} else { } else {
led_fill_led_pwm_data(current_led, led_fill_led_pwm_data(current_led, &tmp_led_data[WS2812_RAW_BYTES_PER_LED]);
&tmp_led_data[WS2812_RAW_BYTES_PER_LED]);
} }
/* /*
@@ -148,13 +140,10 @@ void WS2812::led_update_sequence(uint8_t tc) {
if (current_led == 0) { if (current_led == 0) {
current_led++; /* Go to next LED */ current_led++; /* Go to next LED */
led_fill_led_pwm_data(current_led, led_fill_led_pwm_data(current_led, &tmp_led_data[WS2812_RAW_BYTES_PER_LED]); /* Prepare second LED too */
&tmp_led_data[WS2812_RAW_BYTES_PER_LED]); /* Prepare second LED too */
hdma_tim1_ch1.Instance->CCR |= (DMA_CCR_CIRC); // set circular flag for circular mode hdma_tim1_ch1.Instance->CCR |= (DMA_CCR_CIRC); // set circular flag for circular mode
hdma_tim1_ch1.State = HAL_DMA_STATE_READY; hdma_tim1_ch1.State = HAL_DMA_STATE_READY;
HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t) tmp_led_data, HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t)tmp_led_data, (uint32_t)&htim1.Instance->CCR1, 2 * WS2812_RAW_BYTES_PER_LED);
(uint32_t) &htim1.Instance->CCR1,
2 * WS2812_RAW_BYTES_PER_LED);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
} }
@@ -164,8 +153,7 @@ void WS2812::led_update_sequence(uint8_t tc) {
* - If TC event is enabled and we have EVEN number of LEDS (2, 4, 6, ...) * - If TC event is enabled and we have EVEN number of LEDS (2, 4, 6, ...)
* - If HT event is enabled and we have ODD number of LEDS (1, 3, 5, ...) * - If HT event is enabled and we have ODD number of LEDS (1, 3, 5, ...)
*/ */
} else if ((!tc && (WS2812_LED_COUNT & 0x01)) } else if ((!tc && (WS2812_LED_COUNT & 0x01)) || (tc && !(WS2812_LED_COUNT & 0x01))) {
|| (tc && !(WS2812_LED_COUNT & 0x01))) {
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
HAL_DMA_Abort(&hdma_tim1_ch1); HAL_DMA_Abort(&hdma_tim1_ch1);
@@ -176,23 +164,19 @@ void WS2812::led_update_sequence(uint8_t tc) {
void WS2812::led_fill_led_pwm_data(size_t ledx, volatile uint16_t *ptr) { void WS2812::led_fill_led_pwm_data(size_t ledx, volatile uint16_t *ptr) {
size_t i; size_t i;
uint16_t OnOffValues[] = { 2* htim1.Instance->ARR / 3, uint16_t OnOffValues[] = {2 * htim1.Instance->ARR / 3, (4 * htim1.Instance->ARR) / 3};
(4 * htim1.Instance->ARR) / 3 };
if (ledx < WS2812_LED_COUNT) { if (ledx < WS2812_LED_COUNT) {
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
//Also unmux RGB -> GRB in the index order here // Also unmux RGB -> GRB in the index order here
ptr[i] = ptr[i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 1] & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0];
(leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 1] ptr[8 + i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 0] & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0];
& (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0]; ptr[16 + i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 2] & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0];
ptr[8 + i] = #if WS2812_LED_CHANNEL_COUNT == 4
(leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 0] ptr[24 + i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 3] & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0];
& (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0]; #endif
ptr[16 + i] =
(leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 2]
& (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0];
} }
} else { } else {
//Fill with zero? // Fill with zero?
} }
} }

View File

@@ -11,7 +11,7 @@
#ifndef CORE_DRIVERS_WS2812_H_ #ifndef CORE_DRIVERS_WS2812_H_
#define CORE_DRIVERS_WS2812_H_ #define CORE_DRIVERS_WS2812_H_
#ifndef WS2812_LED_COUNT #ifndef WS2812_LED_COUNT
#define WS2812_LED_COUNT 4 #define WS2812_LED_COUNT 3
#endif #endif
#ifndef WS2812_LED_CHANNEL_COUNT #ifndef WS2812_LED_CHANNEL_COUNT
#define WS2812_LED_CHANNEL_COUNT 3 #define WS2812_LED_CHANNEL_COUNT 3