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