CircleOS  1
buzzer.c
Go to the documentation of this file.
1 /****************** COPYRIGHT (C) 2007-2013 KEOLABS S.A.S. ********************/
14 /******************************************************************************/
15 
16 
17 /* Includes ------------------------------------------------------------------*/
18 #include "circle.h"
19 
21 
22 /* Private typedef -----------------------------------------------------------*/
23 
25 enum eOctave
26 {
27  OCT_440 = 0,
28  OCT_880 = 1,
29  OCT_1760 = 2,
30  OCT_3520 = 3,
31  OCT_7040 = 4
32 } octave;
33 
35 enum eNotes
36 {
37  NOTE_PAUSE = 0,
38  NOTE_LA = 1,
39  NOTE_LA_H = 8 + 1,
40  NOTE_SI = 2,
41  NOTE_DO = 3,
42  NOTE_DO_H = 8 + 3,
43  NOTE_RE = 4,
44  NOTE_RE_H = 8 + 4,
45  NOTE_MI = 5,
46  NOTE_FA = 6,
47  NOTE_FA_H = 8 + 6,
48  NOTE_SOL = 7,
49  NOTE_SOL_H = 8 + 7
50 } note;
51 
52 /* Private define ------------------------------------------------------------*/
53 #define BUZZER_SHORTBEEP_DURATION 100
54 #define BUZZER_LONGBEEP_DURATION 1000
55 #define RTTTL_SEP ':'
56 
57 /* Private macro -------------------------------------------------------------*/
58 
59 /* Private variables ---------------------------------------------------------*/
60 enum BUZZER_mode Buzzer_Mode = BUZZER_UNDEF;
61 counter_t Buzzer_Counter = 0;
62 
63 /* For the melody.*/
64 const u8* CurrentMelody = 0;
65 const u8* CurrentMelodySTART = 0;
66 u8 DefaultOctave = OCT_880;
67 u8 DefaultDuration = 4;
68 u16 DefaultBeats = 63;
69 
70 CONST_DATA u16 Note_Freq[16] =
71 {
72  0, /*pause*/
73  440, /*A=LA*/
74  494, /*B=SI*/
75  524, /*C=DO*/
76  588, /*D=RE*/
77  660, /*E=MI*/
78  698, /*F=FA*/
79  784, /*G=SOL*/
80  0, /* "8+n" for "NOTE#"*/
81  466, /*A#=LA#*/
82  0,
83  544, /*C#=DO#*/
84  622, /*D#=RE#*/
85  0,
86  740, /*F#=FA#*/
87  830 /*G#=SOL#*/
88 };
89 
90 
91 /* Private function prototypes -----------------------------------------------*/
92 
93 /* Private functions ---------------------------------------------------------*/
94 
95 /* External variables ---------------------------------------------------------*/
96 
97 
98 /*******************************************************************************
99 *
100 * BUZZER_PlayNote
101 *
102 *******************************************************************************/
108 /******************************************************************************/
109 void BUZZER_PlayNote( void )
110 {
111  u8 duration = DefaultDuration;
112  u8 c;
113 
114  /* Discard blank characters*/
115  while ( *CurrentMelody == ' ' )
116  {
117  CurrentMelody++;
118  }
119 
120  /* Check whether a duration is present.*/
121  if ( ( *CurrentMelody > '0' ) && ( *CurrentMelody < '9' ) )
122  {
123  duration = *CurrentMelody++ - '0';
124 
125  if ( ( *CurrentMelody > '0' ) && ( *CurrentMelody < '9' ) )
126  {
127  duration *= 10;
128  duration += ( *CurrentMelody++ - '0' );
129  }
130  }
131 
132 #if __RCSTM8__
133  // Compute the number of milliseconds of the given note
134 // Buzzer_Counter = 32L * 60 * 1000 / duration / DefaultBeats; // This is the THEORETICAL value
135  Buzzer_Counter = 35000 / DefaultBeats * 10 / duration; // This is the value that matches CircleOS3
136 #else
137  // TODO verify the code and rewrite for efficiency
138  Buzzer_Counter = ( ( 32 / duration ) * 256L * 32L ) / DefaultBeats;
139  Buzzer_Counter *= ( SYSTEM_CLOCK / 12000L );
140  Buzzer_Counter /= 1000L; /*FL081103 divide in two stages to keep precision*/
141 #endif
142 
143  /* Read the note*/
144  c = *CurrentMelody++;
145 
146  if ( ( c >= 'a' ) && ( c <= 'z' ) )
147  {
148  c += ( 'A' - 'a' );
149  }
150 
151  if ( c == 'P' )
152  {
153  note = NOTE_PAUSE;
154  }
155  else if ( ( c >= 'A' ) && ( c <= 'G' ) )
156  {
157  note = ( c - 'A' ) + NOTE_LA;
158 
159  if ( *CurrentMelody == '#' )
160  {
161  note |= 0x8;
162  CurrentMelody++;
163  }
164  }
165 
166  octave = DefaultOctave;
167  c = *CurrentMelody;
168 
169  if ( ( c >= '5' ) && ( c <= '8' ) )
170  {
171  octave = OCT_440 + ( c - '5' );
172  CurrentMelody++;
173  }
174 
175  BUZZER_SetFrequency( ( Note_Freq[note] * ( 1 << octave ) ) );
176 
177  /* Handle special duration */
178  if ( *CurrentMelody == '.' )
179  {
180  /* Dotted note: Add half duration */
181  Buzzer_Counter += ( Buzzer_Counter / 2 );
182  CurrentMelody++;
183  }
184 
185  /* Discard delimiter */
186  while ( ( c = *CurrentMelody++ ) != 0 )
187  {
188  if ( c == ',' )
189  break;
190  }
191 
192  /* Check end of melody */
193  if ( c == 0 )
194  {
195  CurrentMelody = 0;
197  }
198 }
199 
200 /* Public functions for CircleOS ---------------------------------------------*/
201 
202 
203 /*******************************************************************************
204 *
205 * BUZZER_Handler
206 *
207 *******************************************************************************/
215 /******************************************************************************/
216 void BUZZER_Handler( void )
217 {
218  switch ( Buzzer_Mode )
219  {
220  case BUZZER_PLAYMUSIC :
221  if ( Buzzer_Counter <= 0 )
222  {
223  /* Play next note*/
224  BUZZER_PlayNote();
225  }
226  else
227  {
228  /* Continue the current note*/
229  Buzzer_Counter--;
230  }
231  break;
232 
233  case BUZZER_SHORTBEEP :
234  if ( Buzzer_Counter++ >= WEIGHTED_TIME( BUZZER_SHORTBEEP_DURATION ) )
235  {
237  }
238  break;
239 
240  case BUZZER_LONGBEEP :
241  if ( Buzzer_Counter++ >= WEIGHTED_TIME( BUZZER_LONGBEEP_DURATION ) )
242  {
244  }
245  break;
246 
247  default:
248  break;
249  }
250 }
251 
253 
254 /* Public functions ----------------------------------------------------------*/
255 
256 /*******************************************************************************
257 *
258 * BUZZER_GetMode
259 *
260 *******************************************************************************/
268 /******************************************************************************/
270 {
271  return Buzzer_Mode;
272 }
273 
274 
275 /*******************************************************************************
276 *
277 * BUZZER_PlayMusic
278 *
279 *******************************************************************************/
339 /******************************************************************************/
340 void BUZZER_PlayMusic( const u8* melody )
341 {
342  u8 c;
343  u8 default_id = 0;
344  u16 default_val = 0;
345 
346  DefaultOctave = OCT_880; /* Default for the default Octave.*/
347  DefaultDuration = 4; /* Default for the default Duration.*/
348  DefaultBeats = 63;
349  CurrentMelody = melody;
350  CurrentMelodySTART = melody;
351 
352  while ( *CurrentMelody != RTTTL_SEP )
353  {
354  if ( *CurrentMelody == 0 )
355  {
356  return;
357  }
358 
359  /* Discard the melody name.*/
360  CurrentMelody++;
361  }
362 
363  /* Now read the defaults if any.*/
364  for ( ++CurrentMelody; *CurrentMelody != RTTTL_SEP; CurrentMelody++ )
365  {
366  if ( *CurrentMelody == 0 )
367  {
368  return;
369  }
370 
371  /* Discard any blank.*/
372  while ( *CurrentMelody == ' ' )
373  {
374  CurrentMelody++;
375  }
376 
377  c = *CurrentMelody;
378 
379  if ( c == RTTTL_SEP )
380  {
381  break;
382  }
383 
384  if ( ( c >= 'a' ) && ( c <= 'z' ) )
385  {
386  c += ( 'A' - 'a' );
387  }
388 
389  if ( ( c >= 'A' ) && ( c <= 'Z' ) )
390  {
391  default_id = c;
392  continue;
393  }
394 
395  if ( ( c >= '0' ) && ( c <= '9' ) )
396  {
397  default_val *= 10;
398  default_val += ( c - '0' );
399  c = * ( CurrentMelody + 1 );
400 
401  if ( ( c >= '0' ) && ( c <= '9' ) )
402  {
403  continue;
404  }
405 
406  if ( default_id == 'D' )
407  {
408  DefaultDuration = default_val;
409  }
410  else if ( default_id == 'O' )
411  {
412  DefaultOctave = default_val - 5;
413 
414  if ( DefaultOctave > OCT_7040 )
415  DefaultOctave = OCT_440;
416  }
417  else if ( default_id == 'B' )
418  {
419  DefaultBeats = default_val;
420 
421  /* Check minimum BPM, so that the counter can be a 16-bit value */
422  if ( ( DefaultBeats < 16 ) || ( DefaultBeats > 500 ) )
423  DefaultBeats = 63;
424  }
425 
426  default_val = 0;
427  default_id = 0;
428  }
429  }
430 
432 }