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