• Main Page
  • Related Pages
  • Data Structures
  • Files
  • File List
  • Globals

buzzer.c

Go to the documentation of this file.
00001 /****************** COPYRIGHT (C) 2007-2010 RAISONANCE S.A.S. *****************/
00014 /******************************************************************************/
00015 
00016 
00017 /* Includes ------------------------------------------------------------------*/
00018 #include "circle.h"
00019 
00021 
00022 /* Private typedef -----------------------------------------------------------*/
00023 
00025 enum eOctave
00026 {
00027     OCT_440  = 0,  
00028     OCT_880  = 1,  
00029     OCT_1760 = 2,  
00030     OCT_3520 = 3,  
00031     OCT_7040 = 4   
00032 } octave;
00033 
00035 enum eNotes
00036 {
00037     NOTE_PAUSE = 0,    
00038     NOTE_LA    = 1,    
00039     NOTE_LA_H  = 8 + 1, 
00040     NOTE_SI    = 2,    
00041     NOTE_DO    = 3,    
00042     NOTE_DO_H  = 8 + 3, 
00043     NOTE_RE    = 4,    
00044     NOTE_RE_H  = 8 + 4, 
00045     NOTE_MI    = 5,    
00046     NOTE_FA    = 6,    
00047     NOTE_FA_H  = 8 + 6, 
00048     NOTE_SOL   = 7,    
00049     NOTE_SOL_H = 8 + 7 
00050 } note;
00051 
00052 /* Private define ------------------------------------------------------------*/
00053 #define BUZZER_SHORTBEEP_DURATION   100
00054 #define BUZZER_LONGBEEP_DURATION    1000
00055 #define RTTTL_SEP                   ':'
00056 
00057 /* Private macro -------------------------------------------------------------*/
00058 
00059 /* Private variables ---------------------------------------------------------*/
00060 enum BUZZER_mode                 Buzzer_Mode          = BUZZER_UNDEF;
00061 counter_t                        Buzzer_Counter       = 0;
00062 
00063 /* For the melody.*/
00064 const u8*                        CurrentMelody        = 0;
00065 const u8*                        CurrentMelodySTART   = 0;
00066 u8                               DefaultOctave        = OCT_880;
00067 u8                               DefaultDuration      = 4;
00068 u16                              DefaultBeats         = 63;
00069 
00070 CONST_DATA u16 Note_Freq[16] =
00071 {
00072     0,    /*pause*/
00073     440,  /*A=LA*/
00074     494,  /*B=SI*/
00075     524,  /*C=DO*/
00076     588,  /*D=RE*/
00077     660,  /*E=MI*/
00078     698,  /*F=FA*/
00079     784,  /*G=SOL*/
00080     0,    /* "8+n" for "NOTE#"*/
00081     466,  /*A#=LA#*/
00082     0,
00083     544,  /*C#=DO#*/
00084     622,  /*D#=RE#*/
00085     0,
00086     740,  /*F#=FA#*/
00087     830   /*G#=SOL#*/
00088 };
00089 
00090 
00091 /* Private function prototypes -----------------------------------------------*/
00092 
00093 /* Private functions ---------------------------------------------------------*/
00094 
00095 /* External variables ---------------------------------------------------------*/
00096 
00097 
00098 /*******************************************************************************
00099 *
00100 *                                BUZZER_PlayNote
00101 *
00102 *******************************************************************************/
00108 /******************************************************************************/
00109 void BUZZER_PlayNote( void )
00110 {
00111     u8 duration = DefaultDuration;
00112     u8 c;
00113 
00114     /* Discard blank characters*/
00115     while ( *CurrentMelody == ' ' )
00116     {
00117         CurrentMelody++;
00118     }
00119 
00120     /* Check whether a duration is present.*/
00121     if ( ( *CurrentMelody > '0' ) && ( *CurrentMelody < '9' ) )
00122     {
00123         duration = *CurrentMelody++ - '0';
00124 
00125         if ( ( *CurrentMelody > '0' ) && ( *CurrentMelody < '9' ) )
00126         {
00127             duration *= 10;
00128             duration += ( *CurrentMelody++ - '0' );
00129         }
00130     }
00131 
00132 #if __RCSTM8__
00133     // Compute the number of milliseconds of the given note
00134 //  Buzzer_Counter = 32L * 60 * 1000 / duration / DefaultBeats; // This is the THEORETICAL value
00135     Buzzer_Counter = 35000 / DefaultBeats * 10 / duration;      // This is the value that matches CircleOS3
00136 #else
00137     // TODO verify the code and rewrite for efficiency
00138     Buzzer_Counter = ( ( 32 / duration ) * 256L * 32L ) / DefaultBeats;
00139     Buzzer_Counter *= ( SYSTEM_CLOCK / 12000L );
00140     Buzzer_Counter /= 1000L;  /*FL081103 divide in two stages to keep precision*/
00141 #endif
00142 
00143     /* Read the note*/
00144     c = *CurrentMelody++;
00145 
00146     if ( ( c >= 'a' ) && ( c <= 'z' ) )
00147     {
00148         c += ( 'A' - 'a' );
00149     }
00150 
00151     if ( c == 'P' )
00152     {
00153         note = NOTE_PAUSE;
00154     }
00155     else if ( ( c >= 'A' ) && ( c <= 'G' ) )
00156     {
00157         note = ( c - 'A' ) + NOTE_LA;
00158 
00159         if ( *CurrentMelody == '#' )
00160         {
00161             note |= 0x8;
00162             CurrentMelody++;
00163         }
00164     }
00165 
00166     octave = DefaultOctave;
00167     c = *CurrentMelody;
00168 
00169     if ( ( c >= '5' ) && ( c <= '8' ) )
00170     {
00171         octave = OCT_440 + ( c - '5' );
00172         CurrentMelody++;
00173     }
00174 
00175     BUZZER_SetFrequency( ( Note_Freq[note] * ( 1 << octave ) ) );
00176 
00177     /* Handle special duration */
00178     if ( *CurrentMelody == '.' )
00179     {
00180         /* Dotted note: Add half duration */
00181         Buzzer_Counter += ( Buzzer_Counter / 2 );
00182         CurrentMelody++;
00183     }
00184 
00185     /* Discard delimiter */
00186     while ( ( c = *CurrentMelody++ ) != 0 )
00187     {
00188         if ( c == ',' )
00189             break;
00190     }
00191 
00192     /* Check end of melody */
00193     if ( c == 0 )
00194     {
00195         CurrentMelody  = 0;
00196         BUZZER_SetMode( BUZZER_OFF );
00197     }
00198 }
00199 
00200 /* Public functions for CircleOS ---------------------------------------------*/
00201 
00202 
00203 /*******************************************************************************
00204 *
00205 *                                BUZZER_Handler
00206 *
00207 *******************************************************************************/
00215 /******************************************************************************/
00216 void BUZZER_Handler( void )
00217 {
00218     switch ( Buzzer_Mode )
00219     {
00220     case BUZZER_PLAYMUSIC :
00221         if ( Buzzer_Counter <= 0 )
00222         {
00223             /* Play next note*/
00224             BUZZER_PlayNote();
00225         }
00226         else
00227         {
00228             /* Continue the current note*/
00229             Buzzer_Counter--;
00230         }
00231         break;
00232 
00233     case BUZZER_SHORTBEEP :
00234         if ( Buzzer_Counter++ >= WEIGHTED_TIME( BUZZER_SHORTBEEP_DURATION ) )
00235         {
00236             BUZZER_SetMode( BUZZER_OFF );
00237         }
00238         break;
00239 
00240     case BUZZER_LONGBEEP :
00241         if ( Buzzer_Counter++ >= WEIGHTED_TIME( BUZZER_LONGBEEP_DURATION ) )
00242         {
00243             BUZZER_SetMode( BUZZER_OFF );
00244         }
00245         break;
00246     }
00247 }
00248 
00250 
00251 /* Public functions ----------------------------------------------------------*/
00252 
00253 /*******************************************************************************
00254 *
00255 *                                BUZZER_GetMode
00256 *
00257 *******************************************************************************/
00265 /******************************************************************************/
00266 enum BUZZER_mode BUZZER_GetMode( void )
00267 {
00268     return Buzzer_Mode;
00269 }
00270 
00271 
00272 /*******************************************************************************
00273 *
00274 *                                BUZZER_PlayMusic
00275 *
00276 *******************************************************************************/
00336 /******************************************************************************/
00337 void BUZZER_PlayMusic( const u8* melody )
00338 {
00339     u8    c;
00340     u8    default_id  = 0;
00341     u16   default_val = 0;
00342 
00343     DefaultOctave      = OCT_880;  /* Default for the default Octave.*/
00344     DefaultDuration    = 4;        /* Default for the default Duration.*/
00345     DefaultBeats       = 63;
00346     CurrentMelody      = melody;
00347     CurrentMelodySTART = melody;
00348 
00349     while ( *CurrentMelody != RTTTL_SEP )
00350     {
00351         if ( *CurrentMelody == 0 )
00352         {
00353             return;
00354         }
00355 
00356         /* Discard the melody name.*/
00357         CurrentMelody++;
00358     }
00359 
00360     /* Now read the defaults if any.*/
00361     for ( ++CurrentMelody; *CurrentMelody != RTTTL_SEP; CurrentMelody++ )
00362     {
00363         if ( *CurrentMelody == 0 )
00364         {
00365             return;
00366         }
00367 
00368         /* Discard any blank.*/
00369         while ( *CurrentMelody == ' ' )
00370         {
00371             CurrentMelody++;
00372         }
00373 
00374         c = *CurrentMelody;
00375 
00376         if ( c == RTTTL_SEP )
00377         {
00378             break;
00379         }
00380 
00381         if ( ( c >= 'a' ) && ( c <= 'z' ) )
00382         {
00383             c += ( 'A' - 'a' );
00384         }
00385 
00386         if ( ( c >= 'A' ) && ( c <= 'Z' ) )
00387         {
00388             default_id = c;
00389             continue;
00390         }
00391 
00392         if ( ( c >= '0' ) && ( c <= '9' ) )
00393         {
00394             default_val *= 10;
00395             default_val += ( c - '0' );
00396             c = * ( CurrentMelody + 1 );
00397 
00398             if ( ( c >= '0' ) && ( c <= '9' ) )
00399             {
00400                 continue;
00401             }
00402 
00403             if ( default_id == 'D' )
00404             {
00405                 DefaultDuration = default_val;
00406             }
00407             else if ( default_id == 'O' )
00408             {
00409                 DefaultOctave = default_val - 5;
00410 
00411                 if ( DefaultOctave > OCT_7040 )
00412                     DefaultOctave = OCT_440;
00413             }
00414             else if ( default_id == 'B' )
00415             {
00416                 DefaultBeats = default_val;
00417 
00418                 /* Check minimum BPM, so that the counter can be a 16-bit value */
00419                 if ( ( DefaultBeats < 16 ) || ( DefaultBeats > 500 ) )
00420                     DefaultBeats = 63;
00421             }
00422 
00423             default_val = 0;
00424             default_id  = 0;
00425         }
00426     }
00427 
00428     BUZZER_SetMode( BUZZER_PLAYMUSIC );
00429 }