optical/NxBase/console.c
2025-09-04 09:45:08 +08:00

916 lines
17 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define _IN_CONSOLE_C
#include "console.h"
#include "serial.h"
#include "trigger.h"
#include "cpuid.h"
//---------------------------------------------------------------------------------------------
int g_useQueue = 1; // = 0, 不使用队列输出,同步等待串口发送完成。= 1使用队列输入输出
//---------------------------------------------------------------------------------------------
void SetConsoleOutType(int type)
{
if (type != 0)
{
g_useQueue = 1;
}
else
{
g_useQueue = 0;
}
}
//---------------------------------------------------------------------------------------------
int SendData(u8 * pDatBuf, int len)
{
if (g_useQueue == 1)
{
#if (CONSOLE_PORT == COMM_USART1)
return Usart1SendData(pDatBuf, len);
#elif (CONSOLE_PORT == COMM_USART2)
return Usart2SendData(pDatBuf, len);
#elif (CONSOLE_PORT == COMM_USART3)
return Usart3SendData(pDatBuf, len);
#elif (CONSOLE_PORT == COMM_USART4)
return Usart4SendData(pDatBuf, len);
#elif (CONSOLE_PORT == COMM_USART5)
return Usart5SendData(pDatBuf, len);
#elif (CONSOLE_PORT == COMM_USART6)
return Usart6SendData(pDatBuf, len);
#else
return 0;
#endif
}
else
{
#if (CONSOLE_PORT == COMM_USART1)
return Usart1SendDataSync(pDatBuf, len);
#elif (CONSOLE_PORT == COMM_USART2)
return Usart2SendDataSync(pDatBuf, len);
#elif (CONSOLE_PORT == COMM_USART3)
return Usart3SendDataSync(pDatBuf, len);
#elif (CONSOLE_PORT == COMM_USART4)
return Usart4SendDataSync(pDatBuf, len);
#elif (CONSOLE_PORT == COMM_USART5)
return Usart5SendDataSync(pDatBuf, len);
#elif (CONSOLE_PORT == COMM_USART6)
return Usart6SendDataSync(pDatBuf, len);
#else
return 0;
#endif
}
}
int ResvData(u8 * pDat, int expectLen)
{
if (g_useQueue == 1)
{
#if (CONSOLE_PORT == COMM_USART1)
return Usart1GetData(pDat, expectLen);
#elif (CONSOLE_PORT == COMM_USART2)
return Usart2GetData(pDat, expectLen);
#elif (CONSOLE_PORT == COMM_USART3)
return Usart3GetData(pDat, expectLen);
#elif (CONSOLE_PORT == COMM_USART4)
return Usart4GetData(pDat, expectLen);
#elif (CONSOLE_PORT == COMM_USART5)
return Usart5GetData(pDat, expectLen);
#elif (CONSOLE_PORT == COMM_USART6)
return Usart6GetData(pDat, expectLen);
#else
return 0;
#endif
}
else
{
#if (CONSOLE_PORT == COMM_USART1)
return Usart1GetDataSync(pDat, expectLen);
#elif (CONSOLE_PORT == COMM_USART2)
return Usart2GetDataSync(pDat, expectLen);
#elif (CONSOLE_PORT == COMM_USART3)
return Usart3GetDataSync(pDat, expectLen);
#elif (CONSOLE_PORT == COMM_USART4)
return Usart4GetDataSync(pDat, expectLen);
#elif (CONSOLE_PORT == COMM_USART5)
return Usart5GetDataSync(pDat, expectLen);
#elif (CONSOLE_PORT == COMM_USART6)
return Usart6GetDataSync(pDat, expectLen);
#else
return 0;
#endif
}
}
// 串口选择
#if (CONSOLE_PORT == COMM_USART1)
#define INIT_USART InitUsart1
#elif (CONSOLE_PORT == COMM_USART2)
#define INIT_USART InitUsart2
#elif (CONSOLE_PORT == COMM_USART3)
#define INIT_USART InitUsart3
#elif (CONSOLE_PORT == COMM_USART4)
#define INIT_USART InitUsart4
#elif (CONSOLE_PORT == COMM_USART5)
#define INIT_USART InitUsart5
#elif (CONSOLE_PORT == COMM_USART6)
#define INIT_USART InitUsart6
#else
#endif
//---------------------------------------------------------------------------------------------
// 输入输出支持
#include <stdio.h>
#include <string.h>
#if defined ( __CC_ARM )
#pragma import(__use_no_semihosting_swi)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
FILE __stdin;
// 重定义 fputc 函数
int fputc(int ch, FILE *f)
{
u8 c = (u8)ch;
SendData(&c, 1);
return ch;
}
// 重定义 fgetc 函数
int fgetc(FILE *f)
{
int ch;
u8 c;
ch = ResvData(&c, 1);
if (ch == 1)
{
#if (0) // 回显
SendData(&c, 1);
#endif
return c;
}
return -1;
}
int ferror(FILE *f)
{
// 添加代码
return EOF;
}
void _ttywrch(int ch)
{
u8 c = (u8)ch;
SendData(&c, 1);
}
void _sys_exit(int return_code)
{
while (1);
}
#define GETCHAR getchar
#define PUTCHAR putchar
#elif defined ( __GNUC__ )
int __io_putchar(int ch)
{
u8 c;
c = ch;
SendData(&c, 1);
return ch;
}
int __io_getchar(void)
{
int ch;
u8 c;
ch = ResvData(&c, 1);
if (ch == 1)
{
ch = (int)c;
return ch;
}
return 0;
}
int _read(int file, char *ptr, int len)
{
int rslt;
rslt = ResvData((u8*)ptr, len);
return rslt;
}
int _write(int file, char *ptr, int len)
{
SendData((u8*)ptr, len);
return len;
}
#define PUTCHAR __io_putchar
#define GETCHAR __io_getchar
#endif
int PutChar(int ch)
{
return PUTCHAR(ch);
}
int GetChar(void)
{
return GETCHAR();
}
//---------------------------------------------------------------------------------------------
typedef struct
{
int pause; // 暂停
int newCmd; // 新命令标志
int cmdExec; // 命令执行标志
int cancel; // 请求退出执行标志
char command[MAX_CMD_LINE]; // 命令行内容
int cmdInCtrl; // 控制命令状态
int cmdPointer; // 命令行指针
int cmdLen; // 命令长度
char cmdBuf[MAX_CMD_LINE]; // 命令行缓存
}CmdLine;
CmdLine g_cmdLine;
//---------------------------------------------------------------------------------------------
int IsNewCommand(void)
{
return g_cmdLine.newCmd;
}
int LockExecAndGetCmdStr(char*pBuf)
{
int len;
EnterCritical();
len = g_cmdLine.cmdLen;
g_cmdLine.cmdExec = 1;
g_cmdLine.newCmd = 0;
ExitCritical();
memcpy(pBuf, g_cmdLine.command, len);
return len;
}
void UnlockExec(void)
{
g_cmdLine.cmdExec = 0;
}
void SetPauseStatus(int sta)
{
if (sta != 0)
{
g_cmdLine.pause = 1;
}
else
{
g_cmdLine.pause = 0;
}
}
//---------------------------------------------------------------------------------------------
// 循环队列保存历史命令
#define HISTORY_CMD_NUM 10 // 历史命令存储个数
char g_cmdHistory[HISTORY_CMD_NUM][MAX_CMD_LINE];
int g_cmdHisIdx = 0; // 历史命令指针
int g_cmdHisNum = 0; // 历史命令个数
int g_cmdHisSer = -1; // 历史命令遍历
int g_cursorNum = 0; // 20220412
void InitHistory(void)
{
g_cmdHisIdx = 0; // 历史命令指针
g_cmdHisNum = 0; // 历史命令个数
g_cmdHisSer = -1; // 历史命令遍历
g_cursorNum = 0;
memset(g_cmdHistory, 0, HISTORY_CMD_NUM*MAX_CMD_LINE);
}
void AddNewCmdToHistory(char * pCmd)
{
if (pCmd != NULL)
{
// 判断当前命令是否已经存放在历史命令中,如果已存放,将其提取到队列尾部
for (int i = 0; i < g_cmdHisNum; i++)
{
if (strcmp(&(g_cmdHistory[i][0]), pCmd) == 0) // 已存放
{
int temp1, temp2;
int count;
// 计算提取到队列尾部所需次数
if (i >= g_cmdHisIdx)
{
count = g_cmdHisNum - (i - g_cmdHisIdx);
}
else
{
count = g_cmdHisIdx - i;
}
count--;
// 提取过程
for (int j = 0; j < count; j++)
{
temp1 = i + j;
temp2 = temp1 + 1;
if (temp1 >= g_cmdHisNum)
{
temp1 -= g_cmdHisNum;
}
if (temp2 >= g_cmdHisNum)
{
temp2 -= g_cmdHisNum;
}
memset(&(g_cmdHistory[temp1][0]), 0, MAX_CMD_LINE);
strcpy(&(g_cmdHistory[temp1][0]), &(g_cmdHistory[temp2][0]));
if (j == (count - 1))
{
memset(&(g_cmdHistory[temp2][0]), 0, MAX_CMD_LINE);
strcpy(&(g_cmdHistory[temp2][0]), pCmd);
}
}
return;
}
}
if (g_cmdHisIdx >= HISTORY_CMD_NUM)
{
g_cmdHisIdx = 0;
}
memset(&(g_cmdHistory[g_cmdHisIdx][0]), 0, MAX_CMD_LINE);
strcpy(&(g_cmdHistory[g_cmdHisIdx][0]), pCmd);
g_cmdHisIdx++;
if (g_cmdHisNum < HISTORY_CMD_NUM)
{
g_cmdHisNum++;
}
}
}
// 上光标处理
void UpCursorProc(void)
{
if (g_cursorNum > 0)
{
g_cursorNum--;
}
else
{
return;
}
g_cmdHisSer--;
if (g_cmdHisSer < 0)
{
g_cmdHisSer = g_cmdHisNum - 1;
}
if (1)
{
// 输出退格,清空所有
while (g_cmdLine.cmdPointer != 0)
{
PUTCHAR(0x08); // 输出退格
PUTCHAR(' '); // 输出空格
PUTCHAR(0x08); // 输出退格
g_cmdLine.cmdPointer--;
}
// 显示历史命令
if (g_cmdLine.cmdExec == 0 && g_cmdLine.newCmd == 0)
{
char ch;
for (int i = 0; i < MAX_CMD_LINE; i++)
{
ch = g_cmdHistory[g_cmdHisSer][i];
if (ch > 0x1F && ch < 0x7F) // 添加字符到命令行中
{
if (g_cmdLine.cmdPointer < MAX_CMD_LINE-1)
{
PUTCHAR(ch); // 回显示
g_cmdLine.cmdBuf[g_cmdLine.cmdPointer] = ch;
g_cmdLine.cmdPointer++;
}
}
}
}
else
{
g_cmdLine.cmdPointer = 0;
g_cmdLine.cmdBuf[0] = 0;
}
}
}
// 下光标处理
void DownCursorProc(void)
{
if (g_cursorNum < g_cmdHisNum)
{
g_cursorNum++;
}
else
{
return;
}
g_cmdHisSer++;
if (g_cursorNum == g_cmdHisNum)
{
// 输出退格,清空所有
while (g_cmdLine.cmdPointer != 0)
{
PUTCHAR(0x08); // 输出退格
PUTCHAR(' '); // 输出空格
PUTCHAR(0x08); // 输出退格
g_cmdLine.cmdPointer--;
}
return;
}
if (g_cmdHisSer >= g_cmdHisNum)
{
g_cmdHisSer = 0;
}
if (1)
{
// 输出退格,清空所有
while (g_cmdLine.cmdPointer != 0)
{
PUTCHAR(0x08); // 输出退格
PUTCHAR(' '); // 输出空格
PUTCHAR(0x08); // 输出退格
g_cmdLine.cmdPointer--;
}
// 显示历史命令
if (g_cmdLine.cmdExec == 0 && g_cmdLine.newCmd == 0)
{
char ch;
for (int i = 0; i < MAX_CMD_LINE; i++)
{
ch = g_cmdHistory[g_cmdHisSer][i];
if (ch > 0x1F && ch < 0x7F) // 添加字符到命令行中
{
if (g_cmdLine.cmdPointer < MAX_CMD_LINE-1)
{
PUTCHAR(ch); // 回显示
g_cmdLine.cmdBuf[g_cmdLine.cmdPointer] = ch;
g_cmdLine.cmdPointer++;
}
}
}
}
else
{
g_cmdLine.cmdPointer = 0;
g_cmdLine.cmdBuf[0] = 0;
}
}
}
//---------------------------------------------------------------------------------------------
void OutNewCmdLine(void)
{
g_cmdLine.cmdPointer = 0; // 命令行指针
g_cmdLine.cmdLen = 0; // 命令长度
PUTCHAR(0x0D); // 回车
PUTCHAR(0x0A); // 换行
PUTCHAR('C');
PUTCHAR('M');
PUTCHAR('D');
PUTCHAR(':');
PUTCHAR('>');
}
//---------------------------------------------------------------------------------------------
void InitConsole(void)
{
InitTrigger();
#if (CONSOLE_PORT != COMM_NONE)
INIT_USART(B115200, '8', 'N', '1');
#endif
AddTriggerToList(10, ConsoleCmdScan, NULL); // 10ms 响应控制台
printf("\x0c"); // 超级终端清屏
printf("\033[1;40;32m"); // 设置超级终端背景为黑色,字符为绿色
printf("\x0c"); // 超级终端清屏
memset(&g_cmdLine, 0, sizeof(CmdLine));
g_useQueue = 1; // = 0, 不使用队列输出,同步等待串口发送完成。= 1使用队列输入输出
InitHistory();
}
// 定时器处理回显和检测命令输入
void ConsoleCmdScan()
{
int ch;
if (g_cmdLine.pause != 0)
{
return;
}
ch = GETCHAR();
if (ch < 0)
{
g_cmdLine.cmdInCtrl = 0;
return;
}
// 命令处理
switch(ch)
{
case 0x00: // NUL (Null char)
case 0x01: // SOH (Start of Header) 发送文件首
case 0x02: // STX (Start of Text) 文本开始
ch = ch;
break;
case 0x03: // ETX (End of Text) 文本尾
if (g_cmdLine.cmdExec == TRUE) // ctrl+C 为终止命令
{
OutNewCmdLine();
g_cmdLine.cancel = 1;
}
break;
case 0x04: // EOT (End of Transmission) 发送结束
case 0x05: // ENQ (Enquiry)
case 0x06: // ACK (Acknowledgment) 确认
case 0x07: // BEL (Bell) 蜂鸣
ch = ch;
break;
case 0x08: // BS (Backspace) 退格
if (g_cmdLine.cmdPointer != 0)
{
PUTCHAR(0x08); // 输出退格
PUTCHAR(' '); // 输出空格
PUTCHAR(0x08); // 输出退格
g_cmdLine.cmdPointer--;
}
break;
case 0x09: // HT (Horizontal Tab)
// 自动命令补全......
break;
case 0x0A: // LF (Line Feed) 换行
case 0x0B: // VT (Vertical Tab)
case 0x0C: // FF (Form Feed) 换页/清屏
ch = ch;
break;
case 0x0D: // CR (Carriage Return) 回车
{
if (g_cmdLine.newCmd == 0 && g_cmdLine.cmdExec == 0)
{
PUTCHAR(0x0D); // 增加回车
PUTCHAR(0x0A); // 增加换行
g_cmdLine.cmdBuf[g_cmdLine.cmdPointer] = 0; // 字符串尾
g_cmdLine.cmdLen = g_cmdLine.cmdPointer; // 长度
strcpy(g_cmdLine.command, g_cmdLine.cmdBuf); // 拷贝新命令
if (g_cmdLine.cmdLen != 0) // 20220412 命令长度不为0,才存入历史命令
{
AddNewCmdToHistory(g_cmdLine.cmdBuf); // 命令行内容
}
g_cmdHisSer = g_cmdHisIdx; // 20220412
g_cursorNum = g_cmdHisNum;
g_cmdLine.newCmd = 1; // 新命令
}
break;
}
case 0x0E: // SO (Shift Out)SHIFT 松开
case 0x0F: // SI (Shift In) 按下
case 0x10: // DLE (Data Link Escape) 清除
case 0x11: // DC1 (XON) (Device Control 1)
case 0x12: // DC2 (Device Control 2)
case 0x13: // DC3 (XOFF)(Device Control 3)
case 0x14: // DC4 (Device Control 4)
case 0x15: // NAK (Negative Acknowledgement)
case 0x16: // SYN (Synchronous Idle)
case 0x17: // ETB (End of Trans. Block)
case 0x18: // CAN (Cancel)
case 0x19: // EM (End of Medium)
case 0x1A: // SUB (Substitute) // pause 键
ch = ch;
break;
case 0x1B: // ESC (Escape) 退出
g_cmdLine.cmdInCtrl = 1;
break;
case 0x1C: // FS (File Separator)
case 0x1D: // GS (Group Separator)
case 0x1E: // RS (Request to Send/Record Separator)
case 0x1F: // US (Unit Separator)
ch = ch;
break;
case 0x7F:
if (g_cmdLine.cmdPointer != 0)
{
PUTCHAR(0x08); // 输出退格
PUTCHAR(' '); // 输出空格
PUTCHAR(0x08); // 输出退格
g_cmdLine.cmdPointer--;
if (g_cmdLine.cmdLen != 0)
{
g_cmdLine.cmdLen--;
}
}
break;
default:
break;
}
if (ch != 0x1B && g_cmdLine.cmdInCtrl != 0)
{
if (g_cmdLine.cmdInCtrl == 1 && ch == 0x5B)
{
ch = GETCHAR();
switch(ch)
{
case 0x41: // 上光标
ch = 'u';
// 上翻历史命令记录
UpCursorProc(); // 20220412
break;
case 0x42: // 下光标
ch = 'd';
DownCursorProc(); // 下翻历史命令记录
break;
case 0x43: // 右光标
ch = 'r';
break;
case 0x44: // 左光标
ch = 'l';
break;
case 0x31:
{
ch = GETCHAR();
if (ch == 0x7E) // HOME 键
{
ch = 'h';
}
else if (ch == 0x31)
{
ch = GETCHAR();
if (ch == 0x7E) // F1 键
{
ch = '1';
}
}
else if (ch == 0x32)
{
ch = GETCHAR();
if (ch == 0x7E) // F2 键
{
ch = '2';
}
}
else if (ch == 0x33)
{
ch = GETCHAR();
if (ch == 0x7E) // F3 键
{
ch = '3';
}
}
else if (ch == 0x34)
{
ch = GETCHAR();
if (ch == 0x7E) // F4 键
{
ch = '4';
}
}
else if (ch == 0x35)
{
ch = GETCHAR();
if (ch == 0x7E) // F5 键
{
ch = '5';
}
}
else if (ch == 0x37)
{
ch = GETCHAR();
if (ch == 0x7E) // F6 键
{
ch = '6';
}
}
else if (ch == 0x38)
{
ch = GETCHAR();
if (ch == 0x7E) // F7 键
{
ch = '7';
}
}
else if (ch == 0x39)
{
ch = GETCHAR();
if (ch == 0x7E) // F8 键
{
ch = '8';
}
}
break;
}
case 0x32:
{
ch = GETCHAR();
if (ch == 0x7E) // INS 键
{
ch = 'i';
}
else if (ch == 0x30)
{
ch = GETCHAR();
if (ch == 0x7E) // F9 键
{
ch = '9';
}
}
else if (ch == 0x31)
{
ch = GETCHAR();
if (ch == 0x7E) // F10 键
{
ch = 'a';
}
}
else if (ch == 0x33)
{
ch = GETCHAR();
if (ch == 0x7E) // F11 键
{
ch = 'b';
}
}
else if (ch == 0x34)
{
ch = GETCHAR();
if (ch == 0x7E) // F12 键
{
ch = 'c';
}
}
break;
}
case 0x33:
ch = GETCHAR();
if (ch == 0x7E) // DEL 键
{
ch = 'd';
}
break;
case 0x34:
ch = GETCHAR();
if (ch == 0x7E) // END 键
{
ch = 'e';
}
break;
case 0x35:
ch = GETCHAR();
if (ch == 0x7E) // PAGE UP 键
{
ch = 'u';
}
break;
case 0x36:
ch = GETCHAR();
if (ch == 0x7E) // PAGE DOWN 键
{
ch = 'd';
}
break;
default:
g_cmdLine.cmdInCtrl = 0;
break;
}
}
else
{
g_cmdLine.cmdInCtrl = 0;
}
if (g_cmdLine.cmdInCtrl != 0)
{
ch = 0;
g_cmdLine.cmdInCtrl = 0;
}
}
if (g_cmdLine.cmdExec == 0 && g_cmdLine.newCmd == 0)
{
if (ch > 0x1F && ch < 0x7F) // 添加字符到命令行中
{
if (g_cmdLine.cmdPointer < MAX_CMD_LINE-1)
{
PUTCHAR(ch); // 回显示
g_cmdLine.cmdBuf[g_cmdLine.cmdPointer] = ch;
g_cmdLine.cmdPointer++;
}
}
}
else
{
g_cmdLine.cmdPointer = 0;
g_cmdLine.cmdBuf[0] = 0;
}
}
int IsConsoleCancel(void)
{
int rslt = g_cmdLine.cancel;
g_cmdLine.cancel = 0;
return rslt;
}
// 20220412 提供一个外部接口,用于获取存储的历史命令
int GetHistoryCmd(int hisIdx, char * pch)
{
if (hisIdx < 0 || hisIdx > HISTORY_CMD_NUM || pch == NULL)
{
return -1;
}
strncpy(pch, &(g_cmdHistory[hisIdx][0]), MAX_CMD_LINE);
return 0;
}
int GetHistoryNum(void)
{
return g_cmdHisNum;
}
int GetHistoryMaxNum(void)
{
return HISTORY_CMD_NUM;
}
int GetHistoryIdx(void)
{
return g_cmdHisIdx;
}
//---------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------