148 lines
3.0 KiB
C
148 lines
3.0 KiB
C
#include <libopencm3/stm32/rcc.h>
|
|
#include <libopencm3/stm32/gpio.h>
|
|
#include <libopencm3/cm3/systick.h>
|
|
#include <libopencmsis/core_cm3.h>
|
|
|
|
#include "uart.h"
|
|
#include "temp_sensor.h"
|
|
#include "fan_ctrl_pwm.h"
|
|
#include "fan_ctrl_dc.h"
|
|
#include "fan_controller.h"
|
|
#include "eeprom_config.h"
|
|
|
|
#include "pinout.h"
|
|
|
|
#define SYSTICK_FREQ 10 // Hz
|
|
|
|
static uint64_t timebase_ms = 0;
|
|
static bool systick_triggered = false;
|
|
|
|
static void clock_setup(void)
|
|
{
|
|
/* We are running on MSI (2.1 MHz) after boot. */
|
|
rcc_periph_clock_enable(RCC_GPIOA); // for basically everything
|
|
|
|
/* Enable clocks for peripherals. */
|
|
rcc_periph_clock_enable(RCC_USART2);
|
|
rcc_periph_clock_enable(RCC_ADC1);
|
|
rcc_periph_clock_enable(RCC_DMA);
|
|
rcc_periph_clock_enable(RCC_TIM21);
|
|
}
|
|
|
|
/* Set up systick to fire freq times per second */
|
|
static void init_systick(int freq)
|
|
{
|
|
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
|
|
/* clear counter so it starts right away */
|
|
STK_CVR = 0;
|
|
|
|
systick_set_reload(rcc_ahb_frequency / freq);
|
|
systick_counter_enable();
|
|
systick_interrupt_enable();
|
|
}
|
|
|
|
|
|
int main(void)
|
|
{
|
|
// delay startup a bit to allow debugger to connect before debug pins are
|
|
// reconfigured to UART.
|
|
for(uint32_t i = 0; i < 1000000; i++) {
|
|
__asm__("nop");
|
|
}
|
|
|
|
clock_setup();
|
|
init_systick(SYSTICK_FREQ);
|
|
|
|
uart_init();
|
|
temp_sensor_init();
|
|
|
|
bool use_dcdc = EEPROM_CONFIG_FLAGS & EEPROM_CONFIG_FLAG_USE_DCDC_CONTROL;
|
|
|
|
if(use_dcdc) {
|
|
fan_ctrl_dc_init();
|
|
} else {
|
|
fan_ctrl_pwm_init();
|
|
}
|
|
|
|
fan_controller_init();
|
|
|
|
uart_enqueue("TinyFanControl v" VERSION " initialized.\n");
|
|
|
|
uint8_t last_duty = 0;
|
|
|
|
gpio_clear(LED_PORT, LED_PIN);
|
|
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_PIN);
|
|
|
|
while (1) {
|
|
if(systick_triggered) {
|
|
systick_triggered = false;
|
|
|
|
timebase_ms += 1000 / SYSTICK_FREQ;
|
|
|
|
uint32_t timebase_ms_fast = timebase_ms & 0xFFFFFFFF;
|
|
|
|
if(timebase_ms_fast <= 1000) {
|
|
if((timebase_ms_fast % 100) == 0) {
|
|
gpio_toggle(LED_PORT, LED_PIN);
|
|
}
|
|
} else {
|
|
// start the measurement in the background.
|
|
temp_sensor_trigger_update();
|
|
}
|
|
}
|
|
|
|
// check for completion of a measurement
|
|
if(temp_sensor_has_new_values()) {
|
|
// if a temperature update is available, run the control loop.
|
|
fxp_t temperature = temp_sensor_get_ntc_temperature();
|
|
|
|
uint8_t duty = fan_controller_update(temperature);
|
|
|
|
// handle fan power-on and power-off
|
|
if(last_duty == 0 && duty != 0) {
|
|
gpio_set(LED_PORT, LED_PIN);
|
|
|
|
if(use_dcdc) {
|
|
fan_ctrl_dc_enable();
|
|
} else {
|
|
fan_ctrl_pwm_enable();
|
|
}
|
|
} else if(last_duty != 0 && duty == 0) {
|
|
gpio_clear(LED_PORT, LED_PIN);
|
|
|
|
if(use_dcdc) {
|
|
fan_ctrl_dc_disable();
|
|
} else {
|
|
fan_ctrl_pwm_disable();
|
|
}
|
|
}
|
|
|
|
// set the updated duty cycle
|
|
if(use_dcdc) {
|
|
fan_ctrl_dc_set_duty(duty);
|
|
} else {
|
|
fan_ctrl_pwm_set_duty(duty);
|
|
}
|
|
|
|
last_duty = duty;
|
|
}
|
|
|
|
__WFI();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Called when systick fires */
|
|
void sys_tick_handler(void)
|
|
{
|
|
systick_triggered = true;
|
|
}
|
|
|
|
|
|
void hard_fault_handler(void)
|
|
{
|
|
while (1);
|
|
}
|