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