From 5128602335db12b38ed1c2451b84fd97f1e0f029 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 2 May 2021 21:39:47 +1000 Subject: [PATCH] LED iffy (unstable timer?) --- source/Core/BSP/MHP30/Setup.c | 633 ++++++++++++++--------------- source/Core/BSP/MHP30/postRTOS.cpp | 18 +- source/Core/Drivers/WS2812.cpp | 280 ++++++------- source/Core/Drivers/WS2812.h | 32 +- 4 files changed, 470 insertions(+), 493 deletions(-) diff --git a/source/Core/BSP/MHP30/Setup.c b/source/Core/BSP/MHP30/Setup.c index 28817182..e0851ded 100644 --- a/source/Core/BSP/MHP30/Setup.c +++ b/source/Core/BSP/MHP30/Setup.c @@ -16,10 +16,10 @@ DMA_HandleTypeDef hdma_i2c1_rx; DMA_HandleTypeDef hdma_i2c1_tx; IWDG_HandleTypeDef hiwdg; -TIM_HandleTypeDef htim1; -DMA_HandleTypeDef hdma_tim1_ch1; -TIM_HandleTypeDef htim2; -TIM_HandleTypeDef htim3; +TIM_HandleTypeDef htim1; +DMA_HandleTypeDef hdma_tim1_ch1; +TIM_HandleTypeDef htim2; +TIM_HandleTypeDef htim3; #define ADC_CHANNELS 4 #define ADC_SAMPLES 16 uint32_t ADCReadings[ADC_SAMPLES * ADC_CHANNELS]; // room for 32 lots of the pair of readings @@ -35,422 +35,415 @@ static void MX_TIM1_Init(void); static void MX_DMA_Init(void); static void MX_GPIO_Init(void); static void MX_ADC2_Init(void); -void Setup_HAL() { - SystemClock_Config(); +void Setup_HAL() { + SystemClock_Config(); - __HAL_AFIO_REMAP_SWJ_NOJTAG(); + __HAL_AFIO_REMAP_SWJ_NOJTAG(); - MX_GPIO_Init(); - MX_DMA_Init(); - MX_I2C1_Init(); - MX_ADC1_Init(); - MX_ADC2_Init(); - MX_TIM3_Init(); - MX_TIM2_Init(); - MX_TIM1_Init(); - MX_IWDG_Init(); - HAL_ADC_Start(&hadc2); - HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADCReadings, - (ADC_SAMPLES * ADC_CHANNELS)); // start DMA of normal readings - // HAL_ADCEx_InjectedStart(&hadc1); // enable injected readings - // HAL_ADCEx_InjectedStart(&hadc2); // enable injected readings + MX_GPIO_Init(); + MX_DMA_Init(); + MX_I2C1_Init(); + MX_ADC1_Init(); + MX_ADC2_Init(); + MX_TIM3_Init(); + MX_TIM2_Init(); + MX_TIM1_Init(); + MX_IWDG_Init(); + HAL_ADC_Start(&hadc2); + HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADCReadings, + (ADC_SAMPLES * ADC_CHANNELS)); // start DMA of normal readings + // HAL_ADCEx_InjectedStart(&hadc1); // enable injected readings + // HAL_ADCEx_InjectedStart(&hadc2); // enable injected readings } // channel 0 -> temperature sensor, 1-> VIN, 2-> tip uint16_t getADC(uint8_t channel) { - uint32_t sum = 0; - for (uint8_t i = 0; i < ADC_SAMPLES; i++) { - uint16_t adc1Sample = ADCReadings[channel + (i * ADC_CHANNELS)]; - uint16_t adc2Sample = ADCReadings[channel + (i * ADC_CHANNELS)] >> 16; + uint32_t sum = 0; + for (uint8_t i = 0; i < ADC_SAMPLES; i++) { + uint16_t adc1Sample = ADCReadings[channel + (i * ADC_CHANNELS)]; + uint16_t adc2Sample = ADCReadings[channel + (i * ADC_CHANNELS)] >> 16; - sum += (adc1Sample + adc2Sample); - } - return sum >> 2; + sum += (adc1Sample + adc2Sample); + } + return sum >> 2; } /** System Clock Configuration */ void SystemClock_Config(void) { - RCC_OscInitTypeDef RCC_OscInitStruct; - RCC_ClkInitTypeDef RCC_ClkInitStruct; - RCC_PeriphCLKInitTypeDef PeriphClkInit; + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInit; - /**Initializes the CPU, AHB and APB busses clocks - */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI - | RCC_OSCILLATORTYPE_LSI; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.LSIState = RCC_LSI_ON; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; - RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16; // 64MHz - HAL_RCC_OscConfig(&RCC_OscInitStruct); + /**Initializes the CPU, AHB and APB busses clocks + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.LSIState = RCC_LSI_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16; // 64MHz + HAL_RCC_OscConfig(&RCC_OscInitStruct); - /**Initializes the CPU, AHB and APB busses clocks - */ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK - | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV16; // TIM - // 2,3,4,5,6,7,12,13,14 - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 64 mhz to some peripherals and adc + /**Initializes the CPU, AHB and APB busses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV16; // TIM + // 2,3,4,5,6,7,12,13,14 + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 64 mhz to some peripherals and adc - HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2); + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2); - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; - PeriphClkInit.AdcClockSelection = RCC_CFGR_ADCPRE_DIV8; // 6 or 8 are the only non overclocked options - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; + PeriphClkInit.AdcClockSelection = RCC_CFGR_ADCPRE_DIV8; // 6 or 8 are the only non overclocked options + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); - /**Configure the Systick interrupt time - */ - HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); + /**Configure the Systick interrupt time + */ + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); - /**Configure the Systick - */ - HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); + /**Configure the Systick + */ + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); - /* SysTick_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0); + /* SysTick_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0); } /* ADC1 init function */ static void MX_ADC1_Init(void) { - ADC_MultiModeTypeDef multimode; + ADC_MultiModeTypeDef multimode; - ADC_ChannelConfTypeDef sConfig; - /**Common config - */ - hadc1.Instance = ADC1; - hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; - hadc1.Init.ContinuousConvMode = ENABLE; - hadc1.Init.DiscontinuousConvMode = DISABLE; - hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; - hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc1.Init.NbrOfConversion = ADC_CHANNELS; - HAL_ADC_Init(&hadc1); + ADC_ChannelConfTypeDef sConfig; + /**Common config + */ + hadc1.Instance = ADC1; + hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; + hadc1.Init.ContinuousConvMode = ENABLE; + hadc1.Init.DiscontinuousConvMode = DISABLE; + hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; + hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc1.Init.NbrOfConversion = ADC_CHANNELS; + HAL_ADC_Init(&hadc1); - /**Configure the ADC multi-mode - */ - multimode.Mode = ADC_DUALMODE_REGSIMULT_INJECSIMULT; - HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode); + /**Configure the ADC multi-mode + */ + multimode.Mode = ADC_DUALMODE_REGSIMULT_INJECSIMULT; + HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode); - /**Configure Regular Channel - */ - sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; + /**Configure Regular Channel + */ + sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; - sConfig.Channel = TMP36_ADC1_CHANNEL; - sConfig.Rank = ADC_REGULAR_RANK_1; - HAL_ADC_ConfigChannel(&hadc1, &sConfig); + sConfig.Channel = TMP36_ADC1_CHANNEL; + sConfig.Rank = ADC_REGULAR_RANK_1; + HAL_ADC_ConfigChannel(&hadc1, &sConfig); - /**Configure Regular Channel - */ - sConfig.Channel = VIN_ADC1_CHANNEL; - sConfig.Rank = ADC_REGULAR_RANK_2; - HAL_ADC_ConfigChannel(&hadc1, &sConfig); + /**Configure Regular Channel + */ + sConfig.Channel = VIN_ADC1_CHANNEL; + sConfig.Rank = ADC_REGULAR_RANK_2; + HAL_ADC_ConfigChannel(&hadc1, &sConfig); - sConfig.Channel = TIP_TEMP_ADC1_CHANNEL; - sConfig.Rank = ADC_REGULAR_RANK_3; - HAL_ADC_ConfigChannel(&hadc1, &sConfig); + sConfig.Channel = TIP_TEMP_ADC1_CHANNEL; + sConfig.Rank = ADC_REGULAR_RANK_3; + HAL_ADC_ConfigChannel(&hadc1, &sConfig); - sConfig.Channel = PLATE_SENSOR_ADC1_CHANNEL; - sConfig.Rank = ADC_REGULAR_RANK_4; - HAL_ADC_ConfigChannel(&hadc1, &sConfig); + sConfig.Channel = PLATE_SENSOR_ADC1_CHANNEL; + sConfig.Rank = ADC_REGULAR_RANK_4; + HAL_ADC_ConfigChannel(&hadc1, &sConfig); - SET_BIT(hadc1.Instance->CR1, (ADC_CR1_EOSIE)); // Enable end of Normal - // Run ADC internal calibration - while (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK) - ; + SET_BIT(hadc1.Instance->CR1, (ADC_CR1_EOSIE)); // Enable end of Normal + // Run ADC internal calibration + while (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK) + ; } /* ADC2 init function */ static void MX_ADC2_Init(void) { - ADC_ChannelConfTypeDef sConfig; + ADC_ChannelConfTypeDef sConfig; - /**Common config - */ - hadc2.Instance = ADC2; - hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE; - hadc2.Init.ContinuousConvMode = ENABLE; - hadc2.Init.DiscontinuousConvMode = DISABLE; - hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START; - hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc2.Init.NbrOfConversion = ADC_CHANNELS; - HAL_ADC_Init(&hadc2); - sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; + /**Common config + */ + hadc2.Instance = ADC2; + hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE; + hadc2.Init.ContinuousConvMode = ENABLE; + hadc2.Init.DiscontinuousConvMode = DISABLE; + hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START; + hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc2.Init.NbrOfConversion = ADC_CHANNELS; + HAL_ADC_Init(&hadc2); + sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; - /**Configure Regular Channel - */ - sConfig.Channel = TMP36_ADC2_CHANNEL; - sConfig.Rank = ADC_REGULAR_RANK_1; - HAL_ADC_ConfigChannel(&hadc2, &sConfig); + /**Configure Regular Channel + */ + sConfig.Channel = TMP36_ADC2_CHANNEL; + sConfig.Rank = ADC_REGULAR_RANK_1; + HAL_ADC_ConfigChannel(&hadc2, &sConfig); - sConfig.Channel = VIN_ADC2_CHANNEL; - sConfig.Rank = ADC_REGULAR_RANK_2; - HAL_ADC_ConfigChannel(&hadc2, &sConfig); - sConfig.Channel = TIP_TEMP_ADC1_CHANNEL; - sConfig.Rank = ADC_REGULAR_RANK_3; - HAL_ADC_ConfigChannel(&hadc2, &sConfig); - sConfig.Channel = PLATE_SENSOR_ADC2_CHANNEL; - sConfig.Rank = ADC_REGULAR_RANK_4; - HAL_ADC_ConfigChannel(&hadc2, &sConfig); + sConfig.Channel = VIN_ADC2_CHANNEL; + sConfig.Rank = ADC_REGULAR_RANK_2; + HAL_ADC_ConfigChannel(&hadc2, &sConfig); + sConfig.Channel = TIP_TEMP_ADC1_CHANNEL; + sConfig.Rank = ADC_REGULAR_RANK_3; + HAL_ADC_ConfigChannel(&hadc2, &sConfig); + sConfig.Channel = PLATE_SENSOR_ADC2_CHANNEL; + sConfig.Rank = ADC_REGULAR_RANK_4; + HAL_ADC_ConfigChannel(&hadc2, &sConfig); - // Run ADC internal calibration - while (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK) - ; + // Run ADC internal calibration + while (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK) + ; } /* I2C1 init function */ static void MX_I2C1_Init(void) { - hi2c1.Instance = I2C1; - hi2c1.Init.ClockSpeed = 300000; - hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; - hi2c1.Init.OwnAddress1 = 0; - hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; - hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; - hi2c1.Init.OwnAddress2 = 0; - hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; - hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; - HAL_I2C_Init(&hi2c1); + hi2c1.Instance = I2C1; + hi2c1.Init.ClockSpeed = 300000; + hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; + hi2c1.Init.OwnAddress1 = 0; + hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c1.Init.OwnAddress2 = 0; + hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + HAL_I2C_Init(&hi2c1); } /* IWDG init function */ static void MX_IWDG_Init(void) { - hiwdg.Instance = IWDG; - hiwdg.Init.Prescaler = IWDG_PRESCALER_256; - hiwdg.Init.Reload = 100; + hiwdg.Instance = IWDG; + hiwdg.Init.Prescaler = IWDG_PRESCALER_256; + hiwdg.Init.Reload = 100; #ifndef SWD_ENABLE - HAL_IWDG_Init(&hiwdg); + HAL_IWDG_Init(&hiwdg); #endif } /* TIM1 init function */ void MX_TIM1_Init(void) { - /* USER CODE BEGIN TIM1_Init 0 */ + /* USER CODE BEGIN TIM1_Init 0 */ - /* USER CODE END TIM1_Init 0 */ + /* USER CODE END TIM1_Init 0 */ - TIM_ClockConfigTypeDef sClockSourceConfig = { 0 }; - TIM_MasterConfigTypeDef sMasterConfig = { 0 }; - TIM_OC_InitTypeDef sConfigOC = { 0 }; - TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = { 0 }; + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; - /* USER CODE BEGIN TIM1_Init 1 */ + /* USER CODE BEGIN TIM1_Init 1 */ - /* USER CODE END TIM1_Init 1 */ - htim1.Instance = TIM1; - htim1.Init.Prescaler = 0; - htim1.Init.CounterMode = TIM_COUNTERMODE_UP; - htim1.Init.Period = 40; - htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; - htim1.Init.RepetitionCounter = 0; - htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; - HAL_TIM_Base_Init(&htim1); + /* USER CODE END TIM1_Init 1 */ + htim1.Instance = TIM1; + htim1.Init.Prescaler = 0; + htim1.Init.CounterMode = TIM_COUNTERMODE_UP; + htim1.Init.Period = 42; + htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim1.Init.RepetitionCounter = 0; + htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; + HAL_TIM_Base_Init(&htim1); - sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; - HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig); + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig); - HAL_TIM_PWM_Init(&htim1); + HAL_TIM_PWM_Init(&htim1); - sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; - sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; - HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig); + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig); - sConfigOC.OCMode = TIM_OCMODE_PWM1; - sConfigOC.Pulse = 0; - sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; - sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; - sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; - sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; - sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; - HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1); + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; + sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; + sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; + HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1); - sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; - sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; - sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; - sBreakDeadTimeConfig.DeadTime = 0; - sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; - sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW; - sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; - HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig); + sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; + sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; + sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + sBreakDeadTimeConfig.DeadTime = 0; + sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; + sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW; + sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; + HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig); - __HAL_RCC_GPIOA_CLK_ENABLE(); - GPIO_InitTypeDef GPIO_InitStruct; - /**TIM1 GPIO Configuration - PA8 ------> TIM1_CH1 - */ - GPIO_InitStruct.Pin = WS2812_Pin; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - HAL_GPIO_Init(WS2812_GPIO_Port, &GPIO_InitStruct); - __HAL_AFIO_REMAP_TIM1_DISABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitTypeDef GPIO_InitStruct; + /**TIM1 GPIO Configuration + PA8 ------> TIM1_CH1 + */ + GPIO_InitStruct.Pin = WS2812_Pin; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(WS2812_GPIO_Port, &GPIO_InitStruct); + __HAL_AFIO_REMAP_TIM1_DISABLE(); } /* TIM3 init function */ static void MX_TIM3_Init(void) { - TIM_ClockConfigTypeDef sClockSourceConfig; - TIM_MasterConfigTypeDef sMasterConfig; - TIM_OC_InitTypeDef sConfigOC; + TIM_ClockConfigTypeDef sClockSourceConfig; + TIM_MasterConfigTypeDef sMasterConfig; + TIM_OC_InitTypeDef sConfigOC; - htim3.Instance = TIM3; - htim3.Init.Prescaler = 1; - htim3.Init.CounterMode = TIM_COUNTERMODE_UP; - htim3.Init.Period = 255; // - htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 4mhz before div - htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; // Preload the ARR register (though we dont use this) - HAL_TIM_Base_Init(&htim3); + htim3.Instance = TIM3; + htim3.Init.Prescaler = 1; + htim3.Init.CounterMode = TIM_COUNTERMODE_UP; + htim3.Init.Period = 255; // + htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 4mhz before div + htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; // Preload the ARR register (though we dont use this) + HAL_TIM_Base_Init(&htim3); - sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; - HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig); + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig); - HAL_TIM_PWM_Init(&htim3); + HAL_TIM_PWM_Init(&htim3); - HAL_TIM_OC_Init(&htim3); + HAL_TIM_OC_Init(&htim3); - sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; - sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; - HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig); + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig); - sConfigOC.OCMode = TIM_OCMODE_PWM1; - sConfigOC.Pulse = 0; // Output control - sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; - sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; - HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, PWM_Out_CHANNEL); - // TODO need to do buzzer - GPIO_InitTypeDef GPIO_InitStruct; + sConfigOC.OCMode = TIM_OCMODE_PWM1; + sConfigOC.Pulse = 0; // Output control + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; + HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, PWM_Out_CHANNEL); + // TODO need to do buzzer + GPIO_InitTypeDef GPIO_InitStruct; - /**TIM3 GPIO Configuration - PWM_Out_Pin ------> TIM3_CH1 - */ - GPIO_InitStruct.Pin = PWM_Out_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // We would like sharp rising edges - HAL_GPIO_Init(PWM_Out_GPIO_Port, &GPIO_InitStruct); - HAL_TIM_PWM_Start(&htim3, PWM_Out_CHANNEL); + /**TIM3 GPIO Configuration + PWM_Out_Pin ------> TIM3_CH1 + */ + GPIO_InitStruct.Pin = PWM_Out_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // We would like sharp rising edges + HAL_GPIO_Init(PWM_Out_GPIO_Port, &GPIO_InitStruct); + HAL_TIM_PWM_Start(&htim3, PWM_Out_CHANNEL); } /* TIM3 init function */ static void MX_TIM2_Init(void) { - TIM_ClockConfigTypeDef sClockSourceConfig; - TIM_MasterConfigTypeDef sMasterConfig; - TIM_OC_InitTypeDef sConfigOC; + TIM_ClockConfigTypeDef sClockSourceConfig; + TIM_MasterConfigTypeDef sMasterConfig; + TIM_OC_InitTypeDef sConfigOC; - htim2.Instance = TIM2; - htim2.Init.Prescaler = 200; // 2 MHz timer clock/2000 = 1 kHz tick rate + htim2.Instance = TIM2; + htim2.Init.Prescaler = 200; // 2 MHz timer clock/2000 = 1 kHz tick rate - // pwm out is 10k from tim3, we want to run our PWM at around 10hz or slower on the output stage - // These values give a rate of around 3.5 Hz for "fast" mode and 1.84 Hz for "slow" - htim2.Init.CounterMode = TIM_COUNTERMODE_UP; - // dummy value, will be reconfigured by BSPInit() - htim2.Init.Period = 10; - htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 8 MHz (x2 APB1) before divide - htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; - htim2.Init.RepetitionCounter = 0; - HAL_TIM_Base_Init(&htim2); + // pwm out is 10k from tim3, we want to run our PWM at around 10hz or slower on the output stage + // These values give a rate of around 3.5 Hz for "fast" mode and 1.84 Hz for "slow" + htim2.Init.CounterMode = TIM_COUNTERMODE_UP; + // dummy value, will be reconfigured by BSPInit() + htim2.Init.Period = 10; + htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 8 MHz (x2 APB1) before divide + htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + htim2.Init.RepetitionCounter = 0; + HAL_TIM_Base_Init(&htim2); - sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; - HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig); + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig); - HAL_TIM_PWM_Init(&htim2); + HAL_TIM_PWM_Init(&htim2); - sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; - sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; - HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig); + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig); - sConfigOC.OCMode = TIM_OCMODE_PWM1; - // dummy value, will be reconfigured by BSPInit() in the BSP.cpp - sConfigOC.Pulse = 5; - sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; - sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; - HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4); - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Pin = HEAT_EN_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // We would like sharp rising edges - HAL_GPIO_Init(HEAT_EN_GPIO_Port, &GPIO_InitStruct); - HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4); + sConfigOC.OCMode = TIM_OCMODE_PWM1; + // dummy value, will be reconfigured by BSPInit() in the BSP.cpp + sConfigOC.Pulse = 5; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; + HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4); + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = HEAT_EN_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // We would like sharp rising edges + HAL_GPIO_Init(HEAT_EN_GPIO_Port, &GPIO_InitStruct); + HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4); } /** * Enable DMA controller clock */ static void MX_DMA_Init(void) { - /* DMA controller clock enable */ - __HAL_RCC_DMA1_CLK_ENABLE(); + /* DMA controller clock enable */ + __HAL_RCC_DMA1_CLK_ENABLE(); - /* DMA interrupt init */ - /* DMA1_Channel1_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 10, 0); - HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); - /* DMA1_Channel1_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 2, 0); // DMA 1 ch2 is used from TIM CH1 for WS2812 - HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn); - /* DMA1_Channel6_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 5, 0); - HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); - /* DMA1_Channel7_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 5, 0); - HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn); + /* DMA interrupt init */ + /* DMA1_Channel1_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 10, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); + /* DMA1_Channel1_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 2, 0); // DMA 1 ch2 is used from TIM CH1 for WS2812 + HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn); + /* DMA1_Channel6_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); + /* DMA1_Channel7_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn); } static void MX_GPIO_Init(void) { - GPIO_InitTypeDef GPIO_InitStruct; - memset(&GPIO_InitStruct, 0, sizeof(GPIO_InitStruct)); + GPIO_InitTypeDef GPIO_InitStruct; + memset(&GPIO_InitStruct, 0, sizeof(GPIO_InitStruct)); - /* GPIO Ports Clock Enable */ - __HAL_RCC_GPIOD_CLK_ENABLE(); - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); - /*Configure GPIO pin Output Level */ - HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_RESET); - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - /*Configure GPIO pins : PD0 PD1 */ - GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - /*Configure peripheral I/O remapping */ - __HAL_AFIO_REMAP_PD01_ENABLE(); - //^ remap XTAL so that pins used + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_RESET); + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + /*Configure GPIO pins : PD0 PD1 */ + GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + /*Configure peripheral I/O remapping */ + __HAL_AFIO_REMAP_PD01_ENABLE(); + //^ remap XTAL so that pins used - /* - * Configure All pins as analog by default - */ - 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_InitStruct.Mode = GPIO_MODE_ANALOG; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - 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_13 - | GPIO_PIN_14 | GPIO_PIN_15; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + /* + * Configure All pins as analog by default + */ + 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_InitStruct.Mode = GPIO_MODE_ANALOG; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + 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_13 | GPIO_PIN_14 | GPIO_PIN_15; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - /*Configure GPIO pins : KEY_B_Pin KEY_A_Pin */ - GPIO_InitStruct.Pin = KEY_B_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_PULLUP; - HAL_GPIO_Init(KEY_B_GPIO_Port, &GPIO_InitStruct); - GPIO_InitStruct.Pin = KEY_A_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_PULLUP; - HAL_GPIO_Init(KEY_A_GPIO_Port, &GPIO_InitStruct); + /*Configure GPIO pins : KEY_B_Pin KEY_A_Pin */ + GPIO_InitStruct.Pin = KEY_B_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(KEY_B_GPIO_Port, &GPIO_InitStruct); + GPIO_InitStruct.Pin = KEY_A_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(KEY_A_GPIO_Port, &GPIO_InitStruct); - /*Configure GPIO pin : OLED_RESET_Pin */ - GPIO_InitStruct.Pin = OLED_RESET_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(OLED_RESET_GPIO_Port, &GPIO_InitStruct); - HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_RESET); - - // Pull down LCD reset - HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_RESET); - HAL_Delay(30); - HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); + /*Configure GPIO pin : OLED_RESET_Pin */ + GPIO_InitStruct.Pin = OLED_RESET_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(OLED_RESET_GPIO_Port, &GPIO_InitStruct); + HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_RESET); + // Pull down LCD reset + HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_RESET); + HAL_Delay(30); + HAL_GPIO_WritePin(OLED_RESET_GPIO_Port, OLED_RESET_Pin, GPIO_PIN_SET); } #ifdef USE_FULL_ASSERT diff --git a/source/Core/BSP/MHP30/postRTOS.cpp b/source/Core/BSP/MHP30/postRTOS.cpp index 0b862aff..61e3647b 100644 --- a/source/Core/BSP/MHP30/postRTOS.cpp +++ b/source/Core/BSP/MHP30/postRTOS.cpp @@ -13,13 +13,13 @@ // Initialisation to be performed with scheduler active void postRToSInit() { - WS2812::init(); - WS2812::led_set_color(0, 0xAA, 0x55, 0x00); - while (true) { -// osDelay(1); -// WS2812::led_set_color(0, 0xFF, 0xFF, 0xFF); -// WS2812::led_update(1); - osDelay(10); - WS2812::led_update(1); - } + WS2812::init(); + WS2812::led_set_color(0, 0xAA, 0x00, 0x00); + while (true) { + // osDelay(1); + // WS2812::led_set_color(0, 0xFF, 0xFF, 0xFF); + // WS2812::led_update(1); + osDelay(10); + WS2812::led_update(1); + } } diff --git a/source/Core/Drivers/WS2812.cpp b/source/Core/Drivers/WS2812.cpp index fce3c193..f9060b56 100644 --- a/source/Core/Drivers/WS2812.cpp +++ b/source/Core/Drivers/WS2812.cpp @@ -9,190 +9,174 @@ #include "task.h" #include #include -uint8_t WS2812::leds_colors[WS2812_LED_CHANNEL_COUNT * WS2812_LED_COUNT]; +uint8_t WS2812::leds_colors[WS2812_LED_CHANNEL_COUNT * WS2812_LED_COUNT]; volatile uint16_t WS2812::tmp_led_data[2 * WS2812_RAW_BYTES_PER_LED]; -volatile uint8_t WS2812::is_reset_pulse; /*!< Status if we are sending reset pulse or led data */ -volatile uint8_t WS2812::is_updating; /*!< Is updating in progress? */ -volatile uint32_t WS2812::current_led; /*!< Current LED number we are sending */ +volatile uint8_t WS2812::is_reset_pulse; /*!< Status if we are sending reset pulse or led data */ +volatile uint8_t WS2812::is_updating; /*!< Is updating in progress? */ +volatile uint32_t WS2812::current_led; /*!< Current LED number we are sending */ void WS2812::init(void) { - memset(leds_colors, 0, sizeof(leds_colors)); - hdma_tim1_ch1.XferHalfCpltCallback = DMAHalfComplete; - hdma_tim1_ch1.XferCpltCallback = DMAComplete; - htim1.Instance->CCR1 = htim1.Instance->ARR / 2 - 1; - htim1.Instance->DIER |= TIM_DIER_CC1DE; + memset(leds_colors, 0, sizeof(leds_colors)); + hdma_tim1_ch1.XferHalfCpltCallback = DMAHalfComplete; + hdma_tim1_ch1.XferCpltCallback = DMAComplete; + htim1.Instance->CCR1 = htim1.Instance->ARR / 2 - 1; + htim1.Instance->DIER |= TIM_DIER_CC1DE; } uint8_t WS2812::led_update(uint8_t block) { - if (is_updating) { /* Check if update in progress already */ - return 0; - } - is_updating = 1; /* We are now updating */ + if (is_updating) { /* Check if update in progress already */ + return 0; + } + is_updating = 1; /* We are now updating */ - led_start_reset_pulse(1); /* Start reset pulse */ - if (block) { - while (!led_is_update_finished()) { - vTaskDelay(1); - }; /* Wait to finish */ - } - return 1; + led_start_reset_pulse(1); /* Start reset pulse */ + if (block) { + while (!led_is_update_finished()) { + vTaskDelay(1); + }; /* Wait to finish */ + } + return 1; } void WS2812::led_set_color(size_t index, uint8_t r, uint8_t g, uint8_t b) { - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 0] = r; - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 1] = g; - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 2] = b; + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 0] = r; + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 1] = g; + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 2] = b; } void WS2812::led_set_color_all(uint8_t r, uint8_t g, uint8_t b) { - for (int index = 0; index < WS2812_LED_COUNT; index++) { - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 0] = r; - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 1] = g; - leds_colors[index * WS2812_LED_CHANNEL_COUNT + 2] = b; - } + for (int index = 0; index < WS2812_LED_COUNT; index++) { + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 0] = r; + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 1] = g; + leds_colors[index * WS2812_LED_CHANNEL_COUNT + 2] = b; + } } -uint8_t WS2812::led_is_update_finished(void) { - return !is_updating; -} +uint8_t WS2812::led_is_update_finished(void) { return !is_updating; } 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) { - tmp_led_data[0] = htim1.Instance->ARR / 2; // start with half width pulse - } + if (num == 1) { + 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 */ - /* 800kHz PWM x 40 samples = ~50us pulse low */ - hdma_tim1_ch1.Instance->CCR &= (~DMA_CCR_CIRC); // clear circular flag -> normal mode - hdma_tim1_ch1.State = HAL_DMA_STATE_READY; - HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t) tmp_led_data, - (uint32_t) &htim1.Instance->CCR1, 40); - HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); + /* Set DMA to normal mode, set memory to beginning of data and length to 40 elements */ + /* 800kHz PWM x 40 samples = ~50us pulse low */ + hdma_tim1_ch1.Instance->CCR &= (~DMA_CCR_CIRC); // clear circular flag -> normal mode + hdma_tim1_ch1.State = HAL_DMA_STATE_READY; + HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t)tmp_led_data, (uint32_t)&htim1.Instance->CCR1, 2 * WS2812_RAW_BYTES_PER_LED); + HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); } -void WS2812::DMAHalfComplete(DMA_HandleTypeDef *hdma) { - led_update_sequence(0); -} +void WS2812::DMAHalfComplete(DMA_HandleTypeDef *hdma) { led_update_sequence(0); } -void WS2812::DMAComplete(DMA_HandleTypeDef *hdma) { - led_update_sequence(1); -} +void WS2812::DMAComplete(DMA_HandleTypeDef *hdma) { led_update_sequence(1); } 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 */ - /* Check for reset pulse at the end of PWM stream */ - if (is_reset_pulse == 2) { /* Check for reset pulse at the end */ - HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); - HAL_DMA_Abort(&hdma_tim1_ch1); - is_updating = 0; /* We are not updating anymore */ - return; - } + /* Check for reset pulse at the end of PWM stream */ + if (is_reset_pulse == 2) { /* Check for reset pulse at the end */ + HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); + HAL_DMA_Abort(&hdma_tim1_ch1); + is_updating = 0; /* We are not updating anymore */ + return; + } - /* Check for reset pulse on beginning of PWM stream */ - if (is_reset_pulse == 1) { /* Check if we finished with reset pulse */ - /* - * When reset pulse is active, we have to wait full DMA response, - * before we can start modifying array which is shared with DMA and PWM - */ - if (!tc) { /* We must wait for transfer complete */ - return; /* Return and wait to finish */ - } + /* Check for reset pulse on beginning of PWM stream */ + if (is_reset_pulse == 1) { /* Check if we finished with reset pulse */ + /* + * When reset pulse is active, we have to wait full DMA response, + * before we can start modifying array which is shared with DMA and PWM + */ + if (!tc) { /* We must wait for transfer complete */ + return; /* Return and wait to finish */ + } - /* Disable timer output and disable DMA stream */ - HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); - HAL_DMA_Abort(&hdma_tim1_ch1); + /* Disable timer output and disable DMA stream */ + HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); + HAL_DMA_Abort(&hdma_tim1_ch1); - is_reset_pulse = 0; /* Not in reset pulse anymore */ - current_led = 0; /* Reset current led */ - } else { - /* - * When we are not in reset mode, - * go to next led and process data for it - */ - current_led++; /* Go to next LED */ - } + is_reset_pulse = 0; /* Not in reset pulse anymore */ + current_led = 0; /* Reset current led */ + } else { + /* + * When we are not in reset mode, + * go to next led and process data for it + */ + current_led++; /* Go to next LED */ + } - /* - * This part is used to prepare data for "next" led, - * for which update will start once current transfer stops in circular mode - */ - if (current_led < WS2812_LED_COUNT) { - /* - * If we are preparing data for first time (current_led == 0) - * or if there was no TC event (it was HT): - * - * - Prepare first part of array, because either there is no transfer - * or second part (from HT to TC) is now in process for PWM transfer - * - * In other case (TC = 1) - */ - if (current_led == 0 || !tc) { - led_fill_led_pwm_data(current_led, &tmp_led_data[0]); - } else { - led_fill_led_pwm_data(current_led, - &tmp_led_data[WS2812_RAW_BYTES_PER_LED]); - } + /* + * This part is used to prepare data for "next" led, + * for which update will start once current transfer stops in circular mode + */ + if (current_led < WS2812_LED_COUNT) { + /* + * If we are preparing data for first time (current_led == 0) + * or if there was no TC event (it was HT): + * + * - Prepare first part of array, because either there is no transfer + * or second part (from HT to TC) is now in process for PWM transfer + * + * In other case (TC = 1) + */ + if (current_led == 0 || !tc) { + led_fill_led_pwm_data(current_led, &tmp_led_data[0]); + } else { + led_fill_led_pwm_data(current_led, &tmp_led_data[WS2812_RAW_BYTES_PER_LED]); + } - /* - * If we are preparing first led (current_led = 0), then: - * - * - We setup first part of array for first led, - * - We have to prepare second part for second led to have one led prepared in advance - * - Set DMA to circular mode and start the transfer + PWM output - */ - if (current_led == 0) { + /* + * If we are preparing first led (current_led = 0), then: + * + * - We setup first part of array for first led, + * - We have to prepare second part for second led to have one led prepared in advance + * - Set DMA to circular mode and start the transfer + PWM output + */ + if (current_led == 0) { - current_led++; /* Go to next LED */ - led_fill_led_pwm_data(current_led, - &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.State = HAL_DMA_STATE_READY; - HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t) tmp_led_data, - (uint32_t) &htim1.Instance->CCR1, - 2 * WS2812_RAW_BYTES_PER_LED); - HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); - } + current_led++; /* Go to next LED */ + led_fill_led_pwm_data(current_led, &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.State = HAL_DMA_STATE_READY; + HAL_DMA_Start_IT(&hdma_tim1_ch1, (uint32_t)tmp_led_data, (uint32_t)&htim1.Instance->CCR1, 2 * WS2812_RAW_BYTES_PER_LED); + HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); + } - /* - * When we reached all leds, we have to wait to transmit data for all leds before we can disable DMA and PWM: - * - * - 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, ...) - */ - } else if ((!tc && (WS2812_LED_COUNT & 0x01)) - || (tc && !(WS2812_LED_COUNT & 0x01))) { - HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); - HAL_DMA_Abort(&hdma_tim1_ch1); + /* + * When we reached all leds, we have to wait to transmit data for all leds before we can disable DMA and PWM: + * + * - 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, ...) + */ + } else if ((!tc && (WS2812_LED_COUNT & 0x01)) || (tc && !(WS2812_LED_COUNT & 0x01))) { + HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); + HAL_DMA_Abort(&hdma_tim1_ch1); - /* It is time to send final reset pulse, 50us at least */ - led_start_reset_pulse(2); /* Start reset pulse at the end */ - } + /* It is time to send final reset pulse, 50us at least */ + led_start_reset_pulse(2); /* Start reset pulse at the end */ + } } void WS2812::led_fill_led_pwm_data(size_t ledx, volatile uint16_t *ptr) { - size_t i; - uint16_t OnOffValues[] = { 2* htim1.Instance->ARR / 3, - (4 * htim1.Instance->ARR) / 3 }; + size_t i; + uint16_t OnOffValues[] = {2 * htim1.Instance->ARR / 3, (4 * htim1.Instance->ARR) / 3}; - if (ledx < WS2812_LED_COUNT) { - for (i = 0; i < 8; i++) { - //Also unmux RGB -> GRB in the index order here - ptr[i] = - (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 1] - & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0]; - ptr[8 + i] = - (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 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]; - } - } else { - //Fill with zero? - } + if (ledx < WS2812_LED_COUNT) { + for (i = 0; i < 8; i++) { + // Also unmux RGB -> GRB in the index order here + ptr[i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 1] & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0]; + ptr[8 + i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 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]; +#if WS2812_LED_CHANNEL_COUNT == 4 + ptr[24 + i] = (leds_colors[WS2812_LED_CHANNEL_COUNT * ledx + 3] & (1 << (7 - i))) ? OnOffValues[1] : OnOffValues[0]; +#endif + } + } else { + // Fill with zero? + } } diff --git a/source/Core/Drivers/WS2812.h b/source/Core/Drivers/WS2812.h index e43de1e3..3b2221c3 100644 --- a/source/Core/Drivers/WS2812.h +++ b/source/Core/Drivers/WS2812.h @@ -11,7 +11,7 @@ #ifndef CORE_DRIVERS_WS2812_H_ #define CORE_DRIVERS_WS2812_H_ #ifndef WS2812_LED_COUNT -#define WS2812_LED_COUNT 4 +#define WS2812_LED_COUNT 3 #endif #ifndef WS2812_LED_CHANNEL_COUNT #define WS2812_LED_CHANNEL_COUNT 3 @@ -19,23 +19,23 @@ #define WS2812_RAW_BYTES_PER_LED (WS2812_LED_CHANNEL_COUNT * 8) class WS2812 { public: - static void init(void); - static uint8_t led_update(uint8_t block); - static void led_set_color(size_t index, uint8_t r, uint8_t g, uint8_t b); - static void led_set_color_all(uint8_t r, uint8_t g, uint8_t b); + static void init(void); + static uint8_t led_update(uint8_t block); + static void led_set_color(size_t index, uint8_t r, uint8_t g, uint8_t b); + static void led_set_color_all(uint8_t r, uint8_t g, uint8_t b); private: - static uint8_t led_is_update_finished(void); - static void led_start_reset_pulse(uint8_t num); - static void DMAHalfComplete(DMA_HandleTypeDef *hdma); - static void DMAComplete(DMA_HandleTypeDef *hdma); - static void led_update_sequence(uint8_t tc); - static void led_fill_led_pwm_data(size_t ledx, volatile uint16_t *ptr); - static uint8_t leds_colors[WS2812_LED_CHANNEL_COUNT * WS2812_LED_COUNT]; - static volatile uint16_t tmp_led_data[2 * WS2812_RAW_BYTES_PER_LED]; - static volatile uint8_t is_reset_pulse; /*!< Status if we are sending reset pulse or led data */ - static volatile uint8_t is_updating; /*!< Is updating in progress? */ - static volatile uint32_t current_led; /*!< Current LED number we are sending */ + static uint8_t led_is_update_finished(void); + static void led_start_reset_pulse(uint8_t num); + static void DMAHalfComplete(DMA_HandleTypeDef *hdma); + static void DMAComplete(DMA_HandleTypeDef *hdma); + static void led_update_sequence(uint8_t tc); + static void led_fill_led_pwm_data(size_t ledx, volatile uint16_t *ptr); + static uint8_t leds_colors[WS2812_LED_CHANNEL_COUNT * WS2812_LED_COUNT]; + static volatile uint16_t tmp_led_data[2 * WS2812_RAW_BYTES_PER_LED]; + static volatile uint8_t is_reset_pulse; /*!< Status if we are sending reset pulse or led data */ + static volatile uint8_t is_updating; /*!< Is updating in progress? */ + static volatile uint32_t current_led; /*!< Current LED number we are sending */ }; #endif /* CORE_DRIVERS_WS2812_H_ */