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