Library for virtual onscreen keyboard for STM32F746 Disco board

Dependencies:   BSP_DISCO_F746NG mbed

user/keyboard.c

Committer:
Faberge
Date:
2016-09-17
Revision:
0:3ea368f65bca

File content as of revision 0:3ea368f65bca:

/*
 *******************************************************************************
 * Библиотека Keyboard виртуальной клавиатуры для дисплея с тач-экраном на демо-
 * плате STM32F746NG Discovery
 *
 * Файл "keyboard.c"
 *******************************************************************************
 */  

/* Добавляем заголовочный файл */
#include "keyboard.h"

/* Структуры клаватуры и тач-экрана */
Keyboard_TypeDef keyboard;
TS_StateTypeDef tScreen;

/* Функции для работы с экранной клавиатурой */

/* Инициализация и вывод клавиатуры на дисплей */
uint8_t Keyboard_init(uint16_t  x_value, uint16_t   y_value)
{
    uint8_t i;
    
    /* Координаты верхнего левого угла клавиатуры на экране, служат точкой
     * отсчета для определения расположения всех остальных элементов
     */
    keyboard.posX = x_value;
    keyboard.posY = y_value;
    
    /* По умолчанию на клавиатуре английская раскладка в верхнем регистре */
    keyboard.mode = MODE_UPPER_CASE;
    
    /* Блок инициализации для стандартных клавиш */
    
    /* Инициализируем массив координат клавиш на клавиатуре для верхнего ряда */
    for (i = 0; i < 10; i++)
    {
        keyboard.key[i].id = i;
        keyboard.key[i].posX = keyboard.posX + 3 + (KEY_DISTANCE + KEY_SMALL_LENGTH) * i;
        keyboard.key[i].posY = keyboard.posY + 3;
        keyboard.key[i].dimX = KEY_SMALL_LENGTH;
        keyboard.key[i].dimY = KEY_SMALL_HEIGHT;
        keyboard.key[i].status = KEY_RELEASED; 
    }
    
    /* Значения ASCII-кодов каждой клавишы из верхнего ряда для различных 
     * раскладок клавиатуры 
     */
    keyboard.key[0].value[0] = 'Q';
    keyboard.key[0].value[1] = 'q';
    keyboard.key[0].value[2] = '1';
    
    keyboard.key[1].value[0] = 'W';
    keyboard.key[1].value[1] = 'w';
    keyboard.key[1].value[2] = '2';
    
    keyboard.key[2].value[0] = 'E';
    keyboard.key[2].value[1] = 'e';
    keyboard.key[2].value[2] = '3';
    
    keyboard.key[3].value[0] = 'R';
    keyboard.key[3].value[1] = 'r';
    keyboard.key[3].value[2] = '4';
    
    keyboard.key[4].value[0] = 'T';
    keyboard.key[4].value[1] = 't';
    keyboard.key[4].value[2] = '5';
    
    keyboard.key[5].value[0] = 'Y';
    keyboard.key[5].value[1] = 'y';
    keyboard.key[5].value[2] = '6';
    
    keyboard.key[6].value[0] = 'U';
    keyboard.key[6].value[1] = 'u';
    keyboard.key[6].value[2] = '7';
    
    keyboard.key[7].value[0] = 'I';
    keyboard.key[7].value[1] = 'i';
    keyboard.key[7].value[2] = '8';
    
    keyboard.key[8].value[0] = 'O';
    keyboard.key[8].value[1] = 'o';
    keyboard.key[8].value[2] = '9';
    
    keyboard.key[9].value[0] = 'P';
    keyboard.key[9].value[1] = 'p';
    keyboard.key[9].value[2] = '0';
    
    /* Инициализируем массив координат клавиш на клавиатуре для среднего ряда */  
    for (i = 10; i < 19; i++)
    {
        keyboard.key[i].id = i;
        keyboard.key[i].posX = keyboard.posX + 27 + (KEY_DISTANCE + KEY_SMALL_LENGTH) * (i - 10);
        keyboard.key[i].posY = keyboard.posY + 3 + KEY_SMALL_HEIGHT + KEY_DISTANCE;
        keyboard.key[i].dimX = KEY_SMALL_LENGTH;
        keyboard.key[i].dimY = KEY_SMALL_HEIGHT;
        keyboard.key[i].status = KEY_RELEASED; 
    }
    
    /* Значения ASCII-кодов каждой клавишы из среднего ряда для различных
     * раскладок клавиатуры
     */
    keyboard.key[10].value[0] = 'A';
    keyboard.key[10].value[1] = 'a';
    keyboard.key[10].value[2] = '1';
    
    keyboard.key[11].value[0] = 'S';
    keyboard.key[11].value[1] = 's';
    keyboard.key[11].value[2] = '2';
    
    keyboard.key[12].value[0] = 'D';
    keyboard.key[12].value[1] = 'd';
    keyboard.key[12].value[2] = '3';
    
    keyboard.key[13].value[0] = 'F';
    keyboard.key[13].value[1] = 'f';
    keyboard.key[13].value[2] = '4';
    
    keyboard.key[14].value[0] = 'G';
    keyboard.key[14].value[1] = 'g';
    keyboard.key[14].value[2] = '5';
    
    keyboard.key[15].value[0] = 'H';
    keyboard.key[15].value[1] = 'h';
    keyboard.key[15].value[2] = '6';
    
    keyboard.key[16].value[0] = 'J';
    keyboard.key[16].value[1] = 'j';
    keyboard.key[16].value[2] = '7';
    
    keyboard.key[17].value[0] = 'K';
    keyboard.key[17].value[1] = 'k';
    keyboard.key[17].value[2] = '8';
    
    keyboard.key[18].value[0] = 'L';
    keyboard.key[18].value[1] = 'l';
    keyboard.key[18].value[2] = '9';
    
    /* Инициализируем массив координат клавиш на клавиатуре для нижнего ряда */    
    for (i = 19; i < 26; i++)
    {
        keyboard.key[i].id = i;
        keyboard.key[i].posX = keyboard.posX + 51 + (KEY_DISTANCE + KEY_SMALL_LENGTH) * (i - 19);
        keyboard.key[i].posY = keyboard.posY + 3 + (KEY_SMALL_HEIGHT + KEY_DISTANCE) * 2;
        keyboard.key[i].dimX = KEY_SMALL_LENGTH;
        keyboard.key[i].dimY = KEY_SMALL_HEIGHT;
        keyboard.key[i].status = KEY_RELEASED;
    }
    
    /* Значения ASCII-кодов каждой клавишы из нижнего ряда для различных
     * раскладок лавиатуры
     */
    keyboard.key[19].value[0] = 'Z';
    keyboard.key[19].value[1] = 'z';
    keyboard.key[19].value[2] = '1';
    
    keyboard.key[20].value[0] = 'X';
    keyboard.key[20].value[1] = 'x';
    keyboard.key[20].value[2] = '2';
    
    keyboard.key[21].value[0] = 'C';
    keyboard.key[21].value[1] = 'c';
    keyboard.key[21].value[2] = '3';
    
    keyboard.key[22].value[0] = 'V';
    keyboard.key[22].value[1] = 'v';
    keyboard.key[22].value[2] = '4';
    
    keyboard.key[23].value[0] = 'B';
    keyboard.key[23].value[1] = 'b';
    keyboard.key[23].value[2] = '5';
    
    keyboard.key[24].value[0] = 'N';
    keyboard.key[24].value[1] = 'n';
    keyboard.key[24].value[2] = '6';
    
    keyboard.key[25].value[0] = 'M';
    keyboard.key[25].value[1] = 'm';
    keyboard.key[25].value[2] = '7';
    
    /* Блок инициализации для специальных клавиш */
    
    /* Клавиша "Enter" */
    keyboard.key[26].id = 26;
    keyboard.key[26].posX = 51 + (KEY_DISTANCE + KEY_SMALL_LENGTH) * 7;
    keyboard.key[26].posY = keyboard.posY + 3 + (KEY_SMALL_HEIGHT + KEY_DISTANCE) * 2;
    keyboard.key[26].dimX = KEY_ENTER_LENGTH;
    keyboard.key[26].dimY = KEY_SMALL_HEIGHT;
    keyboard.key[26].status = KEY_RELEASED;
    keyboard.key[26].value[0] = KEY_ENTER_VALUE;
    keyboard.key[26].value[1] = KEY_ENTER_VALUE;
    keyboard.key[26].value[2] = KEY_ENTER_VALUE;
    
    /* Клавиша "Shift" */
    keyboard.key[27].id = 27;
    keyboard.key[27].posX = 3;
    keyboard.key[27].posY = keyboard.posY + 3 + (KEY_SMALL_HEIGHT + KEY_DISTANCE) * 3;
    keyboard.key[27].dimX = KEY_SHIFT_LENGTH;
    keyboard.key[27].dimY = KEY_SMALL_HEIGHT;
    keyboard.key[27].status = KEY_RELEASED;
    keyboard.key[27].value[0] = KEY_SHIFT_VALUE;
    keyboard.key[27].value[1] = KEY_SHIFT_VALUE;
    keyboard.key[27].value[2] = KEY_SHIFT_VALUE;
    
    /* Клавиша "Space" */
    keyboard.key[28].id = 28;
    keyboard.key[28].posX = 27 + (KEY_SMALL_LENGTH + KEY_DISTANCE) * 3;
    keyboard.key[28].posY = keyboard.posY + 3 + (KEY_SMALL_HEIGHT + KEY_DISTANCE) * 3;
    keyboard.key[28].dimX = KEY_SPACE_LENGTH;
    keyboard.key[28].dimY = KEY_SMALL_HEIGHT;
    keyboard.key[28].status = KEY_RELEASED;
    keyboard.key[28].value[0] = KEY_SPACE_VALUE;
    keyboard.key[28].value[1] = KEY_SPACE_VALUE;
    keyboard.key[28].value[2] = KEY_SPACE_VALUE;
    
    /* Клавиша "Backspace" */
    keyboard.key[29].id = 29;
    keyboard.key[29].posX = keyboard.posX + 27 + (KEY_DISTANCE + KEY_SMALL_LENGTH) * 8;
    keyboard.key[29].posY = keyboard.posY + 3 + (KEY_SMALL_HEIGHT + KEY_DISTANCE) * 3;
    keyboard.key[29].dimX = KEY_BACKSPACE_LENGTH;
    keyboard.key[29].dimY = KEY_SMALL_HEIGHT;
    keyboard.key[29].status = KEY_RELEASED;
    keyboard.key[29].value[0] = KEY_BACKSPACE_VALUE;
    keyboard.key[29].value[1] = KEY_BACKSPACE_VALUE;
    keyboard.key[29].value[2] = KEY_BACKSPACE_VALUE;
    
    /* Отрисовываем клавиатуру на экране*/
    Keyboard_display_all();
    
    return 0;
}

/* Отрисовка клавиатуры на экране */
uint8_t Keyboard_display_all(void)
{
    uint8_t i;
    
    /* Получаем значение цвета фона экрана*/
    uint32_t back_color = BSP_LCD_GetBackColor();
    
    /* Закрашиваем весь экран цветом фона*/
    BSP_LCD_Clear(back_color);

    /* Отрисовываем каждую клавишу на клавиатуре */
    for (i = 0; i < KEY_NUMBER; i++)
    {
        Key_display_normal(i);
    }
    
    return 0;
}

/* Отрисовка отдельной клавишы клавиатуры на экране */
uint8_t Key_display_normal(uint8_t id)
{
    /* Получаем значение цвета фона экрана и цвета шрифта */
    uint32_t back_color = BSP_LCD_GetBackColor();
    uint32_t text_color = BSP_LCD_GetTextColor();
    
    /* Меняем цвета и закрашиваем место для клавишы на экране цветом фона */
    BSP_LCD_SetTextColor(back_color);
    BSP_LCD_SetBackColor(text_color);               
    BSP_LCD_FillRect(keyboard.key[id].posX, keyboard.key[id].posY, keyboard.key[id].dimX, keyboard.key[id].dimY);
    
    /* Возвращаем прежние значения цвета фона экрана и цвета шрифта*/
    BSP_LCD_SetTextColor(text_color);
    BSP_LCD_SetBackColor(back_color);
    
    /* Рисуем рамку рамку вокруг клавишы и замыкающий пиксель в нижнем правом углу */
    BSP_LCD_DrawRect(keyboard.key[id].posX, keyboard.key[id].posY, keyboard.key[id].dimX, keyboard.key[id].dimY);
    BSP_LCD_DrawPixel(keyboard.key[id].posX + keyboard.key[id].dimX, keyboard.key[id].posY + keyboard.key[id].dimY, text_color);
    
    /* Выводим значение клавишы в текущей раскладке клавиатуры */
    BSP_LCD_DisplayChar(keyboard.key[id].posX + 8, keyboard.key[id].posY + 8, keyboard.key[id].value[keyboard.mode]);
    
    /* Для специальных клавиш выводим больше одного символа */
    Key_display_specials(id);
    
    return 0;
}

/* Отрисовка отдельной клавишы клавиатуры на экране (в инвертированном цвете) */
uint8_t Key_display_inverted(uint8_t id)
{
    uint32_t back_color = BSP_LCD_GetBackColor();
    uint32_t text_color = BSP_LCD_GetTextColor();
    
    /* Закрашиваем место для клавишы на экране цветом шрифта */
    BSP_LCD_FillRect(keyboard.key[id].posX, keyboard.key[id].posY, keyboard.key[id].dimX, keyboard.key[id].dimY);
    
    /* Меняем цвета и выводим значение клавишы в текущей раскладке клавиатуры */
    BSP_LCD_SetTextColor(back_color);
    BSP_LCD_SetBackColor(text_color);
    BSP_LCD_DisplayChar(keyboard.key[id].posX + 8, keyboard.key[id].posY + 8, keyboard.key[id].value[keyboard.mode]);
    
    /* Для спецмальных клавиш выводим больше одного символа */
    Key_display_specials(id);
    
    /* Возвращаем прежние значения цвета фона экрана и цвета шрифта */
    BSP_LCD_SetTextColor(text_color);
    BSP_LCD_SetBackColor(back_color);
    
    return 0;
}

/* Вывод значения специальных клавиш клавиатуры */ 
uint8_t Key_display_specials(uint8_t id)
{
    /* Клавиша "Enter" */
    if (keyboard.key[id].value[keyboard.mode] == KEY_ENTER_VALUE)
    {
        BSP_LCD_DisplayStringAt(keyboard.key[id].posX + 8, keyboard.key[id].posY + 8, (uint8_t *) "Enter", LEFT_MODE);
    }
    /* Клавиша "Shift" */
    if (keyboard.key[id].value[keyboard.mode] == KEY_SHIFT_VALUE)
    {
        BSP_LCD_DisplayStringAt(keyboard.key[id].posX + 4, keyboard.key[id].posY + 8, (uint8_t *) "Shft", LEFT_MODE);
    }
    
    /* Клаиша "Space" */
    if (keyboard.key[id].value[keyboard.mode] == KEY_SPACE_VALUE)
    {
        BSP_LCD_DisplayStringAt(keyboard.key[id].posX + 32, keyboard.key[id].posY + 8, (uint8_t *) "Space", LEFT_MODE);
    }
    
    /* Клавиша "Backspace" */
    if (keyboard.key[id].value[keyboard.mode] == KEY_BACKSPACE_VALUE)
    {
        BSP_LCD_DisplayStringAt(keyboard.key[id].posX + 4, keyboard.key[id].posY + 8, (uint8_t *) "Bspc", LEFT_MODE);
    }
    
    return 0;
}

/* Проверка ввода на экранной клавиатуре */
uint8_t Keyboard_check(void)
{
    uint8_t i;
    uint8_t j;
    
    /* Проверяем состояния драйвера тач-экрана */
    BSP_TS_GetState(&tScreen);
    
    /* Если произошло касание */
    if (tScreen.touchDetected)
    {
        for (i = 0; i < KEY_NUMBER; i++)
        {
            /* Если координаты касания лежат в границах какой-либо из ненажатых кнопок +/- 4 пикселя */
            if (((tScreen.touchX[0] >= keyboard.key[i].posX - 4) && (tScreen.touchX[0] < keyboard.key[i].posX + keyboard.key[i].dimX + 4)) &&
                    ((tScreen.touchY[0] >= keyboard.key[i].posY - 4) && (tScreen.touchY[0] < keyboard.key[i].posY + keyboard.key[i].dimY + 4)) && 
                    (keyboard.key[i].status == KEY_RELEASED))
            {
                /* Отрисовываем нужную клавишу в инвертированном цвете*/
                Key_display_inverted(i);
                
                /* Если до этого нажатие было зафиксировано на другой клавише,
                 * отжимаем её и перерисовываем
                 */
                for (j = 0; j < KEY_NUMBER; j++)
                {
                    if (keyboard.key[j].status == KEY_PRESSED)
                    {
                        Key_display_normal(j);
                        
                        keyboard.key[j].status = KEY_RELEASED;
                    }
                }
                
                /* Меняем состояние клавишы, для которой было зафиксировано нажатие */
                keyboard.key[i].status = KEY_PRESSED;
                
                /* Сбрасываем состояние драйвера тач-экрана */
                BSP_TS_ResetTouchData(&tScreen);
            }
        }
    }
    /* Если касания нет, проверяем состояние каждой клавишы, возможно, касание 
     * было до этого момента и следует обработать ввод
     */
    else
    {
        for (i = 0; i < KEY_NUMBER; i++)
        {
            /* Если клавиша в нажатом состоянии, отжимаем её и перерисовываем */
            if (keyboard.key[i].status == KEY_PRESSED)
            {
                Key_display_normal(i);
                
                keyboard.key[i].status = KEY_RELEASED;
                BSP_TS_ResetTouchData(&tScreen);
                
                /* Возвращаем пользовательский ввод */
                return keyboard.key[i].value[keyboard.mode];
            }
        }
    }
    
    return 0;
}

/* Обработчик ввода на экранной клавиатуре */
uint8_t Keyboard_handler(char buffer[])
{
    uint8_t i;
    uint8_t len;
    uint8_t key;
    
    /* Проверяем, есть ли новое нажатие */
    key = Keyboard_check();
    
    /* Если нажата стандартная клавиша или клавиша "Space" */
    if ((key >= KEY_SPACE_VALUE) && (key != KEY_DELETE_VALUE))
    {
        /* Проверяем буффер клавиатуры и, если есть свободное место, добавляем
         * символ с нажатой клавишы в буфер клавиатуры
         */
        i = strlen(keyboard.buffer);
        if (i < KEY_BUFFER_LEN)
        {
            keyboard.buffer[i] = key;
            keyboard.buffer[i + 1] = '\0';
            
            /* Отображаем буфер клавиатуры на верхней строчке дисплея */
            BSP_LCD_ClearStringLine(0);
            BSP_LCD_DisplayStringAtLine(0, (uint8_t *) keyboard.buffer);
        }
    }
    /* Если нажата специальная клавиша */
    else
    {
        /* Если нажата клавиша "Enter", то копируем данные из буфера клавиатуры
         * в пользовательский буфер и затираем данные в буфере клавиатуры
         */
        if (key == KEY_ENTER_VALUE)
        {
            len = strlen(keyboard.buffer);
            
            for (i = 0; i <= len; i++)
            {
                buffer[i] = keyboard.buffer[i];
            }
            
            keyboard.buffer[0] = '\0';
            
            /* Затираем верхнюю строчку на дисплее */
            BSP_LCD_ClearStringLine(0);
            BSP_LCD_DisplayStringAtLine(0, (uint8_t *) keyboard.buffer);
        }
        
        /* Если нажата клавиша "Shift", меняем раскладку клавиатуры */
        if (key == KEY_SHIFT_VALUE)
        {
            keyboard.mode = !keyboard.mode;
            
            for (i = 0; i < KEY_NUMBER; i++)
            {
                /* Выводим значение клавишы в новой раскладке */
                BSP_LCD_DisplayChar(keyboard.key[i].posX + 8, keyboard.key[i].posY + 8, keyboard.key[i].value[keyboard.mode]);
                Key_display_specials(i);
            }
        }
        
        /* Если нажата клавиша "Backspace", удаляем крайний символ из буфера 
         * клавиатуры */ 
        if (key == KEY_BACKSPACE_VALUE)
        {
            len = strlen(keyboard.buffer);
            if (len != 0)
            {
                keyboard.buffer[len - 1] = '\0'; 
                BSP_LCD_ClearStringLine(0);
                BSP_LCD_DisplayStringAtLine(0, (uint8_t *) keyboard.buffer);
            }
        }
    }
    
    /* Возвращаем значение последней нажатой клавишы */
    return key;
}