altos/stmf0: Pull beeper pin low when beeper is off
[fw/altos] / src / stmf0 / 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 #error BEEPER_CHANNEL undefined
22 #endif
23
24 #ifndef BEEPER_TIMER
25 #define BEEPER_TIMER    1
26 #endif
27
28 #if BEEPER_TIMER == 1
29 #define timer stm_tim1
30 #define STM_RCC_TIMER STM_RCC_APB2ENR_TIM1EN
31 #define stm_rcc_enr stm_rcc.apb2enr
32 #endif
33
34 #if BEEPER_TIMER == 2
35 #define timer stm_tim2
36 #define STM_RCC_TIMER STM_RCC_APB1ENR_TIM2EN
37 #define stm_rcc_enr stm_rcc.apb1enr
38 #endif
39
40 #if BEEPER_TIMER == 3
41 #define timer stm_tim3
42 #define STM_RCC_TIMER STM_RCC_APB1ENR_TIM3EN
43 #define stm_rcc_enr stm_rcc.apb1enr
44 #endif
45
46 #ifndef timer
47 #error BEEPER_TIMER invalid
48 #endif
49
50 static inline void
51 disable(void)
52 {
53         timer.cr1 = 0;
54 #if BEEPER_TIMER == 1
55         timer.bdtr = 0;
56 #endif
57         stm_rcc_enr &= ~(1 << STM_RCC_TIMER);
58
59         /* Disconnect the timer from the pin */
60         stm_afr_set(BEEPER_PORT, BEEPER_PIN, STM_AFR_NONE);
61 }
62
63 void
64 ao_beep(uint8_t beep)
65 {
66         if (beep == 0) {
67                 disable();
68         } else {
69                 stm_rcc_enr |= (1 << STM_RCC_TIMER);
70
71 #if BEEPER_TIMER == 1
72                 /* Master output enable */
73                 stm_tim1.bdtr = (1 << STM_TIM1_BDTR_MOE);
74
75                 stm_tim1.cr2 = ((0 << STM_TIM1_CR2_TI1S) |
76                                 (STM_TIM1_CR2_MMS_RESET << STM_TIM1_CR2_MMS) |
77                                 (0 << STM_TIM1_CR2_CCDS));
78
79                 /* Set prescaler to match cc1111 clocks
80                  */
81                 stm_tim1.psc = AO_TIM_CLK / 750000;
82
83                 /* 1. Select the counter clock (internal, external, prescaler).
84                  *
85                  * Setting SMCR to zero means use the internal clock
86                  */
87
88                 stm_tim1.smcr = 0;
89
90                 /* 2. Write the desired data in the TIMx_ARR and TIMx_CCRx registers. */
91                 stm_tim1.arr = beep;
92                 stm_tim1.ccr1 = beep;
93
94                 /* 3. Set the CCxIE and/or CCxDE bits if an interrupt and/or a
95                  * DMA request is to be generated.
96                  */
97                 /* don't want this */
98
99                 /* 4. Select the output mode. For example, you must write
100                  *  OCxM=011, OCxPE=0, CCxP=0 and CCxE=1 to toggle OCx output
101                  *  pin when CNT matches CCRx, CCRx preload is not used, OCx
102                  *  is enabled and active high.
103                  */
104
105 #if BEEPER_CHANNEL == 1
106                 stm_tim1.ccmr1 = ((0 << STM_TIM1_CCMR1_OC2CE) |
107                                   (STM_TIM1_CCMR_OCM_FROZEN << STM_TIM1_CCMR1_OC2M) |
108                                   (0 << STM_TIM1_CCMR1_OC2PE) |
109                                   (0 << STM_TIM1_CCMR1_OC2FE) |
110                                   (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR1_CC2S) |
111
112                                   (0 << STM_TIM1_CCMR1_OC1CE) |
113                                   (STM_TIM1_CCMR_OCM_TOGGLE << STM_TIM1_CCMR1_OC1M) |
114                                   (0 << STM_TIM1_CCMR1_OC1PE) |
115                                   (0 << STM_TIM1_CCMR1_OC1FE) |
116                                   (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR1_CC1S));
117
118                 stm_tim1.ccer = ((0 << STM_TIM1_CCER_CC4P) |
119                                  (0 << STM_TIM1_CCER_CC4E) |
120                                  (0 << STM_TIM1_CCER_CC3NP) |
121                                  (0 << STM_TIM1_CCER_CC3NE) |
122                                  (0 << STM_TIM1_CCER_CC3P) |
123                                  (0 << STM_TIM1_CCER_CC3E) |
124                                  (0 << STM_TIM1_CCER_CC2NP) |
125                                  (0 << STM_TIM1_CCER_CC2NE) |
126                                  (0 << STM_TIM1_CCER_CC2P) |
127                                  (0 << STM_TIM1_CCER_CC2E) |
128                                  (0 << STM_TIM1_CCER_CC1NE) |
129                                  (0 << STM_TIM1_CCER_CC1P) |
130                                  (1 << STM_TIM1_CCER_CC1E));
131 #endif
132 #if BEEPER_CHANNEL == 2
133                 stm_tim1.ccmr1 = ((0 << STM_TIM1_CCMR1_OC2CE) |
134                                   (STM_TIM1_CCMR_OCM_TOGGLE << STM_TIM1_CCMR1_OC2M) |
135                                   (0 << STM_TIM1_CCMR1_OC2PE) |
136                                   (0 << STM_TIM1_CCMR1_OC2FE) |
137                                   (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR1_CC2S) |
138
139                                   (0 << STM_TIM1_CCMR1_OC1CE) |
140                                   (STM_TIM1_CCMR_OCM_FROZEN << STM_TIM1_CCMR1_OC1M) |
141                                   (0 << STM_TIM1_CCMR1_OC1PE) |
142                                   (0 << STM_TIM1_CCMR1_OC1FE) |
143                                   (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR1_CC1S));
144
145                 stm_tim1.ccer = ((0 << STM_TIM1_CCER_CC4P) |
146                                  (0 << STM_TIM1_CCER_CC4E) |
147                                  (0 << STM_TIM1_CCER_CC3NP) |
148                                  (0 << STM_TIM1_CCER_CC3NE) |
149                                  (0 << STM_TIM1_CCER_CC3P) |
150                                  (0 << STM_TIM1_CCER_CC3E) |
151                                  (0 << STM_TIM1_CCER_CC2NP) |
152                                  (0 << STM_TIM1_CCER_CC2NE) |
153                                  (0 << STM_TIM1_CCER_CC2P) |
154                                  (1 << STM_TIM1_CCER_CC2E) |
155                                  (0 << STM_TIM1_CCER_CC1NE) |
156                                  (0 << STM_TIM1_CCER_CC1P) |
157                                  (0 << STM_TIM1_CCER_CC1E));
158 #endif
159 #if BEEPER_CHANNEL == 3
160                 stm_tim1.ccmr2 = ((0 << STM_TIM1_CCMR2_OC4CE) |
161                                   (STM_TIM1_CCMR_OCM_FROZEN << STM_TIM1_CCMR2_OC4M) |
162                                   (0 << STM_TIM1_CCMR2_OC4PE) |
163                                   (0 << STM_TIM1_CCMR2_OC4FE) |
164                                   (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR2_CC4S) |
165
166                                   (0 << STM_TIM1_CCMR2_OC3CE) |
167                                   (STM_TIM1_CCMR_OCM_TOGGLE << STM_TIM1_CCMR2_OC3M) |
168                                   (0 << STM_TIM1_CCMR2_OC3PE) |
169                                   (0 << STM_TIM1_CCMR2_OC3FE) |
170                                   (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR2_CC3S));
171
172                 stm_tim1.ccer = ((0 << STM_TIM1_CCER_CC4P) |
173                                  (0 << STM_TIM1_CCER_CC4E) |
174                                  (0 << STM_TIM1_CCER_CC3NP) |
175                                  (0 << STM_TIM1_CCER_CC3NE) |
176                                  (0 << STM_TIM1_CCER_CC3P) |
177                                  (1 << STM_TIM1_CCER_CC3E) |
178                                  (0 << STM_TIM1_CCER_CC2NP) |
179                                  (0 << STM_TIM1_CCER_CC2NE) |
180                                  (0 << STM_TIM1_CCER_CC2P) |
181                                  (0 << STM_TIM1_CCER_CC2E) |
182                                  (0 << STM_TIM1_CCER_CC1NE) |
183                                  (0 << STM_TIM1_CCER_CC1P) |
184                                  (0 << STM_TIM1_CCER_CC1E));
185 #endif
186 #if BEEPER_CHANNEL == 4
187                 stm_tim1.ccmr2 = ((0 << STM_TIM1_CCMR2_OC4CE) |
188                                   (STM_TIM1_CCMR2_OC4M_TOGGLE << STM_TIM1_CCMR2_OC4M) |
189                                   (0 << STM_TIM1_CCMR2_OC4PE) |
190                                   (0 << STM_TIM1_CCMR2_OC4FE) |
191                                   (STM_TIM1_CCMR2_CC4S_OUTPUT << STM_TIM1_CCMR2_CC4S) |
192
193                                   (0 << STM_TIM1_CCMR2_OC3CE) |
194                                   (STM_TIM1_CCMR2_OC3M_FROZEN << STM_TIM1_CCMR2_OC3M) |
195                                   (0 << STM_TIM1_CCMR2_OC3PE) |
196                                   (0 << STM_TIM1_CCMR2_OC3FE) |
197                                   (STM_TIM1_CCMR2_CC3S_OUTPUT << STM_TIM1_CCMR2_CC3S));
198
199                 stm_tim1.ccer = ((0 << STM_TIM1_CCER_CC4NP) |
200                                  (0 << STM_TIM1_CCER_CC4P) |
201                                  (1 << STM_TIM1_CCER_CC4E) |
202                                  (0 << STM_TIM1_CCER_CC3NP) |
203                                  (0 << STM_TIM1_CCER_CC3P) |
204                                  (0 << STM_TIM1_CCER_CC3E) |
205                                  (0 << STM_TIM1_CCER_CC2NP) |
206                                  (0 << STM_TIM1_CCER_CC2P) |
207                                  (0 << STM_TIM1_CCER_CC2E) |
208                                  (0 << STM_TIM1_CCER_CC1NP) |
209                                  (0 << STM_TIM1_CCER_CC1P) |
210                                  (0 << STM_TIM1_CCER_CC1E));
211 #endif
212                 /* 5. Enable the counter by setting the CEN bit in the TIMx_CR1 register. */
213
214                 stm_tim1.cr1 = ((STM_TIM1_CR1_CKD_1 << STM_TIM1_CR1_CKD) |
215                                 (0 << STM_TIM1_CR1_ARPE) |
216                                 (STM_TIM1_CR1_CMS_EDGE << STM_TIM1_CR1_CMS) |
217                                 (0 << STM_TIM1_CR1_DIR) |
218                                 (0 << STM_TIM1_CR1_OPM) |
219                                 (0 << STM_TIM1_CR1_URS) |
220                                 (0 << STM_TIM1_CR1_UDIS) |
221                                 (1 << STM_TIM1_CR1_CEN));
222
223                 /* Update the values */
224                 stm_tim1.egr = (1 << STM_TIM1_EGR_UG);
225 #endif
226 #if BEEPER_TIMER == 2 || BEEPER_TIMER == 3
227
228                 timer.cr2 = ((0 << STM_TIM23_CR2_TI1S) |
229                              (STM_TIM23_CR2_MMS_RESET << STM_TIM23_CR2_MMS) |
230                              (0 << STM_TIM23_CR2_CCDS));
231
232                 /* Set prescaler to match cc1111 clocks
233                  */
234                 timer.psc = AO_TIM_CLK / 750000;
235
236                 /* 1. Select the counter clock (internal, external, prescaler).
237                  *
238                  * Setting SMCR to zero means use the internal clock
239                  */
240
241                 timer.smcr = 0;
242
243                 /* 2. Write the desired data in the TIMx_ARR and TIMx_CCRx registers. */
244                 timer.arr = beep;
245                 timer.ccr1 = beep;
246
247                 /* 3. Set the CCxIE and/or CCxDE bits if an interrupt and/or a
248                  * DMA request is to be generated.
249                  */
250                 /* don't want this */
251
252                 /* 4. Select the output mode. For example, you must write
253                  *  OCxM=011, OCxPE=0, CCxP=0 and CCxE=1 to toggle OCx output
254                  *  pin when CNT matches CCRx, CCRx preload is not used, OCx
255                  *  is enabled and active high.
256                  */
257
258 #if BEEPER_CHANNEL == 1
259                 timer.ccmr1 = ((0 << STM_TIM23_CCMR1_OC2CE) |
260                                (STM_TIM23_CCMR1_OC2M_FROZEN << STM_TIM23_CCMR1_OC2M) |
261                                (0 << STM_TIM23_CCMR1_OC2PE) |
262                                (0 << STM_TIM23_CCMR1_OC2FE) |
263                                (STM_TIM23_CCMR1_CC2S_OUTPUT << STM_TIM23_CCMR1_CC2S) |
264
265                                (0 << STM_TIM23_CCMR1_OC1CE) |
266                                (STM_TIM23_CCMR1_OC1M_TOGGLE << STM_TIM23_CCMR1_OC1M) |
267                                (0 << STM_TIM23_CCMR1_OC1PE) |
268                                (0 << STM_TIM23_CCMR1_OC1FE) |
269                                (STM_TIM23_CCMR1_CC1S_OUTPUT << STM_TIM23_CCMR1_CC1S));
270
271                 timer.ccer = ((0 << STM_TIM23_CCER_CC4P) |
272                               (0 << STM_TIM23_CCER_CC4E) |
273                               (0 << STM_TIM23_CCER_CC3NP) |
274                               (0 << STM_TIM23_CCER_CC3P) |
275                               (0 << STM_TIM23_CCER_CC3E) |
276                               (0 << STM_TIM23_CCER_CC2NP) |
277                               (0 << STM_TIM23_CCER_CC2P) |
278                               (0 << STM_TIM23_CCER_CC2E) |
279                               (0 << STM_TIM23_CCER_CC1P) |
280                               (1 << STM_TIM23_CCER_CC1E));
281 #endif
282 #if BEEPER_CHANNEL == 2
283                 timer.ccmr1 = ((0 << STM_TIM23_CCMR1_OC2CE) |
284                                (STM_TIM23_CCMR1_OC2M_TOGGLE << STM_TIM23_CCMR1_OC2M) |
285                                (0 << STM_TIM23_CCMR1_OC2PE) |
286                                (0 << STM_TIM23_CCMR1_OC2FE) |
287                                (STM_TIM23_CCMR1_CC2S_OUTPUT << STM_TIM23_CCMR1_CC2S) |
288
289                                (0 << STM_TIM23_CCMR1_OC1CE) |
290                                (STM_TIM23_CCMR1_OC1M_FROZEN << STM_TIM23_CCMR1_OC1M) |
291                                (0 << STM_TIM23_CCMR1_OC1PE) |
292                                (0 << STM_TIM23_CCMR1_OC1FE) |
293                                (STM_TIM23_CCMR1_CC1S_OUTPUT << STM_TIM23_CCMR1_CC1S));
294
295                 timer.ccer = ((0 << STM_TIM23_CCER_CC4P) |
296                               (0 << STM_TIM23_CCER_CC4E) |
297                               (0 << STM_TIM23_CCER_CC3NP) |
298                               (0 << STM_TIM23_CCER_CC3P) |
299                               (0 << STM_TIM23_CCER_CC3E) |
300                               (0 << STM_TIM23_CCER_CC2NP) |
301                               (0 << STM_TIM23_CCER_CC2P) |
302                               (1 << STM_TIM23_CCER_CC2E) |
303                               (0 << STM_TIM23_CCER_CC1P) |
304                               (0 << STM_TIM23_CCER_CC1E));
305 #endif
306 #if BEEPER_CHANNEL == 3
307                 timer.ccmr2 = ((0 << STM_TIM23_CCMR2_OC4CE) |
308                                (STM_TIM23_CCMR2_OC4M_FROZEN << STM_TIM23_CCMR2_OC4M) |
309                                (0 << STM_TIM23_CCMR2_OC4PE) |
310                                (0 << STM_TIM23_CCMR2_OC4FE) |
311                                (STM_TIM23_CCMR2_CC4S_OUTPUT << STM_TIM23_CCMR2_CC4S) |
312
313                                (0 << STM_TIM23_CCMR2_OC3CE) |
314                                (STM_TIM23_CCMR2_OC3M_TOGGLE << STM_TIM23_CCMR2_OC3M) |
315                                (0 << STM_TIM23_CCMR2_OC3PE) |
316                                (0 << STM_TIM23_CCMR2_OC3FE) |
317                                (STM_TIM23_CCMR2_CC3S_OUTPUT << STM_TIM23_CCMR2_CC3S));
318
319                 timer.ccer = ((0 << STM_TIM23_CCER_CC4P) |
320                               (0 << STM_TIM23_CCER_CC4E) |
321                               (0 << STM_TIM23_CCER_CC3NP) |
322                               (0 << STM_TIM23_CCER_CC3P) |
323                               (1 << STM_TIM23_CCER_CC3E) |
324                               (0 << STM_TIM23_CCER_CC2NP) |
325                               (0 << STM_TIM23_CCER_CC2P) |
326                               (0 << STM_TIM23_CCER_CC2E) |
327                               (0 << STM_TIM23_CCER_CC1P) |
328                               (0 << STM_TIM23_CCER_CC1E));
329 #endif
330 #if BEEPER_CHANNEL == 4
331                 timer.ccmr2 = ((0 << STM_TIM23_CCMR2_OC4CE) |
332                                (STM_TIM23_CCMR2_OC4M_TOGGLE << STM_TIM23_CCMR2_OC4M) |
333                                (0 << STM_TIM23_CCMR2_OC4PE) |
334                                (0 << STM_TIM23_CCMR2_OC4FE) |
335                                (STM_TIM23_CCMR2_CC4S_OUTPUT << STM_TIM23_CCMR2_CC4S) |
336
337                                (0 << STM_TIM23_CCMR2_OC3CE) |
338                                (STM_TIM23_CCMR2_OC3M_FROZEN << STM_TIM23_CCMR2_OC3M) |
339                                (0 << STM_TIM23_CCMR2_OC3PE) |
340                                (0 << STM_TIM23_CCMR2_OC3FE) |
341                                (STM_TIM23_CCMR2_CC3S_OUTPUT << STM_TIM23_CCMR2_CC3S));
342
343                 timer.ccer = ((0 << STM_TIM23_CCER_CC4P) |
344                               (1 << STM_TIM23_CCER_CC4E) |
345                               (0 << STM_TIM23_CCER_CC3NP) |
346                               (0 << STM_TIM23_CCER_CC3P) |
347                               (0 << STM_TIM23_CCER_CC3E) |
348                               (0 << STM_TIM23_CCER_CC2NP) |
349                               (0 << STM_TIM23_CCER_CC2P) |
350                               (0 << STM_TIM23_CCER_CC2E) |
351                               (0 << STM_TIM23_CCER_CC1P) |
352                               (0 << STM_TIM23_CCER_CC1E));
353 #endif
354                 /* 5. Enable the counter by setting the CEN bit in the TIMx_CR1 register. */
355
356                 timer.cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) |
357                              (0 << STM_TIM23_CR1_ARPE) |
358                              (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) |
359                              (0 << STM_TIM23_CR1_DIR) |
360                              (0 << STM_TIM23_CR1_OPM) |
361                              (0 << STM_TIM23_CR1_URS) |
362                              (0 << STM_TIM23_CR1_UDIS) |
363                              (1 << STM_TIM23_CR1_CEN));
364
365                 /* Update the values */
366                 timer.egr = (1 << STM_TIM23_EGR_UG);
367
368                 /* Hook the timer up to the beeper pin */
369                 stm_afr_set(BEEPER_PORT, BEEPER_PIN, STM_AFR_AF2);
370 #endif
371         }
372 }
373
374 void
375 ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant
376 {
377         ao_beep(beep);
378         ao_delay(ticks);
379         ao_beep(0);
380 }
381
382 void
383 ao_beep_init(void)
384 {
385         ao_enable_output(BEEPER_PORT, BEEPER_PIN, BEEPER, 0);
386
387         /* Leave the timer off until requested */
388         stm_rcc_enr &= ~(1 << STM_RCC_TIMER);
389 }