Этот пример кода обрабатывает содержимое кольцевого буфера [2] bufRX с указателями inRX и outRX. Не существенные с точки зрения обработки ввода пользователя куски кода не показны.
Заголовочный файл decodeRX.h:
#ifndef __DECODERX__
#define __DECODERX__
typedef enum
{// Возможные значения для переменной action:
ACTION_NONE, // ничего не делать, ожидание команды
ACTION_BACKSPACE, // удаление символа слева от курсора
ACTION_TAB, // действие по клавише Tab (пока ничего не делать)
ACTION_ENTER, // обработка введенной команды
ACTION_SHOW_HELP, // показать подсказку по командной строке
}TCmdAction;
typedef enum
{
SYM_SINGLE, // ожидание ввода пользователя по одному символу
SYM_1B // начало Esc-последовательности
}TDecodeMode;
void DecodeConsoleCommands (void);
#endif
Модуль decodeRX.c:
#include < string.h>
#include "decodeRX.h"
#include "UARTconsole.h"
#include "miscell.h"
#include "umsg.h"
static TCmdAction action = ACTION_NONE;
static TDecodeMode decodemode = SYM_SINGLE;
static const char trimsymbols [] =
{
0x08, 0x09, 0x0D, 0x0A, 0
};
// Таймаут приема (ввод символов в консоли)
// в единицах 10 мс:
#define RX_TIMEOUT 10
static char cmddata[MAX_CMD_LEN];
static void GetCmdData (u16 idxstart, u16 idxend)
{
u16 idx = 0;
while ((idxstart != idxend) && (idx < sizeof(cmddata)-1))
{
cmddata[idx++] = bufRX[idxstart];
idxstart++;
idxstart &= UART_RXBUFMASK;
}
cmddata[idx] = 0;
ltrim ((char*)cmddata, (char*)trimsymbols);
rtrim ((char*)cmddata, (char*)trimsymbols);
}
// Функция обработки получаемых по UART символов (команды
// пользователя, вводимые в консоли). Рассчитана на вызов
// с интервалом 10 мс (из бесконечного цикла main).
void DecodeConsoleCommands (void)
{
// Счетчик таймаута между повлениями символов
// (нажатиями клавиш пользователя в терминале):
static u16 timeoutcnt = RX_TIMEOUT;
// Индекс начала команды:
static u16 idxStart = 0;
u8 sym;
int cmdlen;
u16 idx;
if (inRX == outRX)
{
// Символов на приеме нет, декремент счетчика таймаута.
if (timeoutcnt)
{
// Таймаут не истек, декремент таймаута:
timeoutcnt--;
}
else
{
// Таймаут истек, проверка ESC-последовательности:
if (SYM_1B == decodemode)
{
umsg("Esc-коды: ");
GetCmdData(idxStart, outRX);
cmdlen = strlen((char*)cmddata);
for (idx=0; idx < cmdlen; idx++)
{
umsg("%02X ", cmddata[idx]);
}
umsg("\n");
idxStart = outRX;
decodemode = SYM_SINGLE;
}
}
}
else
{
// Были обработаны символы, сброс таймаута
timeoutcnt = RX_TIMEOUT;
}
while (inRX != outRX)
{
// Выборка символа:
sym = bufRX[outRX];
outRX++;
outRX &= UART_RXBUFMASK;
switch(decodemode)
{
case SYM_SINGLE:
if (0x08 == sym)
{
action = ACTION_BACKSPACE;
idxStart = outRX;
}
else if (0x09 == sym)
{
action = ACTION_TAB;
idxStart = outRX;
}
else if ('?' == sym)
{
action = ACTION_SHOW_HELP;
idxStart = outRX;
}
else if (0x1B == sym)
{
decodemode = SYM_1B;
}
else if (0x0D == sym)
{
GetCmdData(idxStart, outRX);
action = ACTION_ENTER;
idxStart = outRX;
}
else
{
umsg("%c", sym);
}
break;
case SYM_1B:
break;
}
}
switch(action)
{
case ACTION_NONE:
break;
case ACTION_BACKSPACE:
umsg("BACKSPACE\n");
action = ACTION_NONE;
break;
case ACTION_TAB:
umsg("TAB\n");
action = ACTION_NONE;
break;
case ACTION_ENTER:
umsg("Введена команда %s\n", cmddata);
action = ACTION_NONE;
break;
case ACTION_SHOW_HELP:
umsg("HELP\n");
action = ACTION_NONE;
break;
}
}
Ниже на скриншоте показан результат обработки ввода пользователя в окне терминала. Нажимались клавиши Backspace, Tab, Esc и т. д. (клавиши, показанные в таблице выше). Также демонструется ввод команд и вывод подсказки (HELP) в ответ на ввод символа '?'.