Import drv/ modules.
[bertos.git] / drv / buzzer.c
1 /*!
2  * \file
3  * <!--
4  * Copyright (C) 1999,2003 Bernardo Innocenti <bernie@develer.com>
5  * Copyright (C) 2003 Develer S.r.l. (http://www.develer.com/)
6  * All Rights Reserved.
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.1  2004/05/23 18:10:11  bernie
19  * Import drv/ modules.
20  *
21  * Revision 1.5  2004/04/04 17:44:51  aleph
22  * Move event.h from mware to kern dir
23  *
24  * Revision 1.4  2004/03/24 15:03:45  bernie
25  * Use explicit include paths; clean Doxygen comments
26  *
27  * Revision 1.3  2004/03/03 18:27:44  bernie
28  * Fixed race conds with IRQ when fiddling with I/O ports
29  *
30  * Revision 1.2  2003/12/18 18:15:24  aleph
31  * Use new IRQ disable/enable reentrant macros
32  *
33  * Revision 1.1  2003/12/13 23:53:37  aleph
34  * Add buzzer driver
35  *
36  */
37
38 #include "hw.h"
39 #include "kdebug.h"
40 #include "timer.h"
41 #include "buzzer.h"
42 #include <kern/event.h>
43
44
45 #if (ARCH & ARCH_EMUL)
46
47         int Emul_IsBuzzerOn(void);
48         void Emul_BuzzerOn(void);
49         void Emul_BuzzerOff(void);
50         void Emul_BuzzerInit(void);
51
52 #       define IS_BUZZER_ON  (Emul_IsBuzzerOn())
53 #       define BUZZER_ON     (Emul_BuzzerOn())
54 #       define BUZZER_OFF    (Emul_BuzzerOff())
55 #       define BUZZER_INIT   (Emul_BuzzerInit())
56
57 #elif defined(__AVR__)
58
59 #       define IS_BUZZER_ON  (PORTG & BV(PORTG0))
60
61         /**
62          * Buzzer manipulation macros
63          *
64          * \note Some PORTG functions are being used from
65          *       interrupt code, so we must be careful to
66          *       avoid race conditions.
67          */
68 #       define BUZZER_ON \
69         do { \
70                 cpuflags_t _flags; \
71                 DISABLE_IRQSAVE(_flags); \
72                 PORTG |= BV(PORTG0); \
73                 ENABLE_IRQRESTORE(_flags); \
74         } while (0)
75
76 #       define BUZZER_OFF \
77         do { \
78                 cpuflags_t _flags; \
79                 DISABLE_IRQSAVE(_flags); \
80                 PORTG &= ~BV(PORTG0); \
81                 ENABLE_IRQRESTORE(_flags); \
82         } while (0)
83
84 #       define BUZZER_INIT \
85         do { \
86                 cpuflags_t _flags; \
87                 DISABLE_IRQSAVE(_flags); \
88                 PORTG &= ~BV(PORTG0); \
89                 DDRG |= BV(PORTG0); \
90                 ENABLE_IRQRESTORE(_flags); \
91         } while (0)
92
93 #elif defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__) /* 80C196 */
94
95 #       define IS_BUZZER_ON  (cpld->Buzzer & 1)
96 #       define BUZZER_ON     (cpld->Buzzer = 1)
97 #       define BUZZER_OFF    (cpld->Buzzer = 0)
98 #       define BUZZER_INIT   (cpld->Buzzer = 0)
99
100 #endif /* ARCH, __AVR__, __IAR_SYSTEM_ICC */
101
102
103 /* Local vars */
104 static Timer *buz_timer;
105 static bool buz_timer_running;
106 static time_t buz_repeat_interval;
107 static time_t buz_repeat_duration;
108
109
110 /*!
111  * Turn off buzzer, called by software timer
112  */
113 static void buz_softint(void)
114 {
115         if (IS_BUZZER_ON)
116         {
117                 BUZZER_OFF;
118                 if (buz_repeat_interval)
119                 {
120                         /* Wait for interval time */
121                         buz_timer->delay = buz_repeat_interval;
122                         timer_add(buz_timer);
123                 }
124                 else
125                         buz_timer_running = false;
126         }
127         else if (buz_repeat_interval)
128         {
129                 /* Wait for beep time */
130                 BUZZER_ON;
131                 buz_timer->delay = buz_repeat_duration;
132                 timer_add(buz_timer);
133         }
134         else
135                 buz_timer_running = false;
136 }
137
138
139 /*!
140  * Beep for the specified ms time
141  */
142 void buz_beep(time_t time)
143 {
144         cpuflags_t flags;
145
146         /* Remove the software interrupt if it was already queued */
147         DISABLE_IRQSAVE(flags);
148         if (buz_timer_running)
149                 timer_abort(buz_timer);
150
151         /* Turn on buzzer */
152         BUZZER_ON;
153
154         /* Add software interrupt to turn the buzzer off later */
155         buz_timer_running = true;
156         buz_timer->delay = time;
157         timer_add(buz_timer);
158
159         ENABLE_IRQRESTORE(flags);
160 }
161
162
163 /*!
164  * Start buzzer repetition
165  */
166 void buz_repeat_start(time_t duration, time_t interval)
167 {
168         buz_repeat_interval = interval;
169         buz_repeat_duration = duration;
170         buz_beep(duration);
171 }
172
173
174 /*!
175  * Stop buzzer repetition
176  */
177 void buz_repeat_stop(void)
178 {
179         cpuflags_t flags;
180         DISABLE_IRQSAVE(flags);
181
182         /* Remove the software interrupt if it was already queued */
183         if (buz_timer_running)
184         {
185                 timer_abort(buz_timer);
186                 buz_timer_running = false;
187         }
188
189         buz_repeat_interval = 0;
190         BUZZER_OFF;
191
192         ENABLE_IRQRESTORE(flags);
193 }
194
195
196 /*!
197  * Initialize buzzer
198  */
199 void buz_init(void)
200 {
201         BUZZER_INIT;
202
203         /* Inizializza software interrupt */
204         buz_timer = timer_new();
205         ASSERT(buz_timer != NULL);
206         INITEVENT_INT(&buz_timer->expire, (Hook)buz_softint, 0);
207 }