]> mj.ucw.cz Git - home-hw.git/blob - test-opencm3/test.c
DS18B20: Better timer magic
[home-hw.git] / test-opencm3 / test.c
1 #include "util.h"
2 #include "ds18b20.h"
3
4 #include <libopencm3/cm3/nvic.h>
5 #include <libopencm3/cm3/systick.h>
6 #include <libopencm3/stm32/rcc.h>
7 #include <libopencm3/stm32/gpio.h>
8 #include <libopencm3/stm32/timer.h>
9 #include <libopencm3/stm32/usart.h>
10
11 static void clock_setup(void)
12 {
13         rcc_clock_setup_in_hse_8mhz_out_72mhz();
14
15         rcc_periph_clock_enable(RCC_GPIOA);
16         rcc_periph_clock_enable(RCC_GPIOB);
17         rcc_periph_clock_enable(RCC_GPIOC);
18         rcc_periph_clock_enable(RCC_USART1);
19         rcc_periph_clock_enable(RCC_TIM3);
20         rcc_periph_clock_enable(RCC_TIM4);
21         rcc_periph_clock_enable(RCC_DMA1);
22 }
23
24 static void gpio_setup(void)
25 {
26         // PC13 = BluePill LED
27         gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
28         gpio_clear(GPIOC, GPIO13);
29
30         // PC14 = bypass LED*
31         gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO14);
32         gpio_set(GPIOC, GPIO14);
33
34         // PC15 = bypass opto-coupler
35         gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
36         gpio_clear(GPIOC, GPIO15);
37 }
38
39 static volatile u32 ms_ticks;
40
41 void sys_tick_handler(void)
42 {
43         ms_ticks++;
44 }
45
46 static void tick_setup(void)
47 {
48         systick_set_frequency(1000, 72000000);
49         systick_counter_enable();
50         systick_interrupt_enable();
51 }
52
53 static void delay_ms(uint ms)
54 {
55         u32 start_ticks = ms_ticks;
56         while (ms_ticks - start_ticks < ms)
57                 ;
58 }
59
60 static void usart_setup(void)
61 {
62         gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
63
64         usart_set_baudrate(USART1, 115200);
65         usart_set_databits(USART1, 8);
66         usart_set_stopbits(USART1, USART_STOPBITS_1);
67         usart_set_mode(USART1, USART_MODE_TX_RX);
68         usart_set_parity(USART1, USART_PARITY_NONE);
69         usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
70
71         usart_enable(USART1);
72 }
73
74 static bool bypass_active;
75 static byte pwm;
76
77 static void show_temperature(void)
78 {
79         debug_putc('#');
80         for (uint i=0; ds_sensors[i].address[0]; i++) {
81                 debug_putc(' ');
82                 int t = ds_sensors[i].current_temp;
83                 if (t == DS_TEMP_UNKNOWN)
84                         debug_puts("---.---");
85                 else
86                         debug_printf("%3d.%03d", t / 1000, t % 1000);
87         }
88         debug_printf(" %d", bypass_active);
89         debug_printf(" %d", pwm);
90         debug_puts("\r\n");
91 }
92
93 static void pwm_init(void)
94 {
95         timer_set_prescaler(TIM4, 3);   // clock = 72 MHz / 2 = 36 MHz
96         timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
97         timer_disable_preload(TIM4);
98         timer_set_period(TIM4, 255);    // PWM frequency = 18 MHz / 256 = 70.3125 kHz   FIXME
99         timer_set_oc_mode(TIM4, TIM_OC1, TIM_OCM_PWM1);
100         timer_set_oc_value(TIM4, TIM_OC1, 1);
101         pwm = 1;
102         /*
103          *      1       0.03
104          *      4       0.48
105          *      8       1.54
106          *      12      2.71
107          *      16      3.99
108          *      24      6.34
109          *      32      7.85
110          *      64      7.95
111          *      128     8.02
112          *      255     
113          */
114         timer_set_oc_polarity_high(TIM4, TIM_OC1);
115         timer_enable_counter(TIM4);
116         timer_enable_oc_output(TIM4, TIM_OC1);
117
118         gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO6);
119 }
120
121 int main(void)
122 {
123         clock_setup();
124         gpio_setup();
125         tick_setup();
126         usart_setup();
127         pwm_init();
128
129         ds_init();
130
131         byte cycles = 0;
132         for (;;) {
133                 gpio_toggle(GPIOC, GPIO13);
134                 delay_ms(100);
135                 ds_step();
136                 if (usart_get_flag(USART1, USART_SR_RXNE)) {
137                         uint ch = usart_recv(USART1);
138                         if (ch == 'B') {
139                                 bypass_active = 1;
140                                 gpio_set(GPIOC, GPIO15);        // opto-coupler
141                                 gpio_clear(GPIOC, GPIO14);      // LED
142                         } else if (ch == 'b') {
143                                 bypass_active = 0;
144                                 gpio_clear(GPIOC, GPIO15);      // opto-coupler
145                                 gpio_set(GPIOC, GPIO14);        // LED
146                         } else if (ch >= '0' && ch <= '9') {
147                                 pwm = 3*(ch - '0') + 1;
148                                 /*
149                                  *      ch      pwm       %
150                                  *      0         1       0
151                                  *      1         4       0
152                                  *      2         7      18
153                                  *      3        10      31
154                                  *      4        13      44
155                                  *      5        16      57
156                                  *      6        19      71
157                                  *      7        22      84
158                                  *      8        25      97
159                                  *      9        28     100
160                                  *
161                                  *      % = pwm*4.389 - 12.723
162                                  */
163                                 timer_set_oc_value(TIM4, TIM_OC1, pwm);
164                         }
165                 }
166                 if (cycles++ >= 50) {
167                         cycles = 0;
168                         show_temperature();
169                 }
170         }
171
172         return 0;
173 }