PT606668DC\Src:第27~32

//                        UI.c


/****************************************************************************
 * File Name: UI.c
 *
 * Description:
 *					UI
 *
 * --------------------------------------------------------------------
 * Revision	Author		Date		Comment
 * --------------------------------------------------------------------
 * 1.0          Junrong         2019/12/02		Original
 *
 *****************************************************************************/
#include <stdlib.h>
#include <stdarg.h>
#include "hal.h"
#include "Power.h"
#include "EscCommand.h"
#include "string.h"
#include "Language.h"
#include "DeviceDB.h"
#include "MFG.h"
#include "Printer.h"
#include "UI.h"
#include "ICON.h"
//extern ST_PRINTER_CONFIG g_PrinterConfig;

INT8 densityComp = 0;
INT8 printVoltComp = 0;
INT8 printTempComp = 0;
ST_UI_STATUS UIStatus = {
    .Mode       = UI_MODE_MAIN,
	.Menu       = ENUM_MENU_SERIAL,
    .IdleTime   = 0,
    .IdleFlag   = 0,
};
static QueueHandle_t        UIEventQueueHandle = NULL;
void TIM6_IRQHandler(void)
{
    // Internal 100ms
    if(__HAL_TIM_GET_FLAG(&htimUI, TIM_FLAG_UPDATE) != RESET)  
    {   
        __HAL_TIM_CLEAR_IT(&htimUI, TIM_IT_UPDATE);
        if(UIStatus.IdleTime < 30000)
        {
            UIStatus.IdleTime++;
        }
        if((!UIStatus.IdleFlag) && (UIStatus.Mode == UI_MODE_MENU))
        {
            if(UIStatus.IdleTime > 50)
            {
                UIStatus.IdleFlag = 1;
                UI_SendEvent(UIEVENT_IDLE_TIMEOUT, NULL);
            }
        }
        if(DeviceDB.ShutMode != SHUT_MODE_NEVER)
        {
            switch(DeviceDB.ShutMode)
            {
                case SHUT_MODE_5M:
                    if(UIStatus.IdleTime > 3000)
                    {
                        UI_SendEvent(UIEVENT_SHUTDOWN, NULL);
                    }
                    break;
                case SHUT_MODE_10M:
                    if(UIStatus.IdleTime > 6000)
                    {
                        UI_SendEvent(UIEVENT_SHUTDOWN, NULL);
                    }
                    break;
                case SHUT_MODE_20M:
                    if(UIStatus.IdleTime > 12000)
                    {
                        UI_SendEvent(UIEVENT_SHUTDOWN, NULL);
                    }
                    break;
                case SHUT_MODE_30M:
                    if(UIStatus.IdleTime > 18000)
                    {
                        UI_SendEvent(UIEVENT_SHUTDOWN, NULL);
                    }
                    break;
                case SHUT_MODE_NEVER:
                    break;
            }
            
        }
    }
}
void UI_ClearIdle(void)
{
    UIStatus.IdleTime = 0;
    UIStatus.IdleFlag = 0;
}
static void UiTitleRefresh(void)
{
#ifndef DISABLE_BT
    LCD_TitleBTStateSet(SystemStatus.BTConn);
#endif
    LCD_TitleSettingEn(UIStatus.Mode == UI_MODE_MENU);
    LCD_TitlePHOpenEn(SystemStatus.PHOpen);
    LCD_TitleNoPaperEn(SystemStatus.NoPaper);
    LCD_TitleUSBConnEn(SystemStatus.USBConn);
    LCD_TitleDcConnEn(SystemStatus.DcConn);
    LCD_TitleBatLevelSet(SystemStatus.BatLevel);
}
void UI_Refresh(void)
{
    BYTE fontSize = (DeviceDB.Language == LANGUAGE_CHINESE)?(24):(16);
    switch(UIStatus.Mode)
    {
        case UI_MODE_MAIN:
            if(SystemStatus.BatteryLow)
            {
                LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_BATTERY_LOW]);
            }
            else if(SystemStatus.NoDetectGap)
            {
                switch(DeviceDB.PrintConfig.PaperType)
                {
                    case PAPER_TYPE_GAP:
#if defined(MODEL_PT68DC) || defined(MODEL_PT60DC)
                    case PAPER_TYPE_RFID:
#endif
                    case PAPER_TYPE_NORMAL:
                        LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_NO_DETECT_GAP]);
                        break;
                    case PAPER_TYPE_HOLE:
                        LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_NO_DETECT_HOLE]);
                        break;
                    case PAPER_TYPE_BLACK:
                        LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_NO_DETECT_MARK]);
                        break;
                    
                }
            }
            else if(SystemStatus.CalibrationFailed)
            {
                LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_CALIBRATION_FAILED]);
            }
            else if(SystemStatus.NoPaper)
            {
                LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_NO_PAPER]);
            }
            else if(SystemStatus.PHOpen)
            {
                LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_HEAT_SWITCH_OPEN]);
            }
            else if(SystemStatus.RibbonNoDetect)
            {
                LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_NO_RIBBON]);
            }
            else if(SystemStatus.RibbonRunout)
            {
                LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_OUT_OF_RIBBON]);
            }
            else
            {
                LCD_Clear();
#ifdef BRAND_RU
                LCD_PutText((128 - MIN(128, StrFontWidth(24, MfgInfo.ModelNo)))/2, 16, 24, MfgInfo.ModelNo);
                //LCD_PutText((128 - strlen(MfgInfo.BT.Name)*12)/2, 16, 24, MfgInfo.BT.Name);
                LCD_PutText((128 - MIN(128, StrFontWidth(24, MfgInfo.SerialNo)))/2, 40, 24, "%s", MfgInfo.SerialNo);
#else
                //LCD_PutText((128 - strlen(MfgInfo.ModelNo)*12)/2, 16, 24, MfgInfo.ModelNo);
                LCD_PutText((128 - strlen(MfgInfo.BT.Name)*12)/2, 16, 24, MfgInfo.BT.Name);
                LCD_PutText((128 - strlen(MfgInfo.SerialNo)*12)/2, 40, 24, "%s", MfgInfo.SerialNo);
#endif
            }
            break;
        case UI_MODE_MENU:
#ifdef BRAND_RU
            switch(UIStatus.Menu)
            {
                case ENUM_MENU_SERIAL:
                {
                    LCD_Clear();
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->SerialNo)))/2, 16, 16, pLanguage->SerialNo);
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, MfgInfo.SerialNo)))/2, 40, 16, "%s",MfgInfo.SerialNo);		//Parameters
                    break;
                }
                case ENUM_MENU_SW_VER:
                {
                    char buf[32];
                    MFG_GetFWVersion(buf);
                    LCD_Clear();
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->SoftVer)))/2, 16, fontSize, pLanguage->SoftVer);
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, buf))) / 2, 48, 16, "%s", buf);
                    break;
                }
                case ENUM_MENU_PRINT_TEST:
                {
                    LCD_Clear();
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->SelfCheck))) / 2, 16, fontSize, pLanguage->SelfCheck);
                    //start self-check
                    break;
                }
                case ENUM_MENU_LANGUAGE:
                {
                    LCD_Clear();
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->LanguageSel))) / 2, 16, 16, pLanguage->LanguageSel);
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->LanguageOption[DeviceDB.Language])))/2, 40, 16, pLanguage->LanguageOption[DeviceDB.Language]);
                    break;
                }
                case ENUM_MENU_DENSITY:
                {
                    LCD_Clear();
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->PrintDensity))) / 2, 16, fontSize, pLanguage->PrintDensity);
//                #ifdef __DEBUG__                    
//                    LCD_PutText((DeviceDB.PrintConfig.Depth < 9)?60:56, 40, 24, "%u", DeviceDB.PrintConfig.Depth + 1);
//                #else
                   
                   // LCD_PutText((128 - strlen(pLanguage->DensityOption[DeviceDB.PrintConfig.Depth])*12)/2, 40, 24, pLanguage->DensityOption[DeviceDB.PrintConfig.Depth]);
                    LCD_PutTextEx(40, 16, pLanguage->DensityOption[DeviceDB.PrintConfig.Depth]);
//                #endif
                    break;
                }
                case ENUM_MENU_SPEED:
                {
                    LCD_Clear();
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->PrintSpeed))) / 2, 16, fontSize, pLanguage->PrintSpeed);
                    //LCD_PutText((128 - strlen(pLanguage->SpeedOption[DeviceDB.PrintConfig.Speed])*12)/2, 40, 24, pLanguage->SpeedOption[DeviceDB.PrintConfig.Speed]);
                    LCD_PutTextEx(40, (16), pLanguage->SpeedOption[DeviceDB.PrintConfig.Speed]);
                    break;
                }
//                case ENUM_MENU_DENSITY_COMP:
//                {
//                    LCD_Clear();
//                    LCD_PutText((128 - strlen("浓度补偿")*(fontSize / 2))/2, 16, fontSize, "浓度补偿");
//                    LCD_PutText((128 - 5 * 12)/2, 40, 24, "%+d", densityComp);
//                    break;
//                }
//                case ENUM_MENU_VOLTAGE_COMP:
//                {
//                    LCD_Clear();
//                    LCD_PutText((128 - strlen("电压补偿")*(fontSize / 2))/2, 16, fontSize, "电压补偿");
//                    LCD_PutText((128 - 5 * 12)/2, 40, 24, "%+d", printVoltComp);
//                    break;
//                }
//                case ENUM_MENU_TEMP_COMP:
//                {
//                    LCD_Clear();
//                    LCD_PutText((128 - strlen("温度补偿")*(fontSize / 2))/2, 16, fontSize, "温度补偿");
//                    LCD_PutText((128 - 5 * 12)/2, 40, 24, "%+d", printTempComp);
//                    break;
//                }
                case ENUM_MENU_DISTANCE:
                {
                    LCD_Clear();
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->PrintDistance))) / 2, 16, fontSize, pLanguage->PrintDistance);
                    LCD_PutText((128 - 6 * 8)/2, 40, 16, "%3u mm", DeviceDB.PrintConfig.Distance);
                    break;
                }
#ifdef MODEL_PT68DC
                case ENUM_MENU_UHF_TXPOWER:
                {
                    LCD_Clear();
                    LCD_PutText(0, 16, fontSize, pLanguage->TxPower);
                    LCD_PutText((128 - 6 * 12)/2, 40, 24, "%2u dBm", DeviceDB.PrintConfig.TxPower);
                    break;
                }
#endif
                case ENUM_MENU_AUTO_SHUTDOWN:
                {
                    LCD_Clear();
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->ShutdownMode))) / 2, 16, fontSize, pLanguage->ShutdownMode);
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->ShutdownModeOption[DeviceDB.ShutMode])))/2, 40, 16, pLanguage->ShutdownModeOption[DeviceDB.ShutMode]);
                    break;
                }
                case ENUM_MENU_PAPER_TYPE:
                {
                    LCD_Clear();
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->PaperType))) / 2, 16, fontSize, pLanguage->PaperType);
                    if(strlen(pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]) > 10)
                    {
                        LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType])))/2, 40, 16, pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]);
                    }
                    else
                    {
                        LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType])))/2, 40, 16, pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]);
                    }
                    break;
                }
                case ENUM_MENU_POSITION:
                {
                    LCD_Clear();
                    LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->AutoCalibration)))/2, 16, fontSize, pLanguage->AutoCalibration);
                    if(strlen(pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]) > 10)
                    {
                    //    LCD_PutText((128 - StrFontWidth(16, (char *)pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]))/2, 40, 16, pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]);
                        LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType])))/2, 40, 16, pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]);
                     }
                    else
                    {
                        LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType])))/2, 40, 16, pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]);
                    }
        			LCD_PutText(16, 16, 24, "自动标定");
        			LCD_PutText(28, 40, 24, "间隙纸 %d", g_PrinterConfig.PaperType);
                    break;
                }
                case ENUM_MENU_FACTORY_DEFAULT:
                {
                    LCD_Clear();
                    //LCD_PutText((128 - strlen(pLanguage->ResetFactory)*(fontSize / 2))/2, 16, fontSize, pLanguage->ResetFactory);
                    LCD_PutTextEx(16, fontSize, pLanguage->ResetFactory);
                    break;
                }
                case ENUM_MENU_MAC_ADDRESS:
                {
                    LCD_Clear();
                    if(DeviceDB.Language == LANGUAGE_CHINESE)
                    {
                        LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->MacAdd)))/2, 16, 16, pLanguage->MacAdd);
                    }
                    else
                    {
                        LCD_PutText((128 - MIN(128, StrFontWidth(16, (char *)pLanguage->MacAdd)))/2, 16, 16, pLanguage->MacAdd);
                    }
                    LCD_PutText(0, 48, 16, "%02X%02X:%02X:%02X:%02X:%02X", MfgInfo.BT.MacAddr[0],
                                                                           MfgInfo.BT.MacAddr[1],
                                                                           MfgInfo.BT.MacAddr[2],
                                                                           MfgInfo.BT.MacAddr[3],
                                                                           MfgInfo.BT.MacAddr[4],
                                                                           MfgInfo.BT.MacAddr[5]);
                    break;
                }
            }
#else
        
            switch(UIStatus.Menu)
            {
                case ENUM_MENU_SERIAL:
                {
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->SerialNo)*12)/2, 16, 24, pLanguage->SerialNo);
                    LCD_PutText((128 - strlen(MfgInfo.SerialNo)*12)/2, 40, 24, "%s",MfgInfo.SerialNo);		//Parameters
                    break;
                }
                case ENUM_MENU_SW_VER:
                {
                    char buf[32];
                    MFG_GetFWVersion(buf);
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->SoftVer) * fontSize / 2) / 2, 16, fontSize, pLanguage->SoftVer);
                    LCD_PutText((128 - strlen(buf) * 8) / 2, 48, 16, "%s", buf);
                    //LCD_PutText(0, 40, 24, "V%d.%d.%d.%d",FW_INFO.Version[0],FW_INFO.Version[1],FW_INFO.Version[2],FW_INFO.Version[3]);
                    break;
                }
                case ENUM_MENU_PRINT_TEST:
                {
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->SelfCheck)*(fontSize / 2))/2, 16, fontSize, pLanguage->SelfCheck);
                    //start self-check
                    break;
                }
                case ENUM_MENU_LANGUAGE:
                {
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->LanguageSel)*12)/2, 16, 24, pLanguage->LanguageSel);
                    LCD_PutText((128 - strlen(pLanguage->LanguageOption[DeviceDB.Language])*12)/2, 40, 24, pLanguage->LanguageOption[DeviceDB.Language]);
                    break;
                }
                case ENUM_MENU_DENSITY:
                {
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->PrintDensity)*(fontSize / 2))/2, 16, fontSize, pLanguage->PrintDensity);
//                #ifdef __DEBUG__                    
//                    LCD_PutText((DeviceDB.PrintConfig.Depth < 9)?60:56, 40, 24, "%u", DeviceDB.PrintConfig.Depth + 1);
//                #else
                   
                   // LCD_PutText((128 - strlen(pLanguage->DensityOption[DeviceDB.PrintConfig.Depth])*12)/2, 40, 24, pLanguage->DensityOption[DeviceDB.PrintConfig.Depth]);
                    LCD_PutTextEx(40, (DeviceDB.Language == LANGUAGE_CHINESE)?(24):(16), pLanguage->DensityOption[DeviceDB.PrintConfig.Depth]);
//                #endif
                    break;
                }
                case ENUM_MENU_SPEED:
                {
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->PrintSpeed)*(fontSize / 2))/2, 16, fontSize, pLanguage->PrintSpeed);
                    //LCD_PutText((128 - strlen(pLanguage->SpeedOption[DeviceDB.PrintConfig.Speed])*12)/2, 40, 24, pLanguage->SpeedOption[DeviceDB.PrintConfig.Speed]);
                    LCD_PutTextEx(40, (DeviceDB.Language == LANGUAGE_CHINESE)?(24):(16), pLanguage->SpeedOption[DeviceDB.PrintConfig.Speed]);
                    break;
                }
//                case ENUM_MENU_DENSITY_COMP:
//                {
//                    LCD_Clear();
//                    LCD_PutText((128 - strlen("浓度补偿")*(fontSize / 2))/2, 16, fontSize, "浓度补偿");
//                    LCD_PutText((128 - 5 * 12)/2, 40, 24, "%+d", densityComp);
//                    break;
//                }
//                case ENUM_MENU_VOLTAGE_COMP:
//                {
//                    LCD_Clear();
//                    LCD_PutText((128 - strlen("电压补偿")*(fontSize / 2))/2, 16, fontSize, "电压补偿");
//                    LCD_PutText((128 - 5 * 12)/2, 40, 24, "%+d", printVoltComp);
//                    break;
//                }
//                case ENUM_MENU_TEMP_COMP:
//                {
//                    LCD_Clear();
//                    LCD_PutText((128 - strlen("温度补偿")*(fontSize / 2))/2, 16, fontSize, "温度补偿");
//                    LCD_PutText((128 - 5 * 12)/2, 40, 24, "%+d", printTempComp);
//                    break;
//                }
                case ENUM_MENU_DISTANCE:
                {
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->PrintDistance)*(fontSize / 2))/2, 16, fontSize, pLanguage->PrintDistance);
                    LCD_PutText((128 - 6 * 12)/2, 40, 24, "%3u mm", DeviceDB.PrintConfig.Distance);
                    break;
                }
#ifdef MODEL_PT68DC
                case ENUM_MENU_UHF_TXPOWER:
                {
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->TxPower)*(fontSize / 2))/2, 16, fontSize, pLanguage->TxPower);
                    LCD_PutText((128 - 6 * 12)/2, 40, 24, "%2u dBm", DeviceDB.PrintConfig.TxPower);
                    break;
                }
#endif
                case ENUM_MENU_AUTO_SHUTDOWN:
                {
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->ShutdownMode)*(fontSize / 2))/2, 16, fontSize, pLanguage->ShutdownMode);
                    LCD_PutText((128 - strlen(pLanguage->ShutdownModeOption[DeviceDB.ShutMode])*12)/2, 40, 24, pLanguage->ShutdownModeOption[DeviceDB.ShutMode]);
                    break;
                }
                case ENUM_MENU_PAPER_TYPE:
                {
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->PaperType)*(fontSize / 2))/2, 16, fontSize, pLanguage->PaperType);
                    if(strlen(pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]) > 10)
                    {
                        LCD_PutText((128 - strlen(pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType])*8)/2, 40, 16, pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]);
                    }
                    else
                    {
                        LCD_PutText((128 - strlen(pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType])*12)/2, 40, 24, pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]);
                    }
                    break;
                }
                case ENUM_MENU_POSITION:
                {
                    LCD_Clear();
                    LCD_PutText((128 - strlen(pLanguage->AutoCalibration)*(fontSize / 2))/2, 16, fontSize, pLanguage->AutoCalibration);
                    if(strlen(pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]) > 10)
                    {
                        LCD_PutText((128 - strlen(pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType])*8)/2, 40, 16, pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]);
                    }
                    else
                    {
                        LCD_PutText((128 - strlen(pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType])*12)/2, 40, 24, pLanguage->PaperTypeOption[DeviceDB.PrintConfig.PaperType]);
                    }
        			LCD_PutText(16, 16, 24, "自动标定");
        			LCD_PutText(28, 40, 24, "间隙纸 %d", g_PrinterConfig.PaperType);
                    break;
                }
                case ENUM_MENU_FACTORY_DEFAULT:
                {
                    LCD_Clear();
                    //LCD_PutText((128 - strlen(pLanguage->ResetFactory)*(fontSize / 2))/2, 16, fontSize, pLanguage->ResetFactory);
                    LCD_PutTextEx(16, fontSize, pLanguage->ResetFactory);
                    break;
                }
                case ENUM_MENU_MAC_ADDRESS:
                {
                    LCD_Clear();
                    if(DeviceDB.Language == LANGUAGE_CHINESE)
                    {
                        LCD_PutText((128 - strlen(pLanguage->MacAdd)*12)/2, 16, 24, pLanguage->MacAdd);
                    }
                    else
                    {
                        LCD_PutText((128 - strlen(pLanguage->MacAdd)*8)/2, 16, 16, pLanguage->MacAdd);
                    }
                    LCD_PutText(0, 48, 16, "%02X%02X:%02X:%02X:%02X:%02X", MfgInfo.BT.MacAddr[0],
                                                                           MfgInfo.BT.MacAddr[1],
                                                                           MfgInfo.BT.MacAddr[2],
                                                                           MfgInfo.BT.MacAddr[3],
                                                                           MfgInfo.BT.MacAddr[4],
                                                                           MfgInfo.BT.MacAddr[5]);
                    break;
                }
            }
#endif
            break;
        case UI_MODE_ALERT:
            break;
        case UI_MODE_UPGRADING:
            LCD_ShowMessage(fontSize, pLanguage->Upgrading);
            break;
        case UI_MODE_PRINTING:
        {
            if(SystemStatus.RibbonNoDetect)
            {
                LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_NO_RIBBON]);
            }
            else if(SystemStatus.RibbonRunout)
            {
                LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_OUT_OF_RIBBON]);
            }
            else if(SystemStatus.PauseFlag)
            {
                LCD_ShowMessage(16, pLanguage->Printing[1]);                
//                LCD_PutText(0, 48, 16, "Yes           No");
            }
            else 
            {
                if(SystemStatus.CalibratingFlag)
                {
                    LCD_ShowMessage(fontSize, pLanguage->Printing[2]);
                }
                else
                {
                    LCD_ShowMessage(fontSize, pLanguage->Printing[0]);
                }
            }
            break;
        }
        case UI_MODE_DETECTING:
        { 
            if(SystemStatus.RibbonNoDetect)
            {
                LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_NO_RIBBON]);
            }
            else if(SystemStatus.RibbonRunout)
            {
                LCD_ShowMessage(fontSize, pLanguage->AlertMsg[ALERT_OUT_OF_RIBBON]);
            }
            else if(SystemStatus.PauseFlag)
            {
                LCD_ShowMessage(16, pLanguage->Printing[1]);                
            //    LCD_PutText(0, 48, 16, "Yes           No");
            }
            else 
            {
                if(SystemStatus.CalibratingFlag)
                {
                    LCD_ShowMessage(fontSize, pLanguage->Printing[2]);
                }
                else
                {
                    LCD_ShowMessage(fontSize, pLanguage->Printing[0]);
                }
            }
            break;
        }
    }
    UiTitleRefresh();
}
static void UIKeyEvent_Main(KEY_CODE key)
{
//    if(SystemStatus.RibbonNoDetect)
//    {
//        return;
//    }
    switch(key)
    {
        case KEY_EX_LONG_SETUP:
        case KEY_EX_SETUP:
            if((!SystemStatus.NoPaper) && (!SystemStatus.PHOpen) && (!Printer_IsPrinting()))
            {
                if(DeviceDB.PrintConfig.PaperType == PAPER_TYPE_NORMAL)
                {
//                    while(!IORead(GPIO_BTN_SETUP));
//                    vTaskDelay(100);
//                    while(IORead(GPIO_BTN_SETUP))
//                    {
//                        Motor_Forward(mSpeedLevelToPulseTime(4), PIXEL_MOTOR_STEP);
//                    }
                    while(!IORead(GPIO_BTN_SETUP))
                    {
                        Printer_FeedpaperRow();
                    }
                }
                else
                {
                    Printer_FeedpaperPage();
                }
            }
            break;
        case KEY_EX_START:
            if(!Printer_IsPrinting())
            {
                UIStatus.Mode = UI_MODE_MENU;
                UI_Refresh();
            }
            break;
        case KEY_EX_LONG_START:
            if(!Printer_IsBusy())
            {
                DeviceDB_Save();
                Printer_Shutdown();
            }
            else
            {
                DeviceDB_Save();
                Power_Shutdown();
            }
            break;
        case KEY_EX_COUNT_SETUP:
            break;
    }
}
static void UIKeyEvent_Menu(KEY_CODE key)
{
    switch(key)
    {
        case KEY_EX_LONG_SETUP:
        case KEY_EX_SETUP:
            switch(UIStatus.Menu)
            {
                case ENUM_MENU_PRINT_TEST:
                    Printer_PrintTest();
                    break;
                case ENUM_MENU_LANGUAGE:
#if defined(BRAND_TEST)
                    DeviceDB.Language = (DeviceDB.Language < (ENUM_LANGUAGE_COUNT -1)) ? (DeviceDB.Language + 1) : (0);
#elif defined(BRAND_ORVED)
                    DeviceDB.Language = (DeviceDB.Language == LANGUAGE_ENGLISH) ? (LANGUAGE_ITALIANO) : (LANGUAGE_ENGLISH);
#elif defined(BRAND_RU)
                    DeviceDB.Language = (DeviceDB.Language == LANGUAGE_ENGLISH) ? (LANGUAGE_RU) : (LANGUAGE_ENGLISH);
#else
                    DeviceDB.Language = (DeviceDB.Language == LANGUAGE_ENGLISH) ? (LANGUAGE_CHINESE) : (LANGUAGE_ENGLISH);
#endif
                    LanguageSwitch(DeviceDB.Language);
                    DeviceDBChangeFlag = 1;
                    break;
                case ENUM_MENU_DENSITY:
//                #ifdef __DEBUG__
//                    DeviceDB.PrintConfig.Depth = (DeviceDB.PrintConfig.Depth < (45 - 1)) ? (DeviceDB.PrintConfig.Depth + 1) : (0);
//                #else
                    DeviceDB.PrintConfig.Depth = (DeviceDB.PrintConfig.Depth < (ENUM_PRINT_DEPTH_COUNT - 1)) ? (DeviceDB.PrintConfig.Depth + 1) : (0);
//                #endif
                    DeviceDBChangeFlag = 1;
                    break;
//                case ENUM_MENU_DENSITY_COMP:
//                {
//                    densityComp = (densityComp < 20)?(densityComp + 1):(0);
//                    break;
//                }
//                case ENUM_MENU_VOLTAGE_COMP:
//                {
//                    printVoltComp = (printVoltComp < 20)?(printVoltComp + 1):(0);
//                    break;
//                }
 //               case ENUM_MENU_TEMP_COMP:
//                {
//                    printTempComp = (printTempComp < 10)?(printTempComp + 1):(-10);
//                    break;
//                }
                case ENUM_MENU_SPEED:
                    DeviceDB.PrintConfig.Speed = (DeviceDB.PrintConfig.Speed < (ENUM_PRINT_SPEED_COUNT - 1)) ? (DeviceDB.PrintConfig.Speed + 1) : (0);
                    DeviceDBChangeFlag = 1;
                    break;
                case ENUM_MENU_DISTANCE:
                    DeviceDB.PrintConfig.Distance = (DeviceDB.PrintConfig.Distance < (RFID_ANTENNA_DISTANCE_MAX)) ? (DeviceDB.PrintConfig.Distance + 1) : (RFID_ANTENNA_DISTANCE_MIN);
                    DeviceDBChangeFlag = 1;
                    break;
#ifdef MODEL_PT68DC
                case ENUM_MENU_UHF_TXPOWER:
                {
                    if(DeviceDB.PrintConfig.TxPower < RFID_TX_POWER_MIN)
                    {
                        DeviceDB.PrintConfig.TxPower = RFID_TX_POWER_MIN;
                    }
                    DeviceDB.PrintConfig.TxPower = (DeviceDB.PrintConfig.TxPower < (RFID_TX_POWER_MAX)) ? (DeviceDB.PrintConfig.TxPower + 1) : (RFID_TX_POWER_MIN);
                    UHF_SetTxPower(MIN(25, DeviceDB.PrintConfig.TxPower + 3) * 100, DeviceDB.PrintConfig.TxPower * 100, 1, 0);
                    DeviceDBChangeFlag = 1;
                    break;
                }
#endif
                case ENUM_MENU_AUTO_SHUTDOWN:
                    DeviceDB.ShutMode = (DeviceDB.ShutMode < (ENUM_SHUT_MODE_COUNT - 1)) ? (DeviceDB.ShutMode + 1) : (0);
                    DeviceDBChangeFlag = 1;
                    break;
                case ENUM_MENU_PAPER_TYPE:
                    DeviceDB.PrintConfig.PaperType = (DeviceDB.PrintConfig.PaperType < (ENUM_PAPER_TYPE_COUNT - 1)) ? (DeviceDB.PrintConfig.PaperType + 1) : (0);
                    Printer_ClearPaperStatus();
                    DeviceDBChangeFlag = 1;
                    break;
                case ENUM_MENU_POSITION:
                    //Printer_FeedpaperToEnd();
                    Printer_PaperDetect();
                    return;
                case ENUM_MENU_FACTORY_DEFAULT:
                #ifndef DISABLE_BT
                    if(IORead(GPIO_BT_CONN_STATE))
                    {
                        LCD_ShowMessage((DeviceDB.Language == LANGUAGE_CHINESE)?(24):(16), pLanguage->ResetFactoryMsg[0]);
                        vTaskDelay(1000);
                        UIStatus.Mode = UI_MODE_MAIN;
                        switch(DeviceDB.PrintConfig.PaperType)
                        {
                            case PAPER_TYPE_BLACK:
                            case PAPER_TYPE_HOLE:
                                SystemStatus.NoPaper = 0;
                                break;
                            case PAPER_TYPE_NORMAL:
                            case PAPER_TYPE_GAP:
#if defined(MODEL_PT68DC) || defined(MODEL_PT60DC)
                            case PAPER_TYPE_RFID:
#endif
                                break;
                        }
//                        UI_Refresh();
                        
                    }
                    else
#endif
                    {
                        LCD_ShowMessage((DeviceDB.Language == LANGUAGE_CHINESE)?(24):(16), pLanguage->ResetFactoryMsg[1]);
                        DeviceDB_FactoryDefault();
                        MFG_BTFactoryDefault();
                        vTaskDelay(1000);
                        LCD_ShowMessage((DeviceDB.Language == LANGUAGE_CHINESE)?(24):(16), pLanguage->ResetFactoryMsg[2]);
                        vTaskDelay(1000);
                        UIStatus.Mode = UI_MODE_MAIN;
                        switch(DeviceDB.PrintConfig.PaperType)
                        {
                            case PAPER_TYPE_BLACK:
                            case PAPER_TYPE_HOLE:
                                SystemStatus.NoPaper = 0;
                                break;
                            case PAPER_TYPE_NORMAL:
                            case PAPER_TYPE_GAP:
#if defined(MODEL_PT68DC) || defined(MODEL_PT60DC)
                            case PAPER_TYPE_RFID:
#endif
                                break;
                        }
//                        UI_Refresh();
                    }
                    break;
                case ENUM_MENU_MAC_ADDRESS:
                case ENUM_MENU_SERIAL:
                case ENUM_MENU_SW_VER:
                    break;
            }
            UI_Refresh();
            break;
        case KEY_EX_START:
            if((UIStatus.Menu == ENUM_MENU_PAPER_TYPE) && (DeviceDB.PrintConfig.PaperType == PAPER_TYPE_NORMAL))
            {
                UIStatus.Menu++; // Skip Auto Position Menu
            }
#if defined(MODEL_PT68DC) || defined(MODEL_PT60DC)
            else if((UIStatus.Menu == ENUM_MENU_SPEED) && (DeviceDB.PrintConfig.PaperType != PAPER_TYPE_RFID))
#else
            else if(UIStatus.Menu == ENUM_MENU_SPEED)
#endif
            {
                UIStatus.Menu++; // Skip Antenna distance
#if defined(MODEL_PT68DC)
                UIStatus.Menu++;
#endif
            }
#ifdef DISABLE_BT
            else if(UIStatus.Menu == ENUM_MENU_FACTORY_DEFAULT)
            {
                UIStatus.Menu = 0;
                UI_Refresh();
                break;
            }
#endif
            UIStatus.Menu = (UIStatus.Menu < (ENUM_MENU_COUNT -1))?(UIStatus.Menu + 1):(0); 
            UI_Refresh();
            break;
        case KEY_EX_LONG_START:
            UIStatus.Mode = UI_MODE_MAIN;
            switch(DeviceDB.PrintConfig.PaperType)
            {
                case PAPER_TYPE_BLACK:
                case PAPER_TYPE_HOLE:
                    SystemStatus.NoPaper = 0;
                    break;
                case PAPER_TYPE_NORMAL:
                case PAPER_TYPE_GAP:
#if defined(MODEL_PT68DC) || defined(MODEL_PT60DC)
                case PAPER_TYPE_RFID:
#endif
                    break;
            }
            UI_Refresh();
            break;
        case KEY_EX_COUNT_SETUP:
            switch(UIStatus.Menu)
            {
                case ENUM_MENU_DENSITY:
//                #ifdef __DEBUG__
//                    DeviceDB.PrintConfig.Depth = (DeviceDB.PrintConfig.Depth < (45 - 1)) ? (DeviceDB.PrintConfig.Depth + 1) : (0);
//                #else
                    DeviceDB.PrintConfig.Depth = (DeviceDB.PrintConfig.Depth < (ENUM_PRINT_DEPTH_COUNT - 1)) ? (DeviceDB.PrintConfig.Depth + 1) : (0);
//                #endif
                    DeviceDBChangeFlag = 1;
                    UI_Refresh();
                    break;
                case ENUM_MENU_SPEED:
                    DeviceDB.PrintConfig.Speed = (DeviceDB.PrintConfig.Speed < (ENUM_PRINT_SPEED_COUNT - 1)) ? (DeviceDB.PrintConfig.Speed + 1) : (0);
                    DeviceDBChangeFlag = 1;
                    UI_Refresh();
                    break;
                case ENUM_MENU_DISTANCE:
                    DeviceDB.PrintConfig.Distance = ((DeviceDB.PrintConfig.Distance + 10) <= (RFID_ANTENNA_DISTANCE_MAX)) ? (DeviceDB.PrintConfig.Distance + 10) : (RFID_ANTENNA_DISTANCE_MIN);
                    DeviceDBChangeFlag = 1;
                    UI_Refresh();
                    break;
#ifdef MODEL_PT68DC
                case ENUM_MENU_UHF_TXPOWER:
                    if(DeviceDB.PrintConfig.TxPower < RFID_TX_POWER_MIN)
                    {
                        DeviceDB.PrintConfig.TxPower = RFID_TX_POWER_MIN;
                    }
                    DeviceDB.PrintConfig.TxPower = (DeviceDB.PrintConfig.TxPower < (RFID_TX_POWER_MAX)) ? (DeviceDB.PrintConfig.TxPower + 1) : (RFID_TX_POWER_MIN);
                    DeviceDBChangeFlag = 1;
                    UHF_SetTxPower(MIN(25, DeviceDB.PrintConfig.TxPower + 3) * 100, DeviceDB.PrintConfig.TxPower * 100, 1, 0);
                    UI_Refresh();
                    break;
#endif
                case ENUM_MENU_AUTO_SHUTDOWN:
                    DeviceDB.ShutMode = (DeviceDB.ShutMode < (ENUM_SHUT_MODE_COUNT - 1)) ? (DeviceDB.ShutMode + 1) : (0);
                    DeviceDBChangeFlag = 1;
                    UI_Refresh();
                    break;
                case ENUM_MENU_PAPER_TYPE:
                    DeviceDB.PrintConfig.PaperType = (DeviceDB.PrintConfig.PaperType < (ENUM_PAPER_TYPE_COUNT - 1)) ? (DeviceDB.PrintConfig.PaperType + 1) : (0);
                    DeviceDBChangeFlag = 1;
                    UI_Refresh();
                    break;
            }
            break;
    }
}
static void UIKeyEvent_Alert(KEY_CODE key)
{
    UIStatus.Mode = UI_MODE_MAIN;
    switch(DeviceDB.PrintConfig.PaperType)
    {
        case PAPER_TYPE_BLACK:
        case PAPER_TYPE_HOLE:
            SystemStatus.NoPaper = 0;
            break;
        case PAPER_TYPE_NORMAL:
        case PAPER_TYPE_GAP:
#if defined(MODEL_PT68DC) || defined(MODEL_PT60DC)
        case PAPER_TYPE_RFID:
#endif
            break;
    }
    UI_Refresh();
}
static void UIKeyEvent_Printing(KEY_CODE key)
{
    if((SystemStatus.RibbonNoDetect || SystemStatus.RibbonRunout) && (key !=  KEY_EX_LONG_START))
    {
        return;
    }
    switch(key)
    {
        case KEY_EX_LONG_SETUP:
        case KEY_EX_SETUP:
            if(SystemStatus.PauseFlag)
            {
                // abort
                SystemStatus.AbortFlag = 1;
                SystemStatus.PauseFlag = 0;
                Printer_PrintAbort();  
                UI_SendEvent(UIEVENT_PRINT_ABORT, NULL);              
            }
            break;
        case KEY_EX_START:
            if(SystemStatus.PauseFlag)
            {
                // resume
                Printer_PrintResume();
                SystemStatus.PauseFlag = 0;
                UI_SendEvent(UIEVENT_PRINT_RESUME, NULL);   
            }
            else
            {
                // pause
                Printer_PrintPause();
                SystemStatus.PauseFlag = 1;      
                UI_SendEvent(UIEVENT_PRINT_PAUSE, NULL);             
            }
            break;
        case KEY_EX_LONG_START:
            DeviceDB_Save();
            Power_Shutdown();
            break;
        case KEY_EX_COUNT_SETUP:
            break;
    }
}

static void UIKeyEvent_Detecting(KEY_CODE key)
{
    switch(key)
    {
        case KEY_EX_LONG_SETUP:
        case KEY_EX_SETUP:
            break;
        case KEY_EX_START:
            break;
        case KEY_EX_LONG_START:
            DeviceDB_Save();
            Power_Shutdown();
            break;
        case KEY_EX_COUNT_SETUP:
            break;
    }
}
static void UIKeyEvent_Upgrading(KEY_CODE key)
{
    switch(key)
    {
        case KEY_EX_LONG_SETUP:
        case KEY_EX_SETUP:
            break;
        case KEY_EX_START:
            break;
        case KEY_EX_LONG_START:
//            DeviceDB_Save();
//            Power_Shutdown();
            break;
        case KEY_EX_COUNT_SETUP:
            break;
    }
}
//static void UiTask(const void *param)
//{
//    while(1)
//    {
//        KEY_CODE key = Key_BufferRead(portMAX_DELAY);
//        if(key != KEY_CODE_NULL)
//        {
//            UI_ClearIdle();
//            switch(UIStatus.Mode)
//            {
//                case UI_MODE_MAIN:
//                    UIKeyEvent_Main(key);
//                    break;
//                case UI_MODE_MENU:
//                    UIKeyEvent_Menu(key);
//                    break;
//                case UI_MODE_ALERT:
//                    UIKeyEvent_Alert(key);
//                    break;
//            }
//        }
//    }
//}

void KeyPressESR(KEY_CODE key)
{
    UI_ClearIdle();
//    switch(key)
//    {
//        case KEY_EX_LONG_SETUP:
//        case KEY_EX_SETUP:
//            break;
//        case KEY_EX_START:
//        {
//            UINT16 len = 0;
//            ENUM_ERROR_CODE stat = Printer_RibbonCheck(0, &len);
//            //LCD_PutText(0,0,16,"%d,%u ", stat, len);
//            break;
//        }
//        case KEY_EX_LONG_START:
//            if(!Printer_IsBusy())
//            {
//                DeviceDB_Save();
//                Printer_Shutdown();
//            }
//            else
//            {
//                DeviceDB_Save();
//                Power_Shutdown();
//            }
//            break;
//        case KEY_EX_COUNT_SETUP:
//            break;
//    }
    switch(UIStatus.Mode)
    {
        case UI_MODE_MAIN:
            UIKeyEvent_Main(key);
            break;
        case UI_MODE_MENU:
            UIKeyEvent_Menu(key);
            break;
        case UI_MODE_ALERT:
            UIKeyEvent_Alert(key);
            break;
        case UI_MODE_UPGRADING:
            UIKeyEvent_Upgrading(key);
            break;
        case UI_MODE_PRINTING:
            UIKeyEvent_Printing(key);
            break;
        case UI_MODE_DETECTING:
            UIKeyEvent_Detecting(key);
            break;
    }
}
static void UiEventTask(const void *param)
{
    ST_UIEVENT event = {0};
    while(1)
    {
        if(xQueueReceive(UIEventQueueHandle, &event, portMAX_DELAY))
        {
            switch(event.EventID)
            {
                case UIEVENT_IDLE_TIMEOUT:
                {
                    UIStatus.Mode = UI_MODE_MAIN;
                    switch(DeviceDB.PrintConfig.PaperType)
                    {
                        case PAPER_TYPE_BLACK:
                        case PAPER_TYPE_HOLE:
                            SystemStatus.NoPaper = 0;
                            break;
                        case PAPER_TYPE_NORMAL:
                        case PAPER_TYPE_GAP:
#if defined(MODEL_PT68DC) || defined(MODEL_PT60DC)
                        case PAPER_TYPE_RFID:
#endif
                            break;
                    }
                    DeviceDB_Save();
                    UI_Refresh();
                    break;
                }
                case UIEVENT_SHUTDOWN:
                    Printer_Shutdown();
                    break;
                case UIEVENT_BATTERY_LOW:
                    Printer_PrintAbort();
                    UI_Refresh();
                    break;
                case UIEVENT_BATTERY_LOW_RESUME:
                    UI_Refresh();
                    break;
                case UIEVENT_HEAT_OPEN:
                    UiTitleRefresh();
                    if((UIStatus.Mode == UI_MODE_MAIN) || (UIStatus.Mode == UI_MODE_ALERT))
                    {
                        //UI_Alert(pLanguage->AlertMsg[ALERT_HEAT_SWITCH_OPEN]);
                        UI_Refresh();
                    }
                    if(Printer_IsPrinting())
                    {
                        Printer_ClearPaperStatus();
                        Printer_PrintAbort();
                    }
                    
                    // UI_MODE_MENU
                    if((UIStatus.Mode == UI_MODE_PRINTING) || (UIStatus.Mode == UI_MODE_DETECTING))
                    {
                        UIStatus.Mode = UI_MODE_MAIN;
                        UiTitleRefresh();
                        UI_Refresh();
                    }
                    break;
                case UIEVENT_HEAT_CLOSE:
                    UIStatus.Mode = UI_MODE_MAIN;
                    if(SystemStatus.PauseFlag)
                    {
                        SystemStatus.PauseFlag = 0;
                    }
                    UiTitleRefresh();
                    UI_Refresh();
                    break;
                case UIEVENT_NO_RIBBON:
                    UiTitleRefresh();
                    if(UIStatus.Mode == UI_MODE_MAIN)
                    {
                        //UI_Alert(pLanguage->AlertMsg[ALERT_HEAT_SWITCH_OPEN]);
                        UI_Refresh();
                    }
                    else if(Printer_IsPrinting())
                    {
                        //Printer_ClearPaperStatus();
                        //Printer_PrintPause();
                        Printer_PrintAbort();
                        UI_Refresh();
                    }
                    else
                    {
                        UIStatus.Mode = UI_MODE_MAIN;
                        UI_Refresh();
                    }
                    break;
                case UIEVENT_PRINTING:
                    if(UIStatus.Mode != UI_MODE_PRINTING)
                    {
                        UIStatus.Mode = UI_MODE_PRINTING;
                        UI_Refresh();
                    }
                    break;
                case UIEVENT_DETECTING:
                    if(UIStatus.Mode != UI_MODE_DETECTING)
                    {
                        UIStatus.Mode = UI_MODE_DETECTING;
                        UI_Refresh();
                    }
                    break;
                case UIEVENT_PRINT_DONE:
                    UIStatus.Mode = UI_MODE_MAIN;
                    UI_Refresh();
                    break;
                case UIEVENT_CALIBRATION_DONE:
                    UIStatus.Mode = UI_MODE_MAIN;
                    UI_Refresh();
                    break;
                case UIEVENT_PRINT_PAUSE:
                    UI_Refresh();
                    break;
                case UIEVENT_PRINT_RESUME:
                    UI_Refresh();
                    break;
                case UIEVENT_PRINT_ABORT:
                    UIStatus.Mode = UI_MODE_MAIN;
                    UI_Refresh();
                    break;
                case UIEVENT_SYSTEM_STATUS_CHANGE:
                    UiTitleRefresh();
                    if(UIStatus.Mode == UI_MODE_MAIN)
                    {
                        UI_Refresh();
                    }
                    break;
                case UIEVENT_BATTERY_LV_CHANGE:
                    LCD_TitleBatLevelSet(SystemStatus.BatLevel);
                    break;
                case UIEVENT_UPGRADING:
                    if(UIStatus.Mode != UI_MODE_UPGRADING)
                    {
                        UIStatus.Mode = UI_MODE_UPGRADING;
                        UI_Refresh();
                    }
                    break;
                case UIEVENT_NO_PAPER:
                    break;
                default:
                    break;
            }
        }
    }
}
void UI_Alert(const char *msg)
{
    UIStatus.Mode = UI_MODE_ALERT;
    BYTE fontSize = (DeviceDB.Language == LANGUAGE_CHINESE)?(24):(16);
    LCD_ShowMessage(fontSize, msg);
}
BOOL UI_SendEvent(ENUM_UIEVENT eventID, void *param)
{
    portBASE_TYPE taskWoken = pdFALSE;    
    ST_UIEVENT stEvent;
    if(UIEventQueueHandle == NULL)
    {
        return 0;
    }
    stEvent.EventID = eventID;
    if(param != NULL)
    {
        memcpy(stEvent.Param, param, sizeof(stEvent.Param));
    }
    if (__get_IPSR() != 0) 
    {
        if (xQueueSendFromISR(UIEventQueueHandle, &stEvent, &taskWoken) != pdTRUE)
        {
            return 0;
        }
        portEND_SWITCHING_ISR(taskWoken);
    }
    else 
    {        
        if (xQueueSend(UIEventQueueHandle, &stEvent, 100) != pdTRUE)
        {
            return 0;
        }
    }
    return 1;
}
void UI_Init(void)
{
    UIEventQueueHandle    = xQueueCreate(5, sizeof(ST_UIEVENT));
    osThreadDef(uiEvent, UiEventTask, osPriorityNormal, 0, 256);
    osThreadCreate(osThread(uiEvent), NULL);
//	osThreadDef(UIKey, UiTask, osPriorityNormal, 0, 128);
//	osThreadCreate(osThread(UIKey), NULL);
    HAL_NVIC_SetPriority(TIM6_IRQn, 6, 1);
    HAL_NVIC_EnableIRQ(TIM6_IRQn);
	//UI_Refresh();
    
    LCD_Clear();
//    LCD_PutText((128 - strlen(MfgInfo.ModelNo)*12)/2, 16, 24, MfgInfo.ModelNo);
    //LCD_PutText((128 - strlen(MfgInfo.ModelNo)*12)/2, 16, 24, MfgInfo.ModelNo);
    LCD_PutText((128 - strlen(MfgInfo.BT.Name)*12)/2, 16, 24, MfgInfo.BT.Name);
    LCD_PutText((128 - strlen(MfgInfo.SerialNo)*12)/2, 40, 24, "%s", MfgInfo.SerialNo);
    UiTitleRefresh();
//    LCD_PutImageR(0, 0, ICON_BTConn[0], 0);
//    LCD_PutImageR(16, 0, ICON_Setting, 0);
//    LCD_PutImageR(32, 0, ICON_PHOpen, 0);
//    LCD_PutImageR(48, 0, ICON_NoPaper, 0);
//    LCD_PutImageR(64, 0, ICON_USBConn, 0);
//    LCD_PutImageR(80, 0, ICON_DcConn, 0);
//    LCD_PutImageR(96, 0, ICON_BatLevel[2], 0);
    __HAL_TIM_SET_COUNTER(&htimUI, 0);
    HAL_TIM_Base_Start_IT(&htimUI);
}
























//                       UI.h

 
/****************************************************************************
 * File Name: UI.h
 *
 * Description:
 *					UI
 *
 * --------------------------------------------------------------------
 * Revision	Author		Date		Comment
 * --------------------------------------------------------------------
 * 1.0          Junrong         2019/12/02		Original
 *
 *****************************************************************************/
#ifndef __UI_H__
#define __UI_H__
#include "stm32f1xx_hal.h"
#include "Types.h"

enum
{
	ENUM_MENU_SERIAL,
	ENUM_MENU_SW_VER,
	ENUM_MENU_PRINT_TEST,
	ENUM_MENU_LANGUAGE,
	ENUM_MENU_DENSITY,
	ENUM_MENU_SPEED,
	ENUM_MENU_DISTANCE,
#ifdef MODEL_PT68DC
	ENUM_MENU_UHF_TXPOWER,
#endif
	ENUM_MENU_AUTO_SHUTDOWN,
	ENUM_MENU_PAPER_TYPE,
	ENUM_MENU_POSITION,
	ENUM_MENU_FACTORY_DEFAULT,	
	ENUM_MENU_MAC_ADDRESS,
//	ENUM_MENU_DENSITY_COMP,
//	ENUM_MENU_VOLTAGE_COMP,
//	ENUM_MENU_TEMP_COMP,
	ENUM_MENU_COUNT,
};

typedef BYTE ENUM_MENU;
enum
{
    UI_MODE_MAIN,
    UI_MODE_MENU,
    UI_MODE_ALERT,
    UI_MODE_PRINTING,
    UI_MODE_DETECTING,
    UI_MODE_UPGRADING,
};
typedef BYTE ENUM_UI_MODE;

typedef struct
{
    ENUM_UI_MODE    Mode;
    ENUM_MENU       Menu;
    UINT32          IdleTime;
    BOOL            IdleFlag;
}ST_UI_STATUS;

extern ST_UI_STATUS UIStatus;
enum
{
    UIEVENT_IDLE_TIMEOUT,
    UIEVENT_SHUTDOWN,
    UIEVENT_HEAT_OPEN,
    UIEVENT_HEAT_CLOSE,
    UIEVENT_SYSTEM_STATUS_CHANGE,
    UIEVENT_BATTERY_LV_CHANGE,
    UIEVENT_NO_PAPER,
    UIEVENT_BATTERY_LOW,
    UIEVENT_BATTERY_LOW_RESUME,
    UIEVENT_NO_RIBBON,
    UIEVENT_PRINTING,
    UIEVENT_DETECTING,
    UIEVENT_PRINT_DONE,
    UIEVENT_PRINT_PAUSE,
    UIEVENT_PRINT_RESUME,
    UIEVENT_PRINT_ABORT,
    UIEVENT_CALIBRATION_DONE,
    UIEVENT_UPGRADING,
};
typedef BYTE ENUM_UIEVENT;
typedef struct
{
    ENUM_UIEVENT EventID;
    BYTE         Param[8];
}ST_UIEVENT;

void UI_Init(void);
BOOL UI_SendEvent(ENUM_UIEVENT eventID, void *param);
void UI_Alert(const char *msg);
void UI_Refresh(void);
void UI_ClearIdle(void);
#endif

























//                              usb_device.c 


/**
  ******************************************************************************
  * @file           : usb_device.c
  * @version        : v2.0_Cube
  * @brief          : This file implements the USB Device
  ******************************************************************************
  * This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * Copyright (c) 2020 STMicroelectronics International N.V. 
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without 
  * modification, are permitted, provided that the following conditions are met:
  *
  * 1. Redistribution of source code must retain the above copyright notice, 
  *    this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright notice,
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. Neither the name of STMicroelectronics nor the names of other 
  *    contributors to this software may be used to endorse or promote products 
  *    derived from this software without specific written permission.
  * 4. This software, including modifications and/or derivative works of this 
  *    software, must execute solely and exclusively on microcontroller or
  *    microprocessor devices manufactured by or for STMicroelectronics.
  * 5. Redistribution and use of this software other than as permitted under 
  *    this license is void and will automatically terminate your rights under 
  *    this license. 
  *
  * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" 
  * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT 
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
  * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT 
  * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/

#include "usb_device.h"
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_cdc.h"
#include "usbd_cdc_if.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USB Device Core handle declaration. */
USBD_HandleTypeDef hUsbDeviceFS;

/*
 * -- Insert your variables declaration here --
 */
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/*
 * -- Insert your external function declaration here --
 */
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/**
  * Init USB device Library, add supported class and start the library
  * @retval None
  */
void MX_USB_DEVICE_Init(void)
{
  /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
  
  /* USER CODE END USB_DEVICE_Init_PreTreatment */
  
  /* Init Device Library, add supported class and start the library. */
  USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);

  USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);

  USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);

  USBD_Start(&hUsbDeviceFS);

  /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */
  
  /* USER CODE END USB_DEVICE_Init_PostTreatment */
}

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


























//                           usbd_cdc_if.c


/**
  ******************************************************************************
  * @file           : usbd_cdc_if.c
  * @version        : v2.0_Cube
  * @brief          : Usb device for Virtual Com Port.
  ******************************************************************************
  * This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * Copyright (c) 2020 STMicroelectronics International N.V. 
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without 
  * modification, are permitted, provided that the following conditions are met:
  *
  * 1. Redistribution of source code must retain the above copyright notice, 
  *    this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright notice,
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. Neither the name of STMicroelectronics nor the names of other 
  *    contributors to this software may be used to endorse or promote products 
  *    derived from this software without specific written permission.
  * 4. This software, including modifications and/or derivative works of this 
  *    software, must execute solely and exclusively on microcontroller or
  *    microprocessor devices manufactured by or for STMicroelectronics.
  * 5. Redistribution and use of this software other than as permitted under 
  *    this license is void and will automatically terminate your rights under 
  *    this license. 
  *
  * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" 
  * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT 
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
  * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT 
  * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "usbd_cdc_if.h"
#include "Types.h"

/* USER CODE BEGIN INCLUDE */

/* USER CODE END INCLUDE */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
  * @brief Usb device library.
  * @{
  */

/** @addtogroup USBD_CDC_IF
  * @{
  */

/** @defgroup USBD_CDC_IF_Private_TypesDefinitions USBD_CDC_IF_Private_TypesDefinitions
  * @brief Private types.
  * @{
  */

/* USER CODE BEGIN PRIVATE_TYPES */

/* USER CODE END PRIVATE_TYPES */

/**
  * @}
  */

/** @defgroup USBD_CDC_IF_Private_Defines USBD_CDC_IF_Private_Defines
  * @brief Private defines.
  * @{
  */

/* USER CODE BEGIN PRIVATE_DEFINES */
/* Define size for the receive and transmit buffer over CDC */
/* It's up to user to redefine and/or remove those define */
#define APP_RX_DATA_SIZE  1024
#define APP_TX_DATA_SIZE  1024
/* USER CODE END PRIVATE_DEFINES */

/**
  * @}
  */

/** @defgroup USBD_CDC_IF_Private_Macros USBD_CDC_IF_Private_Macros
  * @brief Private macros.
  * @{
  */

/* USER CODE BEGIN PRIVATE_MACRO */

/* USER CODE END PRIVATE_MACRO */

/**
  * @}
  */

/** @defgroup USBD_CDC_IF_Private_Variables USBD_CDC_IF_Private_Variables
  * @brief Private variables.
  * @{
  */
/* Create buffer for reception and transmission           */
/* It's up to user to redefine and/or remove those define */
/** Received data over USB are stored in this buffer      */
uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];

/** Data to send over USB CDC are stored in this buffer   */
uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];

/* USER CODE BEGIN PRIVATE_VARIABLES */

/* USER CODE END PRIVATE_VARIABLES */

/**
  * @}
  */

/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables
  * @brief Public variables.
  * @{
  */

extern USBD_HandleTypeDef hUsbDeviceFS;

/* USER CODE BEGIN EXPORTED_VARIABLES */

/* USER CODE END EXPORTED_VARIABLES */

/**
  * @}
  */

/** @defgroup USBD_CDC_IF_Private_FunctionPrototypes USBD_CDC_IF_Private_FunctionPrototypes
  * @brief Private functions declaration.
  * @{
  */

static int8_t CDC_Init_FS(void);
static int8_t CDC_DeInit_FS(void);
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t *length);
static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len);

/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */

/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */

/**
  * @}
  */

USBD_CDC_ItfTypeDef USBD_Interface_fops_FS =
{
  CDC_Init_FS,
  CDC_DeInit_FS,
  CDC_Control_FS,
  CDC_Receive_FS
};

/* Private functions ---------------------------------------------------------*/
/**
  * @brief  Initializes the CDC media low layer over the FS USB IP
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
static int8_t CDC_Init_FS(void)
{
  /* USER CODE BEGIN 3 */
  /* Set Application Buffers */
  USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);
  return (USBD_OK);
  /* USER CODE END 3 */
}

/**
  * @brief  DeInitializes the CDC media low layer
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
static int8_t CDC_DeInit_FS(void)
{
  /* USER CODE BEGIN 4 */
  return (USBD_OK);
  /* USER CODE END 4 */
}

/**
  * @brief  Manage the CDC class requests
  * @param  cmd: Command code
  * @param  pbuf: Buffer containing command data (request parameters)
  * @param  length: Number of data to be sent (in bytes)
  * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
  */
#define PRINT_DEVICE_ID "MFG:PUTY;CMD:EPSON;CLS:PRINTER;"
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t *length)
{
  /* USER CODE BEGIN 5 */
    switch(cmd)
    {
        case PRINTER_GET_DEVICE_ID:
        {
            uint16_t devLen = strlen(PRINT_DEVICE_ID);
            pbuf[0] = (uint8_t)(devLen >> 8);
            pbuf[1] = (uint8_t)(devLen);
            strcpy((char *)&pbuf[2], PRINT_DEVICE_ID);     
            *length = devLen + 2;
            break;
        }
        case PRINTER_GET_PORT_STATUS:
            pbuf[0] = 0x18;
//            if(GetTapeSize() == TAPE_SIZE_NONE)
//            {
//                pbuf[0] |= 0x20;
//            }
            *length = 1;
            // 0-2:Reserved, 3:NotError, 4:Select, 5:PaperEmpty, 6-7:Reserved
            break;
        case PRINTER_SOFT_RESET:
 //           HAL_NVIC_SystemReset();
            break;
        default:
            break;
    }

    return (USBD_OK);
    /* USER CODE END 5 */
}

void USB_Send(BYTE *pBuf, UINT16 len)
{
    CDC_Transmit_FS(pBuf, len);
}
void USB_EndReceive(void)
{    
    USBD_CDC_ReceivePacket(&hUsbDeviceFS);
}
__weak void USB_ReceiveISR(BYTE *pBuf, UINT16 len)
{
    USB_EndReceive();
}
/**
  * @brief  Data received over USB OUT endpoint are sent over CDC interface
  *         through this function.
  *
  *         @note
  *         This function will block any OUT packet reception on USB endpoint
  *         untill exiting this function. If you exit this function before transfer
  *         is complete on CDC interface (ie. using DMA controller) it will result
  *         in receiving more data while previous ones are still not sent.
  *
  * @param  Buf: Buffer of data to be received
  * @param  Len: Number of data received (in bytes)
  * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL
  */
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
    USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
    USB_ReceiveISR(Buf, *Len);
    //USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
  /* USER CODE END 6 */
}

/**
  * @brief  CDC_Transmit_FS
  *         Data to send over USB IN endpoint are sent over CDC interface
  *         through this function.
  *         @note
  *
  *
  * @param  Buf: Buffer of data to be sent
  * @param  Len: Number of data to be sent (in bytes)
  * @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY
  */
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
  uint8_t result = USBD_OK;
  /* USER CODE BEGIN 7 */
  USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
  if (hcdc->TxState != 0){
    return USBD_BUSY;
  }
  USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
  result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
  /* USER CODE END 7 */
  return result;
}

/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */

/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

























//              usbd_conf.c


/**
  ******************************************************************************
  * @file           : usbd_conf.c
  * @version        : v2.0_Cube
  * @brief          : This file implements the board support package for the USB device library
  ******************************************************************************
  * This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * Copyright (c) 2020 STMicroelectronics International N.V. 
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without 
  * modification, are permitted, provided that the following conditions are met:
  *
  * 1. Redistribution of source code must retain the above copyright notice, 
  *    this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright notice,
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. Neither the name of STMicroelectronics nor the names of other 
  *    contributors to this software may be used to endorse or promote products 
  *    derived from this software without specific written permission.
  * 4. This software, including modifications and/or derivative works of this 
  *    software, must execute solely and exclusively on microcontroller or
  *    microprocessor devices manufactured by or for STMicroelectronics.
  * 5. Redistribution and use of this software other than as permitted under 
  *    this license is void and will automatically terminate your rights under 
  *    this license. 
  *
  * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" 
  * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT 
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
  * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT 
  * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "usbd_def.h"
#include "usbd_core.h"
#include "usbd_cdc.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

                PCD_HandleTypeDef hpcd_USB_FS;
void _Error_Handler(char * file, int line);

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* Private functions ---------------------------------------------------------*/

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state);

/*******************************************************************************
                       LL Driver Callbacks (PCD -> USB Device Library)
*******************************************************************************/
/* MSP Init */

void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
{
  if(pcdHandle->Instance==USB)
  {
  /* USER CODE BEGIN USB_MspInit 0 */

  /* USER CODE END USB_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USB_CLK_ENABLE();

    /* Peripheral interrupt init */
    HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
  /* USER CODE BEGIN USB_MspInit 1 */

  /* USER CODE END USB_MspInit 1 */
  }
}

void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle)
{
  if(pcdHandle->Instance==USB)
  {
  /* USER CODE BEGIN USB_MspDeInit 0 */

  /* USER CODE END USB_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USB_CLK_DISABLE();

    /* Peripheral interrupt Deinit*/
    HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);

  /* USER CODE BEGIN USB_MspDeInit 1 */

  /* USER CODE END USB_MspDeInit 1 */
  }
}

/**
  * @brief  Setup stage callback
  * @param  hpcd: PCD handle
  * @retval None
  */
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
{
  USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup);
}

/**
  * @brief  Data Out stage callback.
  * @param  hpcd: PCD handle
  * @param  epnum: Endpoint number
  * @retval None
  */
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
  USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
}

/**
  * @brief  Data In stage callback.
  * @param  hpcd: PCD handle
  * @param  epnum: Endpoint number
  * @retval None
  */
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
  USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff);
}

/**
  * @brief  SOF callback.
  * @param  hpcd: PCD handle
  * @retval None
  */
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
{
  USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData);
}

/**
  * @brief  Reset callback.
  * @param  hpcd: PCD handle
  * @retval None
  */
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
{ 
  USBD_SpeedTypeDef speed = USBD_SPEED_FULL;

  /* Set USB current speed. */
  switch (hpcd->Init.speed)
  {
  case PCD_SPEED_FULL:
    speed = USBD_SPEED_FULL;
    break;
	
  default:
    speed = USBD_SPEED_FULL;
    break;    
  }
  USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);
  
  /* Reset Device. */
  USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
}

/**
  * @brief  Suspend callback.
  * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
  * @param  hpcd: PCD handle
  * @retval None
  */
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
{
  /* Inform USB library that core enters in suspend Mode. */
  USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData);
  /* Enter in STOP mode. */
  /* USER CODE BEGIN 2 */
  if (hpcd->Init.low_power_enable)
  {
    /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */
    SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
  }
  /* USER CODE END 2 */
}

/**
  * @brief  Resume callback.
  * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it)
  * @param  hpcd: PCD handle
  * @retval None
  */
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
{
  /* USER CODE BEGIN 3 */

  /* USER CODE END 3 */
  USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData);
}

/**
  * @brief  ISOOUTIncomplete callback.
  * @param  hpcd: PCD handle
  * @param  epnum: Endpoint number
  * @retval None
  */
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
  USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}

/**
  * @brief  ISOINIncomplete callback.
  * @param  hpcd: PCD handle
  * @param  epnum: Endpoint number
  * @retval None
  */
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
  USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum);
}

/**
  * @brief  Connect callback.
  * @param  hpcd: PCD handle
  * @retval None
  */
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
{
  USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData);
}

/**
  * @brief  Disconnect callback.
  * @param  hpcd: PCD handle
  * @retval None
  */
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
{
  USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
}

/*******************************************************************************
                       LL Driver Interface (USB Device Library --> PCD)
*******************************************************************************/

/**
  * @brief  Initializes the low level portion of the device driver.
  * @param  pdev: Device handle
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
  /* Init USB Ip. */
  /* Link the driver to the stack. */
  hpcd_USB_FS.pData = pdev;
  pdev->pData = &hpcd_USB_FS;

  hpcd_USB_FS.Instance = USB;
  hpcd_USB_FS.Init.dev_endpoints = 8;
  hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
  hpcd_USB_FS.Init.ep0_mps = DEP0CTL_MPS_8;
  hpcd_USB_FS.Init.low_power_enable = DISABLE;
  hpcd_USB_FS.Init.lpm_enable = DISABLE;
  hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
  if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);
  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0xC0);
  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0x110);
  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82 , PCD_SNG_BUF, 0x100);
  return USBD_OK;
}

/**
  * @brief  De-Initializes the low level portion of the device driver.
  * @param  pdev: Device handle
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;

  hal_status = HAL_PCD_DeInit(pdev->pData);

  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status; 
}

/**
  * @brief  Starts the low level portion of the device driver.
  * @param  pdev: Device handle
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;
 
  hal_status = HAL_PCD_Start(pdev->pData);
     
  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status;
}

/**
  * @brief  Stops the low level portion of the device driver.
  * @param  pdev: Device handle
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;

  hal_status = HAL_PCD_Stop(pdev->pData);

  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status;
}

/**
  * @brief  Opens an endpoint of the low level driver.
  * @param  pdev: Device handle
  * @param  ep_addr: Endpoint number
  * @param  ep_type: Endpoint type
  * @param  ep_mps: Endpoint max packet size
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;

  hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type);

  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status;
}

/**
  * @brief  Closes an endpoint of the low level driver.
  * @param  pdev: Device handle
  * @param  ep_addr: Endpoint number
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;
  
  hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr);
      
  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status;  
}

/**
  * @brief  Flushes an endpoint of the Low Level Driver.
  * @param  pdev: Device handle
  * @param  ep_addr: Endpoint number
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;
  
  hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr);
      
  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status;  
}

/**
  * @brief  Sets a Stall condition on an endpoint of the Low Level Driver.
  * @param  pdev: Device handle
  * @param  ep_addr: Endpoint number
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;
  
  hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr);

  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status;  
}

/**
  * @brief  Clears a Stall condition on an endpoint of the Low Level Driver.
  * @param  pdev: Device handle
  * @param  ep_addr: Endpoint number
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;
  
  hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr);  
     
  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status; 
}

/**
  * @brief  Returns Stall condition.
  * @param  pdev: Device handle
  * @param  ep_addr: Endpoint number
  * @retval Stall (1: Yes, 0: No)
  */
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
  PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData;
  
  if((ep_addr & 0x80) == 0x80)
  {
    return hpcd->IN_ep[ep_addr & 0x7F].is_stall; 
  }
  else
  {
    return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; 
  }
}

/**
  * @brief  Assigns a USB address to the device.
  * @param  pdev: Device handle
  * @param  dev_addr: Device address
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;
  
  hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr);
     
  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status;  
}

/**
  * @brief  Transmits data over an endpoint.
  * @param  pdev: Device handle
  * @param  ep_addr: Endpoint number
  * @param  pbuf: Pointer to data to be sent
  * @param  size: Data size    
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;

  hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size);
     
  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status;    
}

/**
  * @brief  Prepares an endpoint for reception.
  * @param  pdev: Device handle
  * @param  ep_addr: Endpoint number
  * @param  pbuf: Pointer to data to be received
  * @param  size: Data size
  * @retval USBD status
  */
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size)
{
  HAL_StatusTypeDef hal_status = HAL_OK;
  USBD_StatusTypeDef usb_status = USBD_OK;

  hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size);
     
  switch (hal_status) {
    case HAL_OK :
      usb_status = USBD_OK;
    break;
    case HAL_ERROR :
      usb_status = USBD_FAIL;
    break;
    case HAL_BUSY :
      usb_status = USBD_BUSY;
    break;
    case HAL_TIMEOUT :
      usb_status = USBD_FAIL;
    break;
    default :
      usb_status = USBD_FAIL;
    break;
  }
  return usb_status; 
}

/**
  * @brief  Returns the last transfered packet size.
  * @param  pdev: Device handle
  * @param  ep_addr: Endpoint number
  * @retval Recived Data Size
  */
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr)
{
  return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr);
}

/**
  * @brief  Delays routine for the USB device library.
  * @param  Delay: Delay in ms
  * @retval None
  */
void USBD_LL_Delay(uint32_t Delay)
{
  HAL_Delay(Delay);
}

/**
  * @brief  Static single allocation.
  * @param  size: Size of allocated memory
  * @retval None
  */
void *USBD_static_malloc(uint32_t size)
{
  static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* On 32-bit boundary */
  return mem;
}

/**
  * @brief  Dummy memory free
  * @param  p: Pointer to allocated  memory address
  * @retval None
  */
void USBD_static_free(void *p)
{

}

/**
  * @brief Software Device Connection
  * @param hpcd: PCD handle
  * @param state: Connection state (0: disconnected / 1: connected)
  * @retval None
  */
void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state)
{
  /* USER CODE BEGIN 6 */
  if (state == 1)
  {
    /* Configure Low connection state. */

  }
  else
  {
    /* Configure High connection state. */

  }
  /* USER CODE END 6 */
}

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


























//                                           usbd_desc.c

/**
  ******************************************************************************
  * @file           : usbd_desc.c
  * @version        : v2.0_Cube
  * @brief          : This file implements the USB device descriptors.
  ******************************************************************************
  * This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * Copyright (c) 2020 STMicroelectronics International N.V. 
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without 
  * modification, are permitted, provided that the following conditions are met:
  *
  * 1. Redistribution of source code must retain the above copyright notice, 
  *    this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright notice,
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. Neither the name of STMicroelectronics nor the names of other 
  *    contributors to this software may be used to endorse or promote products 
  *    derived from this software without specific written permission.
  * 4. This software, including modifications and/or derivative works of this 
  *    software, must execute solely and exclusively on microcontroller or
  *    microprocessor devices manufactured by or for STMicroelectronics.
  * 5. Redistribution and use of this software other than as permitted under 
  *    this license is void and will automatically terminate your rights under 
  *    this license. 
  *
  * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" 
  * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT 
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
  * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT 
  * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_conf.h"

/* USER CODE BEGIN INCLUDE */

/* USER CODE END INCLUDE */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
  * @{
  */

/** @addtogroup USBD_DESC
  * @{
  */

/** @defgroup USBD_DESC_Private_TypesDefinitions USBD_DESC_Private_TypesDefinitions
  * @brief Private types.
  * @{
  */

/* USER CODE BEGIN PRIVATE_TYPES */

/* USER CODE END PRIVATE_TYPES */

/**
  * @}
  */

/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines
  * @brief Private defines.
  * @{
  */

#define USBD_VID                        0x0483
#define USBD_LANGID_STRING              1033
#define USBD_MANUFACTURER_STRING        "PUTY"
#define USBD_PID_FS                     0x5720
#define USBD_PRODUCT_STRING_FS          "PUTY Printer"
#define USBD_SERIALNUMBER_STRING_FS     "11101800002"
#define USBD_CONFIGURATION_STRING_FS    "Printer Config"
#define USBD_INTERFACE_STRING_FS        "Printer Interface"

#define USB_SIZ_BOS_DESC            0x0C

/* USER CODE BEGIN PRIVATE_DEFINES */

/* USER CODE END PRIVATE_DEFINES */

/**
  * @}
  */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/** @defgroup USBD_DESC_Private_Macros USBD_DESC_Private_Macros
  * @brief Private macros.
  * @{
  */

/* USER CODE BEGIN PRIVATE_MACRO */

/* USER CODE END PRIVATE_MACRO */

/**
  * @}
  */

/** @defgroup USBD_DESC_Private_FunctionPrototypes USBD_DESC_Private_FunctionPrototypes
  * @brief Private functions declaration.
  * @{
  */

uint8_t * USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t * USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);

#ifdef USB_SUPPORT_USER_STRING_DESC
uint8_t * USBD_FS_USRStringDesc(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
#endif /* USB_SUPPORT_USER_STRING_DESC */

/**
  * @}
  */

/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
  * @brief Private variables.
  * @{
  */

USBD_DescriptorsTypeDef FS_Desc =
{
  USBD_FS_DeviceDescriptor
, USBD_FS_LangIDStrDescriptor
, USBD_FS_ManufacturerStrDescriptor
, USBD_FS_ProductStrDescriptor
, USBD_FS_SerialStrDescriptor
, USBD_FS_ConfigStrDescriptor
, USBD_FS_InterfaceStrDescriptor
};

#if defined ( __ICCARM__ ) /* IAR Compiler */
  #pragma data_alignment=4
#endif /* defined ( __ICCARM__ ) */
/** USB standard device descriptor. */
__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
{
  0x12,                       /*bLength */
  USB_DESC_TYPE_DEVICE,       /*bDescriptorType*/
  0x00,                       /*bcdUSB */
  0x02,
  0x00,                       /*bDeviceClass*/
  0x00,                       /*bDeviceSubClass*/
  0x00,                       /*bDeviceProtocol*/
  USB_MAX_EP0_SIZE,           /*bMaxPacketSize*/
  LOBYTE(USBD_VID),           /*idVendor*/
  HIBYTE(USBD_VID),           /*idVendor*/
  LOBYTE(USBD_PID_FS),        /*idProduct*/
  HIBYTE(USBD_PID_FS),        /*idProduct*/
  0x00,                       /*bcdDevice rel. 2.00*/
  0x02,
  USBD_IDX_MFC_STR,           /*Index of manufacturer  string*/
  USBD_IDX_PRODUCT_STR,       /*Index of product string*/
  USBD_IDX_SERIAL_STR,        /*Index of serial number string*/
  USBD_MAX_NUM_CONFIGURATION  /*bNumConfigurations*/
};

/* USB_DeviceDescriptor */

/**
  * @}
  */

/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables
  * @brief Private variables.
  * @{
  */

#if defined ( __ICCARM__ ) /* IAR Compiler */
  #pragma data_alignment=4
#endif /* defined ( __ICCARM__ ) */

/** USB lang indentifier descriptor. */
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END =
{
     USB_LEN_LANGID_STR_DESC,
     USB_DESC_TYPE_STRING,
     LOBYTE(USBD_LANGID_STRING),
     HIBYTE(USBD_LANGID_STRING)
};

#if defined ( __ICCARM__ ) /* IAR Compiler */
  #pragma data_alignment=4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;

/**
  * @}
  */

/** @defgroup USBD_DESC_Private_Functions USBD_DESC_Private_Functions
  * @brief Private functions.
  * @{
  */

/**
  * @brief  Return the device descriptor
  * @param  speed : Current device speed
  * @param  length : Pointer to data length variable
  * @retval Pointer to descriptor buffer
  */
uint8_t * USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
  *length = sizeof(USBD_FS_DeviceDesc);
  return USBD_FS_DeviceDesc;
}

/**
  * @brief  Return the LangID string descriptor
  * @param  speed : Current device speed
  * @param  length : Pointer to data length variable
  * @retval Pointer to descriptor buffer
  */
uint8_t * USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
  *length = sizeof(USBD_LangIDDesc);
  return USBD_LangIDDesc;
}

/**
  * @brief  Return the product string descriptor
  * @param  speed : Current device speed
  * @param  length : Pointer to data length variable
  * @retval Pointer to descriptor buffer
  */
uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
  if(speed == 0)
  {
    USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
  }
  else
  {
    USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length);
  }
  return USBD_StrDesc;
}

/**
  * @brief  Return the manufacturer string descriptor
  * @param  speed : Current device speed
  * @param  length : Pointer to data length variable
  * @retval Pointer to descriptor buffer
  */
uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
  USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
  return USBD_StrDesc;
}

/**
  * @brief  Return the serial number string descriptor
  * @param  speed : Current device speed
  * @param  length : Pointer to data length variable
  * @retval Pointer to descriptor buffer
  */
uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
  if(speed == USBD_SPEED_HIGH)
  {
    USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
  }
  else
  {
    USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
  }
  return USBD_StrDesc;
}

/**
  * @brief  Return the configuration string descriptor
  * @param  speed : Current device speed
  * @param  length : Pointer to data length variable
  * @retval Pointer to descriptor buffer
  */
uint8_t * USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
  if(speed == USBD_SPEED_HIGH)
  {
    USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
  }
  else
  {
    USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length);
  }
  return USBD_StrDesc;
}

/**
  * @brief  Return the interface string descriptor
  * @param  speed : Current device speed
  * @param  length : Pointer to data length variable
  * @retval Pointer to descriptor buffer
  */
uint8_t * USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
  if(speed == 0)
  {
    USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length);
  }
  else
  {
    USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length);
  }
  return USBD_StrDesc;
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


                               

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值