URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_STM32F103_Primer_GCC/] [ST_Code/] [buzzer.c] - Rev 603
Go to most recent revision | Compare with Previous | Blame | View Log
/********************* (C) COPYRIGHT 2007 RAISONANCE S.A.S. *******************/ /** * * @file buzzer.c * @brief Buzzer dedicated functions with RTTTL format support. * @author IB * @date 07/2007 * **/ /******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "circle.h" /// @cond Internal /* Private typedef -----------------------------------------------------------*/ /*! Octaves */ enum eOctave { OCT_440 = 0, /*!< o = 5 */ OCT_880 = 1, /*!< o = 6 */ OCT_1760 = 2, /*!< o = 7 */ OCT_3520 = 3, /*!< o = 8 */ OCT_7040 = 4 /*!< o = 9 */ } octave; /*! Notes */ enum eNotes { NOTE_PAUSE = 0, /*!< P */ NOTE_LA = 1, /*!< A */ NOTE_LA_H = 8+1, /*!< A# */ NOTE_SI = 2, /*!< B */ NOTE_DO = 3, /*!< C */ NOTE_DO_H = 8+3, /*!< C# */ NOTE_RE = 4, /*!< D */ NOTE_RE_H = 8+4, /*!< D# */ NOTE_MI = 5, /*!< E */ NOTE_FA = 6, /*!< F */ NOTE_FA_H = 8+6, /*!< F# */ NOTE_SOL = 7, /*!< G */ NOTE_SOL_H = 8+7 /*!< G# */ } note; /* Private define ------------------------------------------------------------*/ #define BUZZER_SHORTBEEP_DURATION 100 #define BUZZER_LONGBEEP_DURATION 1000 #define RTTTL_SEP ':' /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ int buzz_counter = 0; int buzz_in_progress = 0; static TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; static TIM_OCInitTypeDef TIM_OCInitStructure; u16 CCR_Val = 0x2EE0; enum BUZZER_mode Buzzer_Mode = BUZZER_UNDEF; u32 Buzzer_Counter = 0; // For the melody. const u8* CurrentMelody = 0; const u8* CurrentMelodySTART = 0; u8 DefaultOctave = OCT_880; u8 DefaultDuration = 4; u16 DefaultBeats = 63; u16 Note_Freq [16] = { 0, //pause 440, //A=LA 494, //B=SI 524, //C=DO 588, //D=RE 660, //E=MI 698, //F=FA 784, //G=SOL 0, // "8+n" for "NOTE#" 466, //A#=LA# 0, 544, //C#=DO# 622, //D#=RE# 0, 740, //F#=FA# 830 //G#=SOL# }; /* Private function prototypes -----------------------------------------------*/ static void PlayMusic( void ); static void BUZZER_SetFrequency( u16 freq ); /* Private functions ---------------------------------------------------------*/ /******************************************************************************* * * PlayMusic * *******************************************************************************/ /** * * Play the next note of the current melody. * **/ /******************************************************************************/ static void PlayMusic( void ) { u8 duration = DefaultDuration; u8 c; // Discard blank characters while ( *CurrentMelody == ' ') { CurrentMelody++; } // Check whether a duration is present. if ( (*CurrentMelody > '0') && (*CurrentMelody < '9') ) { duration = *CurrentMelody++ - '0'; if ( (*CurrentMelody > '0') && (*CurrentMelody < '9') ) { duration *= 10; duration += (*CurrentMelody++ - '0'); } } Buzzer_Counter = ( (32/duration) * 256L * 32L) / DefaultBeats; Buzzer_Counter*= (RCC_ClockFreq.SYSCLK_Frequency / 12000000L); //Adapt to HCLK1 //read the note c = *CurrentMelody++; if ( (c >= 'a') && (c <= 'z') ) { c+=('A'-'a'); } if ( c == 'P' ) { note = NOTE_PAUSE; } else if ( (c >= 'A') && (c <= 'G') ) { note = (c - 'A') + NOTE_LA; if ( *CurrentMelody == '#' ) { note|=0x8; CurrentMelody++; } } octave = DefaultOctave; c = *CurrentMelody; if ( (c>= '5') && (c<= '8') ) { octave = OCT_440 + (c-'5'); CurrentMelody++; } BUZZER_SetFrequency ( (Note_Freq [ note ] * (1<<octave))); //discard delimiter and ignore special duration while ( (c = *CurrentMelody++) != 0 ) { if ( c==',') break; } if ( *(CurrentMelody-1)==0 ) { CurrentMelody = 0; } if ( c == 0 ) { BUZZER_SetMode ( BUZZER_OFF ); } } /*********************************************************************************** * * BUZZER_SetFrequency * ************************************************************************************/ /** * * Set the buzzer frequency * * @param[in] freq New frequency. * **/ /********************************************************************************/ void BUZZER_SetFrequency ( u16 freq ) { /* Calculate the frequency (depend on the PCLK1 clock value) */ CCR_Val = (RCC_ClockFreq.PCLK1_Frequency / freq); TIM_TimeBaseStructure.TIM_Period = CCR_Val * 2; TIM_TimeBaseStructure.TIM_Prescaler = 0x0; TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit( TIM3, &TIM_TimeBaseStructure ); /* Output Compare Toggle Mode configuration: Channel3 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR_Val; TIM_OC3Init( TIM3, &TIM_OCInitStructure ); TIM_OC3PreloadConfig( TIM3, TIM_OCPreload_Enable ); } /* Public functions for CircleOS ---------------------------------------------*/ /******************************************************************************* * * BUZZER_Init * *******************************************************************************/ /** * * Buzzer Initialization * * @attention This function must <b>NOT</b> be called by the user. * **/ /******************************************************************************/ void BUZZER_Init( void ) { GPIO_InitTypeDef GPIO_InitStructure; /* Enable GPIOB clock */ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); /* GPIOB Configuration: TIM3 3in Output */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( GPIOB, &GPIO_InitStructure ); /* TIM3 Configuration ------------------------------------------------------*/ /* TIM3CLK = 18 MHz, Prescaler = 0x0, TIM3 counter clock = 18 MHz */ /* CC update rate = TIM3 counter clock / (2* CCR_Val) ~= 750 Hz */ /* Enable TIM3 clock */ RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE ); TIM_DeInit( TIM3 ); TIM_TimeBaseStructInit( &TIM_TimeBaseStructure ); TIM_OCStructInit( &TIM_OCInitStructure ); /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_Prescaler = 0x0; TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit( TIM3, &TIM_TimeBaseStructure ); /* Output Compare Toggle Mode configuration: Channel3 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR_Val; TIM_OC3Init( TIM3, &TIM_OCInitStructure ); TIM_OC3PreloadConfig( TIM3, TIM_OCPreload_Disable ); BUZZER_SetFrequency( 440 ); /* Enable TIM3 IT */ TIM_ITConfig( TIM3, TIM_IT_CC3, ENABLE ); Buzzer_Mode = BUZZER_OFF; } /******************************************************************************* * * BUZZER_Handler * *******************************************************************************/ /** * * Called by the CircleOS scheduler to manage Buzzer tasks. * * @attention This function must <b>NOT</b> be called by the user. * **/ /******************************************************************************/ void BUZZER_Handler( void ) { int fSetOFF = 0; if ( Buzzer_Mode == BUZZER_PLAYMUSIC ) { if ( Buzzer_Counter == 0 ) { PlayMusic(); } else { Buzzer_Counter--; } return; } else if ( Buzzer_Mode == BUZZER_SHORTBEEP ) { if ( Buzzer_Counter++ == (BUZZER_SHORTBEEP_DURATION) ) { Buzzer_Mode = BUZZER_OFF; return; } if ( Buzzer_Counter == (BUZZER_SHORTBEEP_DURATION/2) ) { fSetOFF = 1; } } else if ( Buzzer_Mode == BUZZER_LONGBEEP ) { if ( Buzzer_Counter++ == (BUZZER_LONGBEEP_DURATION) ) { Buzzer_Mode = BUZZER_OFF; return; } if ( Buzzer_Counter > (BUZZER_LONGBEEP_DURATION/2) ) { fSetOFF = 1; } } if ( fSetOFF == 1 ) { TIM_Cmd(TIM3, DISABLE); } } /// @endcond /* Public functions ----------------------------------------------------------*/ /******************************************************************************* * * BUZZER_GetMode * *******************************************************************************/ /** * * Get the current buzzer mode. * * @return Current buzzer mode. * **/ /******************************************************************************/ enum BUZZER_mode BUZZER_GetMode( void ) { return Buzzer_Mode; } /******************************************************************************* * * BUZZER_SetMode * *******************************************************************************/ /** * * Set new buzzer mode * * @param[in] mode New buzzer mode. * **/ /******************************************************************************/ void BUZZER_SetMode( enum BUZZER_mode mode ) { Buzzer_Mode = mode; Buzzer_Counter = 0; switch ( mode ) { case BUZZER_PLAYMUSIC : PlayMusic(); //start melody /* no break */ case BUZZER_LONGBEEP : case BUZZER_SHORTBEEP : case BUZZER_ON : TIM_Cmd( TIM3, ENABLE ); break; case BUZZER_OFF : TIM_Cmd( TIM3, DISABLE ); break; } } /******************************************************************************* * * BUZZER_PlayMusic * *******************************************************************************/ /** * * Plays the provided melody that follows the RTTTL Format. * * Official Specification * @verbatim <ringing-tones-text-transfer-language> := <name> <sep> [<defaults>] <sep> <note-command>+ <name> := <char>+ ; maximum name length 10 characters <sep> := ":" <defaults> := <def-note-duration> | <def-note-scale> | <def-beats> <def-note-duration> := "d=" <duration> <def-note-scale> := "o=" <scale> <def-beats> := "b=" <beats-per-minute> <beats-per-minute> := 25,28,...,900 ; decimal value ; If not specified, defaults are ; ; 4 = duration ; 6 = scale ; 63 = beats-per-minute <note-command> := [<duration>] <note> [<scale>] [<special-duration>] <delimiter> <duration> := "1" | ; Full 1/1 note "2" | ; 1/2 note "4" | ; 1/4 note "8" | ; 1/8 note "16" | ; 1/16 note "32" | ; 1/32 note <note> := "P" | ; pause "C" | "C#" | "D" | "D#" | "E" | "F" | "F#" | "G" | "G#" | "A" | "A#" | "B" <scale> := "5" | ; Note A is 440Hz "6" | ; Note A is 880Hz "7" | ; Note A is 1.76 kHz "8" ; Note A is 3.52 kHz <special-duration> := "." ; Dotted note <delimiter> := "," @endverbatim * * @param[in] melody New melody to play on buzzer. * **/ /******************************************************************************/ void BUZZER_PlayMusic (const u8 *melody ) { u8 c; u8 default_id = 0; u16 default_val = 0; DefaultOctave = OCT_880; // Default for the default Octave. DefaultDuration = 4; // Default for the default Duration. DefaultBeats = 63; CurrentMelody = melody; CurrentMelodySTART = melody; while( *CurrentMelody != RTTTL_SEP ) { if( *CurrentMelody == 0 ) { return; } // Discard the melody name. CurrentMelody++; } // Now read the defaults if any. for( ++CurrentMelody; *CurrentMelody != RTTTL_SEP; CurrentMelody++ ) { if( *CurrentMelody == 0 ) { return; } // Discard any blank. while ( *CurrentMelody == ' ' ) { CurrentMelody++; } c = *CurrentMelody; if ( c == RTTTL_SEP ) { break; } if ( (c >= 'a') && (c <= 'z') ) { c+=('A'-'a'); } if ( (c >= 'A') && (c <= 'Z') ) { default_id = c; continue; } if ( (c >= '0') && (c <= '9') ) { default_val *= 10; default_val += (c-'0'); c = * (CurrentMelody + 1 ); if ( (c >= '0') && (c <= '9') ) { continue; } if ( default_id == 'D' ) { DefaultDuration = default_val; } else if ( default_id == 'O' ) { DefaultOctave = default_val - 5; if ( DefaultOctave > OCT_7040 ) DefaultOctave = OCT_440; } else if ( default_id == 'B' ) { DefaultBeats = default_val; if ( ( DefaultBeats == 0 ) || ( DefaultBeats > 500 ) ) DefaultBeats = 63; } default_val = 0; default_id = 0; } } BUZZER_SetMode( BUZZER_PLAYMUSIC ); }
Go to most recent revision | Compare with Previous | Blame | View Log