Fixes to usb stack so that it works
[barbilliards.git] / src / timer.c
1 // vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
2 /*
3  * This file is part of the libopencm3 project.
4  *
5  * Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
6  *
7  * This library is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <libopencm3/stm32/rcc.h>
24 #include <libopencm3/stm32/gpio.h>
25 #include <libopencm3/cm3/nvic.h>
26 #include <libopencm3/cm3/systick.h>
27 #include <libopencm3/usb/usbd.h>
28 #include <libopencm3/usb/cdc.h>
29
30 #include "usb_cdcacm.h"
31
32 uint32_t n_millis_total = 0;
33 uint32_t n_millis_cur = 0;
34 uint8_t n_millis_loops = 0;
35 usbd_device *usbd_dev;
36 static uint32_t game_time = 14 * 60 * 1000; // 15 minutes of 1ms ticks
37
38 void sys_tick_handler(void) {
39     ++n_millis_cur;
40     ++n_millis_total;
41
42     if (n_millis_total >= game_time) {
43         gpio_clear(GPIOC, GPIO13); // turn on LED
44         return;
45     }
46
47     /* calculate remaining seconds to print out on the serial port, only do this every
48        1000 millis or so */
49     if (n_millis_loops >= 4) {
50         char time_remaining[6];
51         uint32_t seconds_remaining = (uint32_t)((game_time - n_millis_total) / 1000);
52         int minutes = (int)(seconds_remaining / 60);
53         int seconds = (int)(seconds_remaining % 60);
54         sprintf(time_remaining, "%02d:%02d", minutes, seconds);
55         for (int i = 0; i < 5; i++) {
56             cdcacm_putchar(time_remaining[i]);
57         }
58         cdcacm_putchar('\r');
59         cdcacm_putchar('\n');
60     }
61
62     if (n_millis_cur >= 250) {
63         gpio_toggle(GPIOC, GPIO13);
64         ++n_millis_loops;
65         n_millis_cur = 0;
66         return;
67     }
68
69     return;
70 }
71
72 static void clock_setup(void) {
73     /* Run CPU at 72MHz */
74     rcc_clock_setup_in_hse_8mhz_out_72mhz();
75     rcc_periph_clock_enable(RCC_GPIOA);
76     rcc_periph_clock_enable(RCC_GPIOC);
77     rcc_periph_clock_enable(RCC_AFIO);
78
79     AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON;
80
81     /* 72MHz / 8 => 9000000 counts per second */
82     systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
83
84     /* 9000000 / 9000 = 1000 overflows per second - every 1ms one interrupt */
85     /* SysTick interrupt every N clock pulses: set reload to N-1 */
86     systick_set_reload(8999); // 1 ms
87     systick_interrupt_enable();
88     systick_counter_enable();
89 }
90
91 static void gpio_setup(void) {
92     // Built-in LED on blue pill board, PC13
93     gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
94         GPIO_CNF_OUTPUT_PUSHPULL, GPIO13);
95     gpio_set(GPIOC, GPIO13);
96 }
97
98 int main(void)
99 {
100     clock_setup();
101     gpio_setup();
102     cdcacm_setup();
103
104     gpio_set(GPIOC, GPIO13);
105
106     while (1) {
107         __asm__("nop");
108     }
109
110     return 0;
111 }
112