258 lines
8.3 KiB
C
258 lines
8.3 KiB
C
/**
|
|
* @file board_io.c
|
|
* @brief Board-specific GPIO and shared low-level control helpers.
|
|
*/
|
|
|
|
#include "board_io.h"
|
|
|
|
#define UI_LCD_CONTRAST_PWM_FREQUENCY_HZ 20000u
|
|
#define UI_LCD_CONTRAST_PWM_PERIOD_COUNTS 1000u
|
|
#define UI_LCD_CONTRAST_PWM_DUTY_PERMILLE 300u
|
|
|
|
static TIM_HandleTypeDef g_ui_lcd_contrast_pwm_timer;
|
|
|
|
static uint32_t board_io_get_apb1_timer_clock_hz(void);
|
|
static void board_io_init_lcd_contrast_pwm(void);
|
|
|
|
void board_io_enable_uart_rx_irq(void)
|
|
{
|
|
LL_USART_EnableIT_PE(USART1);
|
|
LL_USART_EnableIT_RXNE(USART1);
|
|
LL_USART_EnableIT_ERROR(USART1);
|
|
NVIC_SetPriority(USART1_IRQn, 0);
|
|
NVIC_EnableIRQ(USART1_IRQn);
|
|
}
|
|
|
|
void board_io_init_standalone_ui(void)
|
|
{
|
|
GPIO_InitTypeDef gpio_init = {0};
|
|
|
|
__HAL_RCC_GPIOG_CLK_ENABLE();
|
|
__HAL_RCC_GPIOD_CLK_ENABLE();
|
|
|
|
HAL_GPIO_WritePin(UI_LCD_RS_GPIO_Port,
|
|
UI_LCD_RS_Pin | UI_LCD_E_Pin | UI_LCD_D4_Pin | UI_LCD_D5_Pin | UI_LCD_D6_Pin | UI_LCD_D7_Pin,
|
|
GPIO_PIN_RESET);
|
|
|
|
/*
|
|
* A fixed contrast pin is only a compromise until a potentiometer is
|
|
* added. Driving V0 low is the safest default for HD44780/SPLC780D-style
|
|
* modules because it makes characters visible instead of appearing blank.
|
|
*/
|
|
HAL_GPIO_WritePin(UI_LCD_V0_REF_GPIO_Port, UI_LCD_V0_REF_Pin, GPIO_PIN_RESET);
|
|
|
|
gpio_init.Pin = UI_LCD_RS_Pin | UI_LCD_E_Pin | UI_LCD_D4_Pin | UI_LCD_D5_Pin | UI_LCD_D6_Pin | UI_LCD_D7_Pin;
|
|
gpio_init.Mode = GPIO_MODE_OUTPUT_PP;
|
|
gpio_init.Pull = GPIO_NOPULL;
|
|
gpio_init.Speed = GPIO_SPEED_FREQ_LOW;
|
|
HAL_GPIO_Init(GPIOG, &gpio_init);
|
|
|
|
gpio_init.Pin = UI_LCD_V0_REF_Pin;
|
|
gpio_init.Mode = GPIO_MODE_OUTPUT_PP;
|
|
gpio_init.Pull = GPIO_NOPULL;
|
|
gpio_init.Speed = GPIO_SPEED_FREQ_LOW;
|
|
HAL_GPIO_Init(UI_LCD_V0_REF_GPIO_Port, &gpio_init);
|
|
|
|
gpio_init.Pin = UI_BUTTON_Pin;
|
|
gpio_init.Mode = GPIO_MODE_INPUT;
|
|
gpio_init.Pull = GPIO_PULLUP;
|
|
HAL_GPIO_Init(UI_BUTTON_GPIO_Port, &gpio_init);
|
|
|
|
board_io_init_lcd_contrast_pwm();
|
|
}
|
|
|
|
static uint32_t board_io_get_apb1_timer_clock_hz(void)
|
|
{
|
|
uint32_t pclk1_hz = HAL_RCC_GetPCLK1Freq();
|
|
|
|
if ((RCC->CFGR & RCC_CFGR_PPRE1) == RCC_CFGR_PPRE1_DIV1)
|
|
{
|
|
return pclk1_hz;
|
|
}
|
|
|
|
return pclk1_hz * 2u;
|
|
}
|
|
|
|
static void board_io_init_lcd_contrast_pwm(void)
|
|
{
|
|
GPIO_InitTypeDef gpio_init = {0};
|
|
TIM_OC_InitTypeDef pwm_channel = {0};
|
|
uint32_t timer_clock_hz = board_io_get_apb1_timer_clock_hz();
|
|
uint32_t prescaler_divisor = timer_clock_hz / (UI_LCD_CONTRAST_PWM_FREQUENCY_HZ * UI_LCD_CONTRAST_PWM_PERIOD_COUNTS);
|
|
uint32_t pulse_counts = ((UI_LCD_CONTRAST_PWM_PERIOD_COUNTS * UI_LCD_CONTRAST_PWM_DUTY_PERMILLE) + 999u) / 1000u;
|
|
|
|
if (prescaler_divisor == 0u)
|
|
{
|
|
prescaler_divisor = 1u;
|
|
}
|
|
|
|
if (pulse_counts >= UI_LCD_CONTRAST_PWM_PERIOD_COUNTS)
|
|
{
|
|
pulse_counts = UI_LCD_CONTRAST_PWM_PERIOD_COUNTS - 1u;
|
|
}
|
|
|
|
__HAL_RCC_GPIOB_CLK_ENABLE();
|
|
__HAL_RCC_TIM4_CLK_ENABLE();
|
|
|
|
/*
|
|
* This PWM output is intended for the LCD contrast input (V0) through a
|
|
* simple RC low-pass filter. Keeping it local to board_io.c avoids
|
|
* spreading board wiring assumptions into higher-level UI code.
|
|
*/
|
|
gpio_init.Pin = UI_LCD_CONTRAST_PWM_Pin;
|
|
gpio_init.Mode = GPIO_MODE_AF_PP;
|
|
gpio_init.Pull = GPIO_NOPULL;
|
|
gpio_init.Speed = GPIO_SPEED_FREQ_LOW;
|
|
gpio_init.Alternate = GPIO_AF2_TIM4;
|
|
HAL_GPIO_Init(UI_LCD_CONTRAST_PWM_GPIO_Port, &gpio_init);
|
|
|
|
g_ui_lcd_contrast_pwm_timer.Instance = TIM4;
|
|
g_ui_lcd_contrast_pwm_timer.Init.Prescaler = (uint32_t)(prescaler_divisor - 1u);
|
|
g_ui_lcd_contrast_pwm_timer.Init.CounterMode = TIM_COUNTERMODE_UP;
|
|
g_ui_lcd_contrast_pwm_timer.Init.Period = UI_LCD_CONTRAST_PWM_PERIOD_COUNTS - 1u;
|
|
g_ui_lcd_contrast_pwm_timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
|
g_ui_lcd_contrast_pwm_timer.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
|
|
|
if (HAL_TIM_PWM_Init(&g_ui_lcd_contrast_pwm_timer) != HAL_OK)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pwm_channel.OCMode = TIM_OCMODE_PWM1;
|
|
pwm_channel.Pulse = pulse_counts;
|
|
pwm_channel.OCPolarity = TIM_OCPOLARITY_HIGH;
|
|
pwm_channel.OCFastMode = TIM_OCFAST_DISABLE;
|
|
|
|
if (HAL_TIM_PWM_ConfigChannel(&g_ui_lcd_contrast_pwm_timer, &pwm_channel, TIM_CHANNEL_3) != HAL_OK)
|
|
{
|
|
return;
|
|
}
|
|
|
|
(void)HAL_TIM_PWM_Start(&g_ui_lcd_contrast_pwm_timer, TIM_CHANNEL_3);
|
|
}
|
|
|
|
void board_io_reset_runtime_outputs(void)
|
|
{
|
|
HAL_GPIO_WritePin(EN_5V1_GPIO_Port, EN_5V1_Pin, GPIO_PIN_RESET);
|
|
HAL_GPIO_WritePin(EN_5V2_GPIO_Port, EN_5V2_Pin, GPIO_PIN_RESET);
|
|
HAL_GPIO_WritePin(LD1_EN_GPIO_Port, LD1_EN_Pin, GPIO_PIN_RESET);
|
|
HAL_GPIO_WritePin(LD2_EN_GPIO_Port, LD2_EN_Pin, GPIO_PIN_RESET);
|
|
HAL_GPIO_WritePin(REF0_EN_GPIO_Port, REF0_EN_Pin, GPIO_PIN_RESET);
|
|
HAL_GPIO_WritePin(REF2_ON_GPIO_Port, REF2_ON_Pin, GPIO_PIN_RESET);
|
|
HAL_GPIO_WritePin(TECEN1_GPIO_Port, TECEN1_Pin, GPIO_PIN_RESET);
|
|
HAL_GPIO_WritePin(TECEN2_GPIO_Port, TECEN2_Pin, GPIO_PIN_RESET);
|
|
HAL_GPIO_WritePin(TEC1_PD_GPIO_Port, TEC1_PD_Pin, GPIO_PIN_RESET);
|
|
HAL_GPIO_WritePin(TEC2_PD_GPIO_Port, TEC2_PD_Pin, GPIO_PIN_RESET);
|
|
|
|
HAL_GPIO_WritePin(ADC_MPD1_CS_GPIO_Port, ADC_MPD1_CS_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(ADC_MPD2_CS_GPIO_Port, ADC_MPD2_CS_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(SPI4_CNV_GPIO_Port, SPI4_CNV_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(SPI5_CNV_GPIO_Port, SPI5_CNV_Pin, GPIO_PIN_SET);
|
|
|
|
HAL_GPIO_WritePin(DAC_LD1_CS_GPIO_Port, DAC_LD1_CS_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(DAC_LD2_CS_GPIO_Port, DAC_LD2_CS_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(DAC_TEC1_CS_GPIO_Port, DAC_TEC1_CS_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(DAC_TEC2_CS_GPIO_Port, DAC_TEC2_CS_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(AD9102_CS_GPIO_Port, AD9102_CS_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(AD9833_CS_GPIO_Port, AD9833_CS_Pin, GPIO_PIN_SET);
|
|
}
|
|
|
|
void board_io_configure_spi2_mode(uint32_t polarity, uint32_t phase)
|
|
{
|
|
if (LL_SPI_IsEnabled(SPI2))
|
|
{
|
|
LL_SPI_Disable(SPI2);
|
|
}
|
|
|
|
LL_SPI_SetClockPolarity(SPI2, polarity);
|
|
LL_SPI_SetClockPhase(SPI2, phase);
|
|
|
|
if (!LL_SPI_IsEnabled(SPI2))
|
|
{
|
|
LL_SPI_Enable(SPI2);
|
|
}
|
|
}
|
|
|
|
bool board_io_is_usb_connected(void)
|
|
{
|
|
return HAL_GPIO_ReadPin(USB_FLAG_GPIO_Port, USB_FLAG_Pin) == GPIO_PIN_SET;
|
|
}
|
|
|
|
bool board_io_is_sd_card_present(void)
|
|
{
|
|
return HAL_GPIO_ReadPin(SDMMC1_EN_GPIO_Port, SDMMC1_EN_Pin) == GPIO_PIN_RESET;
|
|
}
|
|
|
|
bool board_io_is_standalone_ui_button_pressed(void)
|
|
{
|
|
return HAL_GPIO_ReadPin(UI_BUTTON_GPIO_Port, UI_BUTTON_Pin) == GPIO_PIN_RESET;
|
|
}
|
|
|
|
void board_io_set_supply_enabled(uint8_t supply_index, bool enabled)
|
|
{
|
|
GPIO_PinState pin_state = enabled ? GPIO_PIN_SET : GPIO_PIN_RESET;
|
|
|
|
if (supply_index == 1u)
|
|
{
|
|
HAL_GPIO_WritePin(EN_5V1_GPIO_Port, EN_5V1_Pin, pin_state);
|
|
}
|
|
else if (supply_index == 2u)
|
|
{
|
|
HAL_GPIO_WritePin(EN_5V2_GPIO_Port, EN_5V2_Pin, pin_state);
|
|
}
|
|
}
|
|
|
|
void board_io_set_laser_enabled(uint8_t laser_index, bool enabled)
|
|
{
|
|
GPIO_PinState pin_state = enabled ? GPIO_PIN_SET : GPIO_PIN_RESET;
|
|
|
|
if (laser_index == 1u)
|
|
{
|
|
HAL_GPIO_WritePin(LD1_EN_GPIO_Port, LD1_EN_Pin, pin_state);
|
|
}
|
|
else if (laser_index == 2u)
|
|
{
|
|
HAL_GPIO_WritePin(LD2_EN_GPIO_Port, LD2_EN_Pin, pin_state);
|
|
}
|
|
}
|
|
|
|
void board_io_set_reference_enabled(uint8_t reference_index, bool enabled)
|
|
{
|
|
GPIO_PinState pin_state = enabled ? GPIO_PIN_SET : GPIO_PIN_RESET;
|
|
|
|
if (reference_index == 1u)
|
|
{
|
|
HAL_GPIO_WritePin(REF0_EN_GPIO_Port, REF0_EN_Pin, pin_state);
|
|
}
|
|
else if (reference_index == 2u)
|
|
{
|
|
HAL_GPIO_WritePin(REF2_ON_GPIO_Port, REF2_ON_Pin, pin_state);
|
|
}
|
|
}
|
|
|
|
void board_io_set_tec_channel_enabled(uint8_t tec_index, bool enabled)
|
|
{
|
|
GPIO_PinState pin_state = enabled ? GPIO_PIN_SET : GPIO_PIN_RESET;
|
|
|
|
if (tec_index == 1u)
|
|
{
|
|
HAL_GPIO_WritePin(TEC1_PD_GPIO_Port, TEC1_PD_Pin, pin_state);
|
|
HAL_GPIO_WritePin(TECEN1_GPIO_Port, TECEN1_Pin, pin_state);
|
|
}
|
|
else if (tec_index == 2u)
|
|
{
|
|
HAL_GPIO_WritePin(TEC2_PD_GPIO_Port, TEC2_PD_Pin, pin_state);
|
|
HAL_GPIO_WritePin(TECEN2_GPIO_Port, TECEN2_Pin, pin_state);
|
|
}
|
|
}
|
|
|
|
void board_io_write_signal(GPIO_TypeDef *port, uint16_t pin, bool level_high)
|
|
{
|
|
HAL_GPIO_WritePin(port, pin, level_high ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
|
}
|
|
|
|
void board_io_toggle_debug_pin(void)
|
|
{
|
|
HAL_GPIO_TogglePin(TEST_01_GPIO_Port, TEST_01_Pin);
|
|
}
|