示例#1
0
static void button_timer_event_handler(void) {
    if (HAL_Buttons[BUTTON1].active && (BUTTON_GetState(BUTTON1) == BUTTON1_PRESSED)) {
        if (!HAL_Buttons[BUTTON1].debounce_time) {
            HAL_Buttons[BUTTON1].debounce_time += BUTTON_DEBOUNCE_INTERVAL;
#if MODULE_FUNCTION != MOD_FUNC_BOOTLOADER
            HAL_Notify_Button_State(BUTTON1, true); 
#endif
        }
        HAL_Buttons[BUTTON1].debounce_time += BUTTON_DEBOUNCE_INTERVAL;
    } else if (HAL_Buttons[BUTTON1].active) {
        HAL_Buttons[BUTTON1].active = false;
        button_reset(BUTTON1);
    }

    if ((HAL_Buttons[BUTTON1_MIRROR].pin != PIN_INVALID) && HAL_Buttons[BUTTON1_MIRROR].active &&
        BUTTON_GetState(BUTTON1_MIRROR) == (HAL_Buttons[BUTTON1_MIRROR].interrupt_mode == RISING ? 1 : 0)) 
    {
        if (!HAL_Buttons[BUTTON1_MIRROR].debounce_time) {
            HAL_Buttons[BUTTON1_MIRROR].debounce_time += BUTTON_DEBOUNCE_INTERVAL;
#if MODULE_FUNCTION != MOD_FUNC_BOOTLOADER
            HAL_Notify_Button_State(BUTTON1_MIRROR, true);
#endif
        }
        HAL_Buttons[BUTTON1_MIRROR].debounce_time += BUTTON_DEBOUNCE_INTERVAL;
    } else if ((HAL_Buttons[BUTTON1_MIRROR].pin != PIN_INVALID) && HAL_Buttons[BUTTON1_MIRROR].active) {
        HAL_Buttons[BUTTON1_MIRROR].active = false;
        button_reset(BUTTON1_MIRROR);
    }
}
/**
 * @brief  This function handles TIM2_IRQ Handler.
 * @param  None
 * @retval None
 */
void TIM2_irq(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
    {
        if (BUTTON_GetState(BUTTON1) == BUTTON1_PRESSED)
        {
            if (!BUTTON_DEBOUNCED_TIME[BUTTON1])
            {
            BUTTON_DEBOUNCED_TIME[BUTTON1] += BUTTON_DEBOUNCE_INTERVAL;
                HAL_Notify_Button_State(BUTTON1, true);
        }
            BUTTON_DEBOUNCED_TIME[BUTTON1] += BUTTON_DEBOUNCE_INTERVAL;
        }
        else
        {
            HAL_Core_Mode_Button_Reset();
        }
    }

    HAL_System_Interrupt_Trigger(SysInterrupt_TIM2_IRQ, NULL);
    uint8_t result =
    handle_timer(TIM2, TIM_IT_CC1, SysInterrupt_TIM2_Compare1) ||
    handle_timer(TIM2, TIM_IT_CC2, SysInterrupt_TIM2_Compare2) ||
    handle_timer(TIM2, TIM_IT_CC3, SysInterrupt_TIM2_Compare3) ||
    handle_timer(TIM2, TIM_IT_CC4, SysInterrupt_TIM2_Compare4) ||
    handle_timer(TIM2, TIM_IT_Update, SysInterrupt_TIM2_Update) ||
    handle_timer(TIM2, TIM_IT_Trigger, SysInterrupt_TIM2_Trigger);
    UNUSED(result);
}
示例#3
0
void BUTTON_Check_State(uint16_t button, uint8_t pressed) {
    if (BUTTON_GetState(button) == pressed) {
        if (!HAL_Buttons[button].active) {
            HAL_Buttons[button].active = true;
        }
        HAL_Buttons[button].debounce_time += BUTTON_DEBOUNCE_INTERVAL;
    } else if (HAL_Buttons[button].active) {
        HAL_Buttons[button].active = false;
        /* Enable button Interrupt */
        BUTTON_EXTI_Config(button, ENABLE);
    }
}
示例#4
0
/*******************************************************************************
 * Function Name  : TIM1_CC_IRQHandler
 * Description    : This function handles TIM1 Capture Compare interrupt request.
 * Input          : None
 * Output         : None
 * Return         : None
 *******************************************************************************/
void TIM1_CC_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET)
	{
		TIM_ClearITPendingBit(TIM1, TIM_IT_CC4);

		if (BUTTON_GetState(BUTTON1) == BUTTON1_PRESSED)
		{
			BUTTON_DEBOUNCED_TIME[BUTTON1] += BUTTON_DEBOUNCE_INTERVAL;
		}
		else
		{
			/* Disable TIM1 CC4 Interrupt */
			TIM_ITConfig(TIM1, TIM_IT_CC4, DISABLE);

			/* Enable BUTTON1 Interrupt */
			BUTTON_EXTI_Config(BUTTON1, ENABLE);
		}
	}
}
示例#5
0
void BUTTON_Init(Button_TypeDef button, ButtonMode_TypeDef Button_Mode) {

    if (!systick_button_timer.enable) {
        // Initialize button timer
        button_timer_init();
    }

    // Configure button pin
    HAL_Pin_Mode(HAL_Buttons[button].pin, HAL_Buttons[button].interrupt_mode == RISING ? INPUT_PULLDOWN : INPUT_PULLUP);
    if (Button_Mode == BUTTON_MODE_EXTI)  {
        /* Attach GPIOTE Interrupt */
        BUTTON_EXTI_Config(button, ENABLE);
    }

    // Check status when starting up
    if (HAL_Buttons[button].pin != PIN_INVALID && 
        BUTTON_GetState(button) == (HAL_Buttons[button].interrupt_mode == RISING ? 1 : 0)) 
    {
        HAL_Buttons[button].active = true;
        button_timer_start();
    }
}
示例#6
0
enum MENU_code fTest_Mgr( void )
{
    int fRedrawn = 0;
    static bool fFirstTime = 1;
    static bool AUDIO_BuzzerOn_bak = 0;

    if ( fFirstTime )
    {
        fFirstTime = 0;
        MenuFirstDisplay = 1;
    }

    // Hide menu.
    CurrentMenu = 0;
    fDisplayTime = 0; // force display time - battery status

    // Character magnify.
    DRAW_SetCharMagniCoeff( 2 );

    // If screen orientation has changed, redraw screen.
    if ( MenuFirstDisplay == 0 )
    {
        if ( LCD_GetScreenOrientation() != previous_Screen_Orientation )
        {
            MenuFirstDisplay = 1;
        }
    }

    if ( MenuFirstDisplay )
    {
        previous_Screen_Orientation = LCD_GetScreenOrientation();
        POINTER_SetMode( POINTER_OFF );
        LCD_SetRotateScreen( 0 );
        LCD_SetScreenOrientation( V12 );

        // Red LED blinks at high frequency.
        LED_Set( LED_RED, LED_BLINKING_HF );

        // Green LED blinks at low frequency.
        LED_Set( LED_GREEN, LED_BLINKING_LF );

        // Draw a little message on the LCD screen.
        DRAW_SetDefaultColor();
        DRAW_DisplayStringWithMode( 0, Screen_Height - 2 * Char_Height, "Hardware Test", ALL_SCREEN, INVERTED_TEXT, CENTER );
        MenuFirstDisplay = 0;

        // Drawn that rectangle on the screen.
        LCD_FillRect_Circle( BAR_LEFT + 1, BAR_BOTTOM + 1, MAXLEVEL * WIDTH_SQUARE  , WIDTH_SQUARE - 2, RGB_YELLOW );
        LCD_DrawRect( BAR_LEFT, BAR_BOTTOM, MAXLEVEL * WIDTH_SQUARE + 2 , WIDTH_SQUARE, RGB_BLUE );

        // Restrict the move of the pointer to a rectangle.
        POINTER_SetRect( BAR_LEFT + 1, BAR_BOTTOM + 1, MAXLEVEL * WIDTH_SQUARE - POINTER_WIDTH - 2, WIDTH_SQUARE - POINTER_WIDTH - 2 );
        POINTER_SetMode( POINTER_ON );

        // Force buzzer activation
        AUDIO_BuzzerOn_bak = AUDIO_BuzzerOn;
        AUDIO_BuzzerOn = 1;

    } // end FirstDisplay

    // The button is pushed, let's get out of here!
    if ( BUTTON_GetState() == BUTTON_PUSHED )
    {
        int i;
    
        BUTTON_WaitForRelease();

        // Reset CircleOS state.
        MENU_ClearCurrentCommand();
        DRAW_SetDefaultColor();
        DRAW_Clear();
        POINTER_SetMode( POINTER_ON );
        BUTTON_SetMode( BUTTON_ONOFF_FORMAIN );
        POINTER_SetRectScreen();
        DRAW_SetCharMagniCoeff( 1 );

#if BACKLIGHT_INTERFACE
        // Reset backlight PWM rate to its default value.
        LCD_SetBackLight( 0 );
#endif // BACKLIGHT_INTERFACE

        // Switch LEDs off.
        LED_Set( LED_RED, LED_OFF );
        LED_Set( LED_GREEN, LED_OFF );

        fFirstTime  = 1;

        // Search if test aplication present in flash
        for ( i = 0; i < MAXAPP; i++ )
        {
            extern tMenuItem*(( *ApplicationTable )[] );
            tMenuItem*  curapp;
            unsigned addr;

            if (( *ApplicationTable )[ -i ] == APP_VOID ) //has been programmed
            {
                break;
            }
            else
            {
                addr   = ( long unsigned )( *ApplicationTable )[ -i ] ;
                addr &= 0x00FFFFFF;
                addr |= 0x08000000;
                curapp = ( tMenuItem* ) addr;
                if ( !strcmp( curapp->Text, "COMMTEST" ) )
                {
                    LCD_SetOffset( OFFSET_ON );
                    CurrentCommand = curapp;
                    CurrentMenu = 0;
                    BUTTON_SetMode( BUTTON_ONOFF );
                    return CurrentCommand ->Fct_Init();
                }
            }
        }

        LCD_SetRotateScreen( 1 );
        LCD_SetScreenOrientation( previous_Screen_Orientation );

        AUDIO_BuzzerOn = AUDIO_BuzzerOn_bak;

        return MENU_LEAVE;
    }

#if BACKLIGHT_INTERFACE
    // Increment the backlight PWM.
    Current_CCR_BackLightStart += 0x800;

    // If backlight PWM is too high, restart with a lower value.
    if ( Current_CCR_BackLightStart > 0xF000 )
    {
        Current_CCR_BackLightStart = 0x2000;
    }
#endif // BACKLIGHT_INTERFACE


    // Every 59th calls display battery voltage and replay melody sample.
    // Note: due to the fRedrawn == 0, the first time the % 59 == 0
    //       (when divider_coord is null), the code block isn't executed.
    if ((( menu_divider_coord++ % 37 ) == 0 ) && ( fRedrawn == 0 ) )
    {
        char TextBuffer[5];
        *TextBuffer = '%'; *( TextBuffer + 1 ) = 0; // YRT20080204 : to avoid memcpy

        DRAW_DisplayVbat( 20, 12 );
        UTIL_uint2str( TextBuffer + 1, PWR_BatteryLevel, 3, 0 );
        DRAW_DisplayString( 170, 12, TextBuffer, 4 );
    
        BUZZER_PlayMusic( Test_Melody );
    }
    return MENU_CONTINUE;
}
示例#7
0
enum MENU_code fAboutMgr( void )
{
    int            LastApplication   = -1;
    int            AppSizeCounter    = 0;
    int            freeMemoryFlash   = 0;
    int            i;
    long unsigned  addr;
    unsigned long* lptr              = ( unsigned long* ) CIRCLEOS_FAT_ADDRESS; // YRT20090114
    tMenuItem *(( *ApplicationTable )[] );

    ApplicationTable  = ( tMenuItem * ((* )[] ) )( *lptr );

    MENU_ClearCurrentMenu();

    for ( i = 0 ; i < MAXAPP ; i++ )
    {
        if (( *ApplicationTable )[ -i ] == APP_VOID ) //has been programmed
        {
            break;
        }

        LastApplication =  i;
    }

    if ( LastApplication != -1 )
    {
        for ( i = 0; i <= LastApplication; i++ )
        {
            addr   = ( long unsigned )( *ApplicationTable )[ -i ] ;
            addr &= 0xFF000000;

            AppSizeCounter += ( addr >> 24 );
        }
    }

    // When the user pushedthe button, it's time to leave!
    if ( BUTTON_GetState() == BUTTON_PUSHED )
    {
        return fQuit();
    }

    // If screen orientation has changed, we redraw the screen!
    if ( MenuFirstDisplay == 0 )
    {
        if ( LCD_GetScreenOrientation() != previous_Screen_Orientation )
        {
            MenuFirstDisplay = 1;
        }
    }

    // Let's draw the 'About' screen.
    if ( MenuFirstDisplay )
    {
        DRAW_SetCharMagniCoeff( 2 );

        previous_Screen_Orientation   = LCD_GetScreenOrientation();

        DRAW_SetTextColor( RGB_BLACK );
        freeMemoryFlash               = 128 - 104 - AppSizeCounter;
        DRAW_DisplayStringWithMode( 0, 200, "STM32L Primer", ALL_SCREEN, NORMAL_TEXT, CENTER );
        DRAW_DisplayStringWithMode( 0, 174, "CPU:STM32L152VB", ALL_SCREEN, NORMAL_TEXT, CENTER );
        DRAW_SetCharMagniCoeff( 1 );
        DRAW_DisplayString( 62,   148,  "OS : V4.0    24 KB",   18 );
        DRAW_DisplayString( 62,   122,  "App: 2       16 KB",   18 );
        DRAW_DisplayString( 62,    96,  "Avail FLASH: 88 KB",   18 );

        DRAW_SetTextColor( RGB_BLUE );
        DRAW_DisplayString( 97,    148,  UTIL_GetVersion(),      6 );
        DRAW_DisplayString( 146,    148,  "100",                  3 );

        UTIL_uint2str( TextBuffer, LastApplication + 1, 2, 0 );
        DRAW_DisplayString( 97,    122,  TextBuffer,             2 );
        UTIL_uint2str( TextBuffer, AppSizeCounter, 3, 0 );
        DRAW_DisplayString( 146,    122,  TextBuffer,             3 );

        UTIL_uint2str( TextBuffer, freeMemoryFlash , 3, 0 );
        DRAW_DisplayString( 146,    96,  TextBuffer,             3 );

        DRAW_SetCharMagniCoeff( 2 );
        DRAW_SetTextColor( RGB_MAKE( 0, 183, 239 ) );
        DRAW_SetBGndColor( RGB_BLACK );
        LCD_FillRect_Circle( 0, 0, Screen_Width, Char_Height * 2, RGB_BLACK );
        DRAW_DisplayStringWithMode( 0, 0, "STM32circle.com", ALL_SCREEN, NORMAL_TEXT, CENTER );

        DRAW_SetDefaultColor();

        DRAW_SetCharMagniCoeff( 1 );

        MenuFirstDisplay = 0;
    }

    return MENU_CONTINUE;
}
示例#8
0
  enum MENU_code fTest_Mgr( void )
{
    int fRedrawn = 0;
    static bool fFirstTime = 1;
    static s8 AUDIO_SpeakerOn_bak;
    static s8 AUDIO_Volume_bak;

    if ( fFirstTime )
    {
        AUDIO_SpeakerOn_bak = AUDIO_SpeakerOn;
        AUDIO_Volume_bak = AUDIO_Volume;
        AUDIO_Volume = AUDIO_MIN_ATTENUATION;
        AUDIO_SpeakerOn = 1;
        UTIL_SetPll( SPEED_VERY_HIGH );
        fFirstTime = 0;
        MenuFirstDisplay = 1;
    }

    // Hide menu.
    CurrentMenu = 0;
    fDisplayTime = 0; // force display time - battery status

    // Character magnify.
    DRAW_SetCharMagniCoeff( 2 );

    // If screen orientation has changed, redraw screen.
    if ( MenuFirstDisplay == 0 )
    {
        if ( LCD_GetScreenOrientation() != previous_Screen_Orientation )
        {
            MenuFirstDisplay = 1;
        }
    }

    if ( MenuFirstDisplay )
    {
        previous_Screen_Orientation = LCD_GetScreenOrientation();
        POINTER_SetMode( POINTER_OFF );
        LCD_SetRotateScreen( 0 );
        LCD_SetScreenOrientation( V12 );


        // Red LED blinks at high frequency.
        LED_Set( LED_RED, LED_BLINKING_HF );

        // Green LED blinks at low frequency.
        LED_Set( LED_GREEN, LED_BLINKING_LF );

        // Init daughter board LED
        DB_LED_Init();

        // Draw a little message on the LCD screen.
        DRAW_SetDefaultColor();
        DRAW_DisplayStringWithMode( 0, Screen_Height - 2 * Char_Height, "Hardware Test", ALL_SCREEN, INVERTED_TEXT, CENTER );
        MenuFirstDisplay = 0;

        // Drawn that rectangle on the screen.
        LCD_FillRect_Circle( BAR_LEFT + 1, BAR_BOTTOM + 1, MAXLEVEL * WIDTH_SQUARE  , WIDTH_SQUARE - 2, RGB_YELLOW );
        LCD_DrawRect( BAR_LEFT, BAR_BOTTOM, MAXLEVEL * WIDTH_SQUARE + 2 , WIDTH_SQUARE, RGB_BLUE );

        // Restrict the move of the pointer to a rectangle.
        POINTER_SetRect( BAR_LEFT + 1, BAR_BOTTOM + 1, MAXLEVEL * WIDTH_SQUARE - POINTER_WIDTH - 2, WIDTH_SQUARE - POINTER_WIDTH - 2 );
        POINTER_SetMode( POINTER_ON );


        fRedrawn = 1;
        RecordPlaySeq = -1;
        AUDIO_Welcome_Msg();
    } // end FirstDisplay

    // The button is pushed, let's get out of here!
    if ( BUTTON_GetState() == BUTTON_PUSHED )
    {
        int i;

        BUTTON_WaitForRelease();

        // Reset CircleOS state.
        MENU_ClearCurrentCommand();
        DRAW_SetDefaultColor();
        DRAW_Clear();
        POINTER_SetMode( POINTER_ON );
        BUTTON_SetMode( BUTTON_ONOFF_FORMAIN );
        POINTER_SetRectScreen();
        DRAW_SetCharMagniCoeff( 1 );

        // Reset backlight PWM rate to its default value.
        LCD_SetBackLight( 0 );

        // Switch LEDs off.
        LED_Set( LED_RED, LED_OFF );
        LED_Set( LED_GREEN, LED_OFF );
        GPIO_WriteBit( GPIOx_DB_LED, GPIO_Pin_DB_LED1, Bit_SET );
        GPIO_WriteBit( GPIOx_DB_LED, GPIO_Pin_DB_LED2, Bit_SET );

        // No sound
        AUDIO_Playback_status = NO_SOUND;
        AUDIO_Recording_status = NO_RECORD;

        // Restore default mode
        AUDIO_SetMode( AUDIO_MODE, LG_8_BITS, FRQ_16KHZ, MONO );

        // Restore the previous config
        AUDIO_SpeakerOn = AUDIO_SpeakerOn_bak;
        AUDIO_Volume = AUDIO_Volume_bak;
        fFirstTime  = 1;

        for ( i = 0; i < MAXAPP; i++ )
        {
            extern tMenuItem*(( *ApplicationTable )[] );
            tMenuItem*  curapp;
            unsigned addr;


            if (( *ApplicationTable )[ -i ] == APP_VOID ) //has been programmed
            {
                break;
            }
            else
            {
                addr   = ( long unsigned )( *ApplicationTable )[ -i ] ;
                addr &= 0x00FFFFFF;
                addr |= 0x08000000;
                curapp = ( tMenuItem* ) addr;
                if ( !strcmp( curapp->Text, "COMMTEST" ) )
                {
                    LCD_SetOffset( OFFSET_ON );
                    CurrentCommand = curapp;
                    CurrentMenu = 0;
                    BUTTON_SetMode( BUTTON_ONOFF );
                    return CurrentCommand ->Fct_Init();
                }
            }
        }
        LCD_SetRotateScreen( 1 );
        LCD_SetScreenOrientation( previous_Screen_Orientation );


        return MENU_LEAVE;
    }

    // Increment the backlight PWM.
    Current_CCR_BackLightStart += 0x800;

    //-- Parrot mode in order to test microphone and speaker
    if (( AUDIO_Playback_status == NO_SOUND ) && ( AUDIO_Recording_status == NO_RECORD ) )
    {

        // Values -1 and 2 for RecordPlaySeq correspond to the first loop.
        // Recording requires a delay (internal to the Codec?) before
        // getting non-zero values. The first cycle provides this delay

        if (( RecordPlaySeq == 0 ) || ( RecordPlaySeq == -1 ) )
        {
            // End of playback, launch the record
            if ( AUDIO_Playback_status == NO_SOUND )
            {
                AUDIO_SetMode( VOICE_MODE, LG_16_BITS, FRQ_16KHZ, MONO );
                // Take all the available memory for the record (= RAM_BASE - data size - 500 bytes for the stack)
                AUDIO_Record(( sound_type* ) RAM_BASE , (( CIRCLEOS_RAM_OFS ) / sizeof( voice_type ) ) - 500 ) ;
            }
            if ( RecordPlaySeq != -1 )
            {
                // Red LED blinks at high frequency.
                LED_Set( LED_GREEN, LED_OFF );
                LED_Set( LED_RED, LED_ON );
                DRAW_DisplayStringWithMode( 0, 160, "** RECORDING **", ALL_SCREEN, NORMAL_TEXT, CENTER );
                RecordPlaySeq = 1;
            }
            else
                RecordPlaySeq = 2;

        }
        else
        {
            if ( AUDIO_Recording_status == NO_RECORD )
            {
                // End of recording, launch the playback
                AUDIO_SetMode( AUDIO_MODE, LG_16_BITS, FRQ_16KHZ, MONO );
                AUDIO_Play(( sound_type* ) RAM_BASE , (( CIRCLEOS_RAM_OFS ) / sizeof( voice_type ) ) - 500 ) ;
            }
            if ( RecordPlaySeq != 2 )
            {
                // Red LED blinks at high frequency.
                LED_Set( LED_GREEN, LED_ON );
                LED_Set( LED_RED, LED_OFF );
                DRAW_DisplayStringWithMode( 0, 160, "** PLAYING **", ALL_SCREEN, NORMAL_TEXT, CENTER );
            }
            RecordPlaySeq = 0;
        }
    }

    if (( AUDIO_Recording_status == IS_RECORDING )  && (( AUDIO_RecordBuffer_GetStatus( 0 ) & HIGH_FULL ) ) )
        AUDIO_Record_Stop();


    // If backlight PWM is too high, restart with a lower value.
    if ( Current_CCR_BackLightStart > 0xF000 )
    {
        Current_CCR_BackLightStart = 0x2000;
    }

    // Every 59th calls display battery voltage and replay melody sample.
    // Note: due to the fRedrawn == 0, the first time the % 59 == 0
    //       (when divider_coord is null), the code block isn't executed.
    if ((( menu_divider_coord++ % 37 ) == 0 ) && ( fRedrawn == 0 ) )
    {
        char TextBuffer[5];
        *TextBuffer = '%'; *( TextBuffer + 1 ) = 0; // YRT20080204 : to avoid memcpy

        DRAW_DisplayVbat( 20, 12 );
        UTIL_uint2str( TextBuffer + 1, PWR_BatteryLevel, 3, 0 );
        DRAW_DisplayString( 170, 12, TextBuffer, 4 );
    }

    // Toggle daughter card leds
    if (( menu_divider_coord % 2 ) == 0 )
    {
        GPIO_WriteBit( GPIOx_DB_LED, GPIO_Pin_DB_LED1, Bit_SET );
        GPIO_WriteBit( GPIOx_DB_LED, GPIO_Pin_DB_LED2, Bit_RESET );
    }
    else
    {
        GPIO_WriteBit( GPIOx_DB_LED, GPIO_Pin_DB_LED1, Bit_RESET );
        GPIO_WriteBit( GPIOx_DB_LED, GPIO_Pin_DB_LED2, Bit_SET );
    }

    return MENU_CONTINUE;
}
/*******************************************************************************
*
*                                TOUCHSCR calibration
*
*******************************************************************************/
enum MENU_code TOUCHSCREEN_Calibration( void )
{
    s32 xpos = TOUCHSCR_Info.xRaw;
    s32 ypos = TOUCHSCR_Info.yRaw;

    // Avoid time display
    fDisplayTime = FALSE;

    // Cancel calibration, if central button pushed
    if ( BUTTON_GetState() == BUTTON_PUSHED )
    {
        BUTTON_WaitForRelease();
        TS_SeqCal = 8;
        return;
    }

    // Force mode when the function is called from the menu
    if ( TOUCHSCR_Info.Mode != TS_CALIBRATION )
    {
        TOUCHSCR_Info.Mode = TS_CALIBRATION;
        TS_SeqCal = 0;
        fTS_InitCal = 0;
    }

    switch ( TS_SeqCal )
    {
    case 0 :
        if ( fTS_InitCal == 0 )
        {
            // Do it only once
            fTS_InitCal = 1;

            // Don't display main screen and block rotation during calibration
            POINTER_SetMode( POINTER_OFF );
            BUTTON_SetMode( BUTTON_ONOFF );
            LCD_SetScreenOrientation( V12 );
            LCD_SetRotateScreen( 0 );

            // Title
            LCD_FillRect_Circle( 0, 0, Screen_Width, Screen_Height, RGB_WHITE );
            DRAW_SetCharMagniCoeff( 2 );
            DRAW_DisplayStringWithMode( 0, 180, "TOUCHSCREEN", ALL_SCREEN, NORMAL_TEXT, CENTER );
            DRAW_DisplayStringWithMode( 0, 150, "CALIBRATION", ALL_SCREEN, NORMAL_TEXT, CENTER );
            DRAW_SetCharMagniCoeff( 1 );

            // Ask for the first button touch
            DRAW_DisplayStringWithMode( 0, 70, "Press on",  ALL_SCREEN, NORMAL_TEXT, CENTER );
            DRAW_DisplayStringWithMode( 0, 55, "the black cross",  ALL_SCREEN, NORMAL_TEXT, CENTER );
            DRAW_DisplayStringWithMode( 0, 40, "with a stylus",  ALL_SCREEN, NORMAL_TEXT, CENTER );
            DRAW_Cross_Absolute( TS_RefSample[0].X, TS_RefSample[0].Y, RGB_BLACK, CROSS_SIZE );
        }

        // When starting calibration from config menu with touchsreen
        // the first point was entered immediately.
        if ( !TOUCHSCR_Info.TouchPress )
        {
            TS_SeqCal++;
        }
        break;

    case 1:
        // Store first touch informations
        if ( TOUCHSCR_Info.TouchPress )
        {
            TS_CalBuffer[0].X = xpos;
            TS_CalBuffer[0].Y = ypos;
            TS_SeqCal++;
        }
        break;

    case 2 :
        // Ask for the second button touch
        if ( !( TOUCHSCR_Info.TouchPress ) )
        {
            LCD_FillRect_Circle( TS_RefSample[0].X - CROSS_SIZE, TS_RefSample[0].Y - CROSS_SIZE,
            ( CROSS_SIZE * 2 ) + 1, ( CROSS_SIZE * 2 ) + 1, RGB_WHITE );
            DRAW_Cross_Absolute( TS_RefSample[1].X, TS_RefSample[1].Y, RGB_BLACK, CROSS_SIZE );
            TS_SeqCal++;
        }
        break;

    case 3:
        // Store second touch informations
        if ( TOUCHSCR_Info.TouchPress )
        {
            TS_CalBuffer[1].X = xpos;
            TS_CalBuffer[1].Y = ypos;
            TS_SeqCal++;
        }
        break;

    case 4:
        if ( !( TOUCHSCR_Info.TouchPress ) )
        {
            // Ask for the third button touch
            LCD_FillRect_Circle( TS_RefSample[1].X - CROSS_SIZE, TS_RefSample[1].Y - CROSS_SIZE,
            ( CROSS_SIZE * 2 ) + 1, ( CROSS_SIZE * 2 ) + 1, RGB_WHITE );
            DRAW_Cross_Absolute( TS_RefSample[2].X, TS_RefSample[2].Y, RGB_BLACK, CROSS_SIZE );
            TS_SeqCal++;
        }
        break;

    case 5 :
        // Store third touch informations
        if ( TOUCHSCR_Info.TouchPress )
        {
            TS_CalBuffer[2].X = xpos;
            TS_CalBuffer[2].Y = ypos;

            TS_SeqCal++;
        }
        break;

    case 6 :
        // End of calibration
        if ( !( TOUCHSCR_Info.TouchPress ) )
        {
            // Calculate and update the coefficients
            TOUCHSCR_CalculateCalibration( TS_CalBuffer );

            // Save the calibration points
            UTIL_WriteBackupRegister( BKP_TS_X0, TS_CalBuffer[0].X );
            UTIL_WriteBackupRegister( BKP_TS_Y0, TS_CalBuffer[0].Y );
            UTIL_WriteBackupRegister( BKP_TS_X1, TS_CalBuffer[1].X );
            UTIL_WriteBackupRegister( BKP_TS_Y1, TS_CalBuffer[1].Y );
            UTIL_WriteBackupRegister( BKP_TS_X2, TS_CalBuffer[2].X );
            UTIL_WriteBackupRegister( BKP_TS_Y2, TS_CalBuffer[2].Y );

            LCD_FillRect_Circle( 0, 0, Screen_Width, Screen_Height, RGB_WHITE );
            DRAW_DisplayStringWithMode( 0, 55, "Calibration", ALL_SCREEN, NORMAL_TEXT, CENTER );
            DRAW_DisplayStringWithMode( 0, 40, "done.", ALL_SCREEN, NORMAL_TEXT, CENTER );
            DRAW_DisplayStringWithMode( 0, 15, "Touch the screen..", ALL_SCREEN, NORMAL_TEXT, CENTER );
            TS_SeqCal++;
        }
        break;

    case 7:
        if ( TOUCHSCR_Info.TouchPress )
            TS_SeqCal++;
        break;

    case 8:
    {
        // Restore normal conditions
        TS_SeqCal = 0;
        TOUCHSCR_Info.Mode = TS_NORMAL;

        // Can display main screen
        POINTER_SetMode( POINTER_ON );
        BUTTON_SetMode( BUTTON_ONOFF_FORMAIN );
        LCD_SetRotateScreen( 1 );
        DRAW_Clear();
    }
    break;

    } // switch ( TS_SeqCal )
} // end function