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