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