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