altos/test: Adjust CRC error rate after FEC fix
[fw/altos] / src / lpc / ao_fast_timer_lpc.c
1 /*
2  * Copyright © 2016 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include <ao.h>
20 #include <ao_fast_timer.h>
21
22 static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void);
23 static uint8_t ao_fast_timer_count;
24 static uint8_t ao_fast_timer_users;
25
26 static void
27 ao_fast_timer_enable(void)
28 {
29         lpc_ct16b0.tcr = ((1 << LPC_CT16B_TCR_CEN) |
30                           (1 << LPC_CT16B_TCR_CRST));
31 }
32
33 static void
34 ao_fast_timer_disable(void)
35 {
36         lpc_ct16b0.tcr = ((0 << LPC_CT16B_TCR_CEN) |
37                           (0 << LPC_CT16B_TCR_CRST));
38 }
39
40 void
41 ao_fast_timer_on(void (*callback)(void))
42 {
43         ao_fast_timer_callback[ao_fast_timer_count] = callback;
44         if (!ao_fast_timer_count++)
45                 ao_fast_timer_enable();
46 }
47
48 void
49 ao_fast_timer_off(void (*callback)(void))
50 {
51         uint8_t n;
52
53         for (n = 0; n < ao_fast_timer_count; n++)
54                 if (ao_fast_timer_callback[n] == callback) {
55                         for (; n < ao_fast_timer_count-1; n++) {
56                                 ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1];
57                         }
58                         if (!--ao_fast_timer_count)
59                                 ao_fast_timer_disable();
60                         break;
61                 }
62 }
63
64 void lpc_ct16b0_isr(void)
65 {
66         uint32_t        v = lpc_ct16b0.ir;
67         int             i;
68
69         lpc_ct16b0.ir = v;
70         if (v & (1 << LPC_CT16B_IR_MR0INT)) {
71                 for (i = 0; i < ao_fast_timer_count; i++)
72                         (*ao_fast_timer_callback[i])();
73         }
74 }
75
76 #ifndef FAST_TIMER_FREQ
77 #define FAST_TIMER_FREQ 10000
78 #endif
79
80 #define TIMER_FAST      (AO_LPC_SYSCLK / FAST_TIMER_FREQ)
81
82 void
83 ao_fast_timer_init(void)
84 {
85         if (!ao_fast_timer_users) {
86
87                 lpc_nvic_set_enable(LPC_ISR_CT16B0_POS);
88                 lpc_nvic_set_priority(LPC_ISR_CT16B0_POS, AO_LPC_NVIC_CLOCK_PRIORITY);
89                 /* Turn on 16-bit timer CT16B0 */
90
91                 lpc_scb.sysahbclkctrl |= 1 << LPC_SCB_SYSAHBCLKCTRL_CT16B0;
92
93                 /* Disable timer */
94                 lpc_ct16b0.tcr = 0;
95
96                 /* scale factor 1 */
97                 lpc_ct16b0.pr = 0;
98                 lpc_ct16b0.pc = 0;
99
100                 lpc_ct16b0.mcr = ((1 << LPC_CT16B_MCR_MR0I) |
101                                   (1 << LPC_CT16B_MCR_MR0R));
102
103                 lpc_ct16b0.mr[0] = TIMER_FAST;
104
105                 ao_fast_timer_disable();
106         }
107         if (ao_fast_timer_users == AO_FAST_TIMER_MAX)
108                 ao_panic(AO_PANIC_FAST_TIMER);
109         ao_fast_timer_users++;
110 }
111