Use new AVR port pin names.
[bertos.git] / drv / buzzer.c
1 /*!
2  * \file
3  * <!--
4  * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
5  * Copyright 1999, 2003 Bernardo Innocenti <bernie@develer.com>
6  * This file is part of DevLib - See devlib/README for information.
7  * -->
8  *
9  * \version $Id$
10  *
11  * \author Bernardo Innocenti <bernie@develer.com>
12  *
13  * \brief Buzzer driver
14  */
15
16 /*#*
17  *#* $Log$
18  *#* Revision 1.9  2004/09/14 21:01:25  bernie
19  *#* Use new AVR port pin names.
20  *#*
21  *#* Revision 1.8  2004/08/25 14:12:08  rasky
22  *#* Aggiornato il comment block dei log RCS
23  *#*
24  *#* Revision 1.7  2004/08/24 16:53:43  bernie
25  *#* Add missing headers.
26  *#*
27  *#* Revision 1.6  2004/06/07 18:10:06  aleph
28  *#* Remove free pool of timers; use user-provided Timer structure instead
29  *#*
30  *#* Revision 1.5  2004/06/07 15:54:23  aleph
31  *#* Update to new event.h naming
32  *#*
33  *#* Revision 1.4  2004/06/06 16:09:22  bernie
34  *#* Reformat (from project_ks).
35  *#*
36  *#* Revision 1.3  2004/06/03 11:27:09  bernie
37  *#* Add dual-license information.
38  *#*
39  *#* Revision 1.2  2004/05/23 18:21:53  bernie
40  *#* Trim CVS logs and cleanup header info.
41  *#*
42  *#*/
43
44 #include "buzzer.h"
45
46 #include <drv/timer.h>
47 #include <kern/event.h>
48 #include <debug.h>
49 #include <hw.h>
50 #include <arch_config.h>
51
52
53 #if (ARCH & ARCH_EMUL)
54
55         int Emul_IsBuzzerOn(void);
56         void Emul_BuzzerOn(void);
57         void Emul_BuzzerOff(void);
58         void Emul_BuzzerInit(void);
59
60         #define IS_BUZZER_ON  (Emul_IsBuzzerOn())
61         #define BUZZER_ON     (Emul_BuzzerOn())
62         #define BUZZER_OFF    (Emul_BuzzerOff())
63         #define BUZZER_INIT   (Emul_BuzzerInit())
64
65 #elif defined(__AVR__)
66
67         #define IS_BUZZER_ON  (PORTG & BV(PG0))
68
69         /*!
70          * Buzzer manipulation macros
71          *
72          * \note Some PORTG functions are being used from
73          *       interrupt code, so we must be careful to
74          *       avoid race conditions.
75          */
76         #define BUZZER_ON \
77         do { \
78                 cpuflags_t _flags; \
79                 DISABLE_IRQSAVE(_flags); \
80                 PORTG |= BV(PG0); \
81                 ENABLE_IRQRESTORE(_flags); \
82         } while (0)
83
84         #define BUZZER_OFF \
85         do { \
86                 cpuflags_t _flags; \
87                 DISABLE_IRQSAVE(_flags); \
88                 PORTG &= ~BV(PG0); \
89                 ENABLE_IRQRESTORE(_flags); \
90         } while (0)
91
92         #define BUZZER_INIT \
93         do { \
94                 cpuflags_t _flags; \
95                 DISABLE_IRQSAVE(_flags); \
96                 PORTG &= ~BV(PG0); \
97                 DDRG |= BV(PG0); \
98                 ENABLE_IRQRESTORE(_flags); \
99         } while (0)
100
101 #elif defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__) /* 80C196 */
102
103         #define IS_BUZZER_ON  (cpld->Buzzer & 1)
104         #define BUZZER_ON     (cpld->Buzzer = 1)
105         #define BUZZER_OFF    (cpld->Buzzer = 0)
106         #define BUZZER_INIT   (cpld->Buzzer = 0)
107
108 #endif /* ARCH, __AVR__, __IAR_SYSTEM_ICC */
109
110
111 /* Local vars */
112 static Timer buz_timer;
113 static bool buz_timer_running;
114 static time_t buz_repeat_interval;
115 static time_t buz_repeat_duration;
116
117
118 /*!
119  * Turn off buzzer, called by software timer
120  */
121 static void buz_softint(void)
122 {
123         if (IS_BUZZER_ON)
124         {
125                 BUZZER_OFF;
126                 if (buz_repeat_interval)
127                 {
128                         /* Wait for interval time */
129                         buz_timer.delay = buz_repeat_interval;
130                         timer_add(&buz_timer);
131                 }
132                 else
133                         buz_timer_running = false;
134         }
135         else if (buz_repeat_interval)
136         {
137                 /* Wait for beep time */
138                 BUZZER_ON;
139                 buz_timer.delay = buz_repeat_duration;
140                 timer_add(&buz_timer);
141         }
142         else
143                 buz_timer_running = false;
144 }
145
146
147 /*!
148  * Beep for the specified ms time
149  */
150 void buz_beep(time_t time)
151 {
152         cpuflags_t flags;
153
154         /* Remove the software interrupt if it was already queued */
155         DISABLE_IRQSAVE(flags);
156         if (buz_timer_running)
157                 timer_abort(&buz_timer);
158
159         /* Turn on buzzer */
160         BUZZER_ON;
161
162         /* Add software interrupt to turn the buzzer off later */
163         buz_timer_running = true;
164         buz_timer.delay = time;
165         timer_add(&buz_timer);
166
167         ENABLE_IRQRESTORE(flags);
168 }
169
170
171 /*!
172  * Start buzzer repetition
173  */
174 void buz_repeat_start(time_t duration, time_t interval)
175 {
176         buz_repeat_interval = interval;
177         buz_repeat_duration = duration;
178         buz_beep(duration);
179 }
180
181
182 /*!
183  * Stop buzzer repetition
184  */
185 void buz_repeat_stop(void)
186 {
187         cpuflags_t flags;
188         DISABLE_IRQSAVE(flags);
189
190         /* Remove the software interrupt if it was already queued */
191         if (buz_timer_running)
192         {
193                 timer_abort(&buz_timer);
194                 buz_timer_running = false;
195         }
196
197         buz_repeat_interval = 0;
198         BUZZER_OFF;
199
200         ENABLE_IRQRESTORE(flags);
201 }
202
203
204 /*!
205  * Initialize buzzer
206  */
207 void buz_init(void)
208 {
209         BUZZER_INIT;
210
211         /* Inizializza software interrupt */
212         event_initSoftInt(&buz_timer.expire, (Hook)buz_softint, 0);
213 }