altos: Use #define values for ublox packet types
[fw/altos] / src / stm / ao_beep_stm.c
1 /*
2  * Copyright © 2012 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; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include "ao.h"
19
20 #ifndef BEEPER_CHANNEL
21 #define BEEPER_CHANNEL  1
22 #endif
23
24 void
25 ao_beep(uint8_t beep)
26 {
27         if (beep == 0) {
28                 stm_tim3.cr1 = 0;
29                 stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_TIM3EN);
30         } else {
31                 stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM3EN);
32
33                 stm_tim3.cr2 = ((0 << STM_TIM234_CR2_TI1S) |
34                                 (STM_TIM234_CR2_MMS_RESET << STM_TIM234_CR2_MMS) |
35                                 (0 << STM_TIM234_CR2_CCDS));
36
37                 /* Set prescaler to match cc1111 clocks
38                  */
39                 stm_tim3.psc = AO_TIM23467_CLK / 750000;
40
41                 /* 1. Select the counter clock (internal, external, prescaler).
42                  *
43                  * Setting SMCR to zero means use the internal clock
44                  */
45
46                 stm_tim3.smcr = 0;
47
48                 /* 2. Write the desired data in the TIMx_ARR and TIMx_CCRx registers. */
49                 stm_tim3.arr = beep;
50                 stm_tim3.ccr1 = beep;
51
52                 /* 3. Set the CCxIE and/or CCxDE bits if an interrupt and/or a
53                  * DMA request is to be generated.
54                  */
55                 /* don't want this */
56
57                 /* 4. Select the output mode. For example, you must write
58                  *  OCxM=011, OCxPE=0, CCxP=0 and CCxE=1 to toggle OCx output
59                  *  pin when CNT matches CCRx, CCRx preload is not used, OCx
60                  *  is enabled and active high.
61                  */
62
63 #if BEEPER_CHANNEL == 1
64                 stm_tim3.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) |
65                                   (STM_TIM234_CCMR1_OC2M_FROZEN << STM_TIM234_CCMR1_OC2M) |
66                                   (0 << STM_TIM234_CCMR1_OC2PE) |
67                                   (0 << STM_TIM234_CCMR1_OC2FE) |
68                                   (STM_TIM234_CCMR1_CC2S_OUTPUT << STM_TIM234_CCMR1_CC2S) |
69
70                                   (0 << STM_TIM234_CCMR1_OC1CE) |
71                                   (STM_TIM234_CCMR1_OC1M_TOGGLE << STM_TIM234_CCMR1_OC1M) |
72                                   (0 << STM_TIM234_CCMR1_OC1PE) |
73                                   (0 << STM_TIM234_CCMR1_OC1FE) |
74                                   (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S));
75
76                 stm_tim3.ccer = ((0 << STM_TIM234_CCER_CC4NP) |
77                                  (0 << STM_TIM234_CCER_CC4P) |
78                                  (0 << STM_TIM234_CCER_CC4E) |
79                                  (0 << STM_TIM234_CCER_CC3NP) |
80                                  (0 << STM_TIM234_CCER_CC3P) |
81                                  (0 << STM_TIM234_CCER_CC3E) |
82                                  (0 << STM_TIM234_CCER_CC2NP) |
83                                  (0 << STM_TIM234_CCER_CC2P) |
84                                  (0 << STM_TIM234_CCER_CC2E) |
85                                  (0 << STM_TIM234_CCER_CC1NP) |
86                                  (0 << STM_TIM234_CCER_CC1P) |
87                                  (1 << STM_TIM234_CCER_CC1E));
88 #endif
89 #if BEEPER_CHANNEL == 4
90                 stm_tim3.ccmr2 = ((0 << STM_TIM234_CCMR2_OC4CE) |
91                                   (STM_TIM234_CCMR2_OC4M_TOGGLE << STM_TIM234_CCMR2_OC4M) |
92                                   (0 << STM_TIM234_CCMR2_OC4PE) |
93                                   (0 << STM_TIM234_CCMR2_OC4FE) |
94                                   (STM_TIM234_CCMR2_CC4S_OUTPUT << STM_TIM234_CCMR2_CC4S) |
95
96                                   (0 << STM_TIM234_CCMR2_OC3CE) |
97                                   (STM_TIM234_CCMR2_OC3M_FROZEN << STM_TIM234_CCMR2_OC3M) |
98                                   (0 << STM_TIM234_CCMR2_OC3PE) |
99                                   (0 << STM_TIM234_CCMR2_OC3FE) |
100                                   (STM_TIM234_CCMR2_CC3S_OUTPUT << STM_TIM234_CCMR2_CC3S));
101
102                 stm_tim3.ccer = ((0 << STM_TIM234_CCER_CC4NP) |
103                                  (0 << STM_TIM234_CCER_CC4P) |
104                                  (1 << STM_TIM234_CCER_CC4E) |
105                                  (0 << STM_TIM234_CCER_CC3NP) |
106                                  (0 << STM_TIM234_CCER_CC3P) |
107                                  (0 << STM_TIM234_CCER_CC3E) |
108                                  (0 << STM_TIM234_CCER_CC2NP) |
109                                  (0 << STM_TIM234_CCER_CC2P) |
110                                  (0 << STM_TIM234_CCER_CC2E) |
111                                  (0 << STM_TIM234_CCER_CC1NP) |
112                                  (0 << STM_TIM234_CCER_CC1P) |
113                                  (0 << STM_TIM234_CCER_CC1E));
114 #endif
115
116
117                 /* 5. Enable the counter by setting the CEN bit in the TIMx_CR1 register. */
118
119                 stm_tim3.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) |
120                                 (0 << STM_TIM234_CR1_ARPE) |
121                                 (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) |
122                                 (0 << STM_TIM234_CR1_DIR) |
123                                 (0 << STM_TIM234_CR1_OPM) |
124                                 (0 << STM_TIM234_CR1_URS) |
125                                 (0 << STM_TIM234_CR1_UDIS) |
126                                 (1 << STM_TIM234_CR1_CEN));
127
128                 /* Update the values */
129                 stm_tim3.egr = (1 << STM_TIM234_EGR_UG);
130         }
131 }
132
133 void
134 ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant
135 {
136         ao_beep(beep);
137         ao_delay(ticks);
138         ao_beep(0);
139 }
140
141 void
142 ao_beep_init(void)
143 {
144 #if BEEPER_CHANNEL == 1
145
146         /* Our beeper is on PC6, which is hooked to TIM3_CH1.
147          */
148         stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN);
149
150         stm_afr_set(&stm_gpioc, 6, STM_AFR_AF2);
151 #endif
152 #if BEEPER_CHANNEL == 4
153
154         /* Our beeper is on PB1, which is hooked to TIM3_CH4.
155          */
156         stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
157
158         stm_afr_set(&stm_gpiob, 1, STM_AFR_AF2);
159 #endif
160
161         /* Leave the timer off until requested */
162         
163         stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_TIM3EN);
164 }