前言:

当我们使用嵌入式linux 进行开发时,kernel 跑起来之后,我们希望能通过串口(标准输入、输出),在应用程序正在运行的过程中,进行一些调试工作,例如,对CPU一些寄存进行调整,以观测调整以后的结果,并且,当我们无法把我们的应用程序放在后台运行,那么我们就需要实现一个基础的控制台。

下文中的控制台,虽然简单,但完备的支持 上 下 左 右 backspace del 常用控制台操作,使用 上 下 键可以浏览已经输入过的命令(类似 doskey 这样的功能),支持 光标 左右移动 修改命令

一般我们在 main 函数最后 都会做 while(TRUE) sleep(1000) 这样 阻塞住主线程,用这个控制台的实现,替换这个过程,则应用程序可增加控制台应用功能,各部分的具体实现如下:

调用代码(main.c):

#include 

#include "app_console.h"

intmain(intargc,char*argv[])

{

// 之前的应用代码

....

....

....

App_Console_Start();

return0;

}

控制台头文件(app_console.h)

#ifndef __APP_CONSOLE_H__

#define __APP_CONSOLE_H__

#ifdef __cplusplus

extern"C"

{

#endif

#include "type_def.h"

voidApp_Console_Start();

#ifdef __cplusplus

}

#endif

#endif

控制台C文件(app_console.c)

#include "app_console.h"

#include "ctype.h"

#include "unistd.h"

#include "app_test.h"

// 说明

// read write 使用的是 POSIX 的标准文件读写函数

// unistd.h 包含了 STDIN_FILENO 等文件描述符的定义

// ctype.h 包含了 isprint 函数的声明

// 经过仔细考虑,决定不支持 ESC 键,因为ESC 键的键值为 0x1b 与 上下左右的键值重复

// 但可以考虑按2下ESC清除本行输入

// 对不可打印字符的处理仅限于以下已经列出的宏定义

// change:

// 放弃对 double ESC 的支持,因为可能出现按了 ESC 又按了 方向键 的情况

// 则用户输入编码为 '/x1b' '/x1b' '[' 'A' (按了ESC 又按了上键)

// change:

// 为了将应用与控制台应用剥离,则将 #define MAX_CMD_LEN 512 房到 app_test.h 中定义

// 二维数组作为参数进行传递时,需要明确第二个维度的大小,否则编译器无法正确定位地址

#define KEY_BACKSPACE    '/x08'    // back space

#define KEY_DEL          '/x7F'    // del

#define KEY_ENTER        '/x0A'    // 回车

// 以下为 0x1b 开头的键值

//#define KEY_DOUBLEESC    "/x1B/x1B"// ESC

//#define KEY_ARROW_UP     "/x1B[A"  // 上

//#define KEY_ARROW_DOWN   "/x1B[B"  // 下

//#define KEY_ARROW_LEFT   "/x1B[D"  // 左

//#define KEY_ARROW_RIGHT  "/x1B[C"  // 右

typedefenum

{

WKS_WAIT,

WKS_RECV1B,

WKS_UDLR,

}T_WaitKeyState;

#define MAX_CMD_HISTORY 32

#define MAX_PAR_COUNT 16

staticcharszPrompt[] = {"TR_Console> "};

staticT_WaitKeyState waitKeyState = WKS_WAIT;

staticcharszCmdHistory[MAX_CMD_HISTORY][MAX_CMD_LEN];

staticcharszCmdNow[MAX_CMD_LEN] = {0};

staticUINT32nCmdIndex = 0;

staticUINT32nCmdCursor = 0;

staticUINT32nCmdInputCount = 0;

staticUINT32nCmdInputCursor = 0;

staticvoidApp_Console_ParseCmd(constchar* pCmd);

staticUINT32App_Console_ReadInput(char*input)

{

U32    nRead=0;

structpollfd p;

structtermio term,term_old;

/* Get control of the terminal */

ioctl(STDIN_FILENO,TCGETA,(void*)&term);

term_old = term;

term.c_lflag &= ~ICANON;

term.c_lflag &= ~ECHO;

ioctl(STDIN_FILENO,TCSETAW,(void*)&term);

/* Get event we want to know */

p.fd     = STDIN_FILENO;

p.events = POLLIN;

/* If we receive one thing, get the byte now */

if(poll(&p,1,-1)>0)

{

if(p.revents==POLLIN)

{

nRead=read(STDIN_FILENO,input,1);

}

}

/* Purge the byte */

/* tcflush(0,TCIOFLUSH); */

/* Leave control */

ioctl(STDIN_FILENO,TCSETAW,(void*)&term_old);

return(nRead);

}

staticvoidApp_Console_BSChar()

{

charszTemp[3];

szTemp[0] ='/b';

szTemp[1] =' ';

szTemp[2] ='/b';

write(STDOUT_FILENO,szTemp,3);

}

staticvoidApp_Console_OnPrintChar(charinput)

{

if(nCmdInputCount == MAX_CMD_LEN)return;

if(nCmdInputCursor 

{

charszTemp[MAX_CMD_LEN] = {0};

char* pCmd = szCmdNow;

intnBackCount = nCmdInputCount-nCmdInputCursor;

szTemp[0] = input;

memcpy(&szTemp[1],&pCmd[nCmdInputCursor],nBackCount);

write(STDOUT_FILENO,szTemp,nBackCount+1);

memcpy(&pCmd[nCmdInputCursor],&szTemp,nBackCount+1);

memset(szTemp,'/b',nBackCount);

write(STDOUT_FILENO,szTemp,nBackCount);

}

else

{

write(STDOUT_FILENO,&input,1);

szCmdNow[nCmdInputCount] = input;

}

nCmdInputCursor++;

nCmdInputCount++;

}

staticvoidApp_Console_OnBackspace()

{

if(nCmdInputCursor > 0)

{

if(nCmdInputCursor == nCmdInputCount)// 光标在末尾

App_Console_BSChar();

else// 光标不在末尾

{

charszTemp[MAX_CMD_LEN] = {0};

char* pCmd = szCmdNow;

intnBackCount = nCmdInputCount-nCmdInputCursor;

szTemp[0] ='/b';

memcpy(&szTemp[1],&pCmd[nCmdInputCursor],nBackCount);

szTemp[nBackCount+1] =' ';

write(STDOUT_FILENO,szTemp,nBackCount+2);

memcpy(&pCmd[nCmdInputCursor-1],&szTemp[1],nBackCount);

memset(szTemp,'/b',nBackCount+1);

write(STDOUT_FILENO,szTemp,nBackCount+1);

}

nCmdInputCount --;

nCmdInputCursor--;

}

}

staticvoidApp_Console_OnDel()

{

if(nCmdInputCursor 

{

charszTemp[MAX_CMD_LEN] = {0};

char* pCmd = szCmdNow;

intnBackCount = nCmdInputCount-nCmdInputCursor-1;

memcpy(szTemp,&pCmd[nCmdInputCursor+1],nBackCount);

szTemp[nBackCount] =' ';

write(STDOUT_FILENO,szTemp,nBackCount+1);

memcpy(&pCmd[nCmdInputCursor],szTemp,nBackCount);

memset(szTemp,'/b',nBackCount+1);

write(STDOUT_FILENO,szTemp,nBackCount+1);

nCmdInputCount--;

}

}

staticvoidApp_Console_OnDoubleEsc()

{

if(nCmdInputCount > 0)

{

char* pCmd = szCmdNow;

// 将光标移动到最末尾

while(nCmdInputCursor 

{

write(STDOUT_FILENO,&pCmd[nCmdInputCursor],1);

nCmdInputCursor++;

}

// 清除所有输入的数据

inti=0;

for(i=0;i

nCmdInputCount = 0;

nCmdInputCursor = 0;

}

}

staticvoidApp_Console_OnUp()

{

if(nCmdCursor == 0)return;

nCmdCursor --;

// 清除掉现在所有的输入

App_Console_OnDoubleEsc();

char* pCmdHistory = &szCmdHistory[nCmdCursor][0];

memcpy(szCmdNow,pCmdHistory,MAX_CMD_LEN);

nCmdInputCount = strlen(szCmdNow);

nCmdInputCursor= nCmdInputCount;

write(STDOUT_FILENO,szCmdNow,nCmdInputCount);

}

staticvoidApp_Console_OnDown()

{

if(nCmdCursor >= (nCmdIndex-1))return;

nCmdCursor ++;

// 清除掉现在所有的输入

App_Console_OnDoubleEsc();

char* pCmdHistory = &szCmdHistory[nCmdCursor][0];

memcpy(szCmdNow,pCmdHistory,MAX_CMD_LEN);

nCmdInputCount = strlen(szCmdNow);

nCmdInputCursor= nCmdInputCount;

write(STDOUT_FILENO,szCmdNow,nCmdInputCount);

}

staticvoidApp_Console_OnLeft()

{

if(nCmdInputCursor > 0)

{

charc ='/b';

write(STDOUT_FILENO,&c,1);

nCmdInputCursor--;

}

}

staticvoidApp_Console_OnRight()

{

if(nCmdInputCursor 

{

char* pCmd = szCmdNow;

charc = pCmd[nCmdInputCursor];

write(STDOUT_FILENO,&c,1);

nCmdInputCursor++;

}

}

staticvoidApp_Console_OnEnter()

{

szCmdNow[nCmdInputCount] ='/0';

charszTemp[] = {"/r/n"};

write(STDOUT_FILENO,szTemp,strlen(szTemp));

nCmdInputCount = 0;

nCmdInputCursor = 0;

if(strlen(szCmdNow) == 0)return;

if(nCmdIndex == MAX_CMD_HISTORY)// 命令队列满了,移动

{

charszTempCmd[MAX_CMD_HISTORY][MAX_CMD_LEN];

memcpy(szTempCmd,&szCmdHistory[1][0],MAX_CMD_LEN*(MAX_CMD_HISTORY-1));

memcpy(szCmdHistory,szTempCmd,MAX_CMD_LEN*(MAX_CMD_HISTORY-1));

nCmdIndex = MAX_CMD_HISTORY-1;

nCmdCursor = nCmdIndex;

}

memcpy(szCmdHistory[nCmdIndex],szCmdNow,MAX_CMD_LEN);

nCmdIndex++;

nCmdCursor = nCmdIndex;

// 解析命令

App_Console_ParseCmd(szCmdNow);

}

staticvoidApp_Console_CmdLoop()

{

BOOLbGetEnter = FALSE;

while(TRUE)

{

// 读取一个console输入

UINT32nReturn = 0;

charinput;

nReturn = App_Console_ReadInput (&input);

if(nReturn > 0)

{

switch(waitKeyState)

{

caseWKS_WAIT :

if(isprint(input))// 可打印字符

App_Console_OnPrintChar(input);

else

{

if(input == KEY_BACKSPACE)

App_Console_OnBackspace();

elseif(input == KEY_DEL)

App_Console_OnDel();

elseif(input == KEY_ENTER)

{

App_Console_OnEnter();

bGetEnter = TRUE;

}

elseif(input =='/x1b')

waitKeyState = WKS_RECV1B;

else

waitKeyState = WKS_WAIT;

}

break;

caseWKS_RECV1B:

if(input =='/x1b')// 按了ESC 又按了方向键,或者是 ESC

{

//App_Console_OnDoubleEsc();

waitKeyState = WKS_RECV1B;

}

else

if(input =='[')//可能为 上下左右 4个键

waitKeyState = WKS_UDLR;

else//下面的情况为 按了 ESC 键之后,按了其他的键的处理

{

if(isprint(input)) App_Console_OnPrintChar(input);

waitKeyState = WKS_WAIT;

}

break;

caseWKS_UDLR:

if(input =='A')// 上

App_Console_OnUp();

elseif(input =='B')// 下

App_Console_OnDown();

elseif(input =='D')// 左

App_Console_OnLeft();

elseif(input =='C')// 右

App_Console_OnRight();

else

{

if(isprint(input)) App_Console_OnPrintChar(input);

}

waitKeyState = WKS_WAIT;

break;

default:

break;

}

}

if(bGetEnter)

{

break;

}

}

}

voidApp_Console_Start()

{

// 清空 sdtout 缓冲

fflush(stdout);

fflush(stdin);

charszTemp[] = {"/r/nStart TR Console.../r/n/r/n"};

write(STDOUT_FILENO,szTemp,strlen(szTemp));

while(TRUE)

{

write(STDOUT_FILENO,szPrompt,strlen(szPrompt));

App_Console_CmdLoop();

}

}

// 解析命令

staticvoidApp_Console_ParseCmd(constchar* pCmd)

{

intlength = strlen(pCmd);

// 全部转小写

inti=0;

charszTempCmd[MAX_CMD_LEN];

for(i=0; i 

// 将输入的命令各个 part 分开

charszPart[MAX_PAR_COUNT][MAX_CMD_LEN];

intnPartCount = 0;

intnPartCursor = 0;

intnCmdCursor = 0;

memset(szPart,0,sizeof(szPart));

while(TRUE)

{

if(nCmdCursor == length)

{

if(nPartCursor > 0)

{

nPartCount++;

nPartCursor = 0;

}

break;

}

if( (szTempCmd[nCmdCursor] ==',') || (szTempCmd[nCmdCursor] ==' ') )// part 分割符

{

szPart[nPartCount][nPartCursor] ='/0';

nPartCount++;

nPartCursor = 0;

}

else

{

szPart[nPartCount][nPartCursor] = szTempCmd[nCmdCursor];

nPartCursor++;

}

nCmdCursor++;

}

App_Test_OnCmd(szPart,nPartCount);

}#include "app_console.h"

#include "ctype.h"

#include "unistd.h"

#include "app_test.h"

// 说明

// read write 使用的是 POSIX 的标准文件读写函数

// unistd.h 包含了 STDIN_FILENO 等文件描述符的定义

// ctype.h 包含了 isprint 函数的声明

// 经过仔细考虑,决定不支持 ESC 键,因为ESC 键的键值为 0x1b 与 上下左右的键值重复

// 但可以考虑按2下ESC清除本行输入

// 对不可打印字符的处理仅限于以下已经列出的宏定义

// change:

// 放弃对 double ESC 的支持,因为可能出现按了 ESC 又按了 方向键 的情况

// 则用户输入编码为 '/x1b' '/x1b' '[' 'A' (按了ESC 又按了上键)

// change:

// 为了将应用与控制台应用剥离,则将 #define MAX_CMD_LEN 512 房到 app_test.h 中定义

// 二维数组作为参数进行传递时,需要明确第二个维度的大小,否则编译器无法正确定位地址

#define KEY_BACKSPACE '/x08' // back space

#define KEY_DEL '/x7F' // del

#define KEY_ENTER '/x0A' // 回车

// 以下为 0x1b 开头的键值

//#define KEY_DOUBLEESC "/x1B/x1B"// ESC

//#define KEY_ARROW_UP "/x1B[A" // 上

//#define KEY_ARROW_DOWN "/x1B[B" // 下

//#define KEY_ARROW_LEFT "/x1B[D" // 左

//#define KEY_ARROW_RIGHT "/x1B[C" // 右

typedef enum

{

WKS_WAIT,

WKS_RECV1B,

WKS_UDLR,

}T_WaitKeyState;

#define MAX_CMD_HISTORY 32

#define MAX_PAR_COUNT 16

static char szPrompt[] = {"TR_Console> "};

static T_WaitKeyState waitKeyState = WKS_WAIT;

static char szCmdHistory[MAX_CMD_HISTORY][MAX_CMD_LEN];

static char szCmdNow[MAX_CMD_LEN] = {0};

static UINT32 nCmdIndex = 0;

static UINT32 nCmdCursor = 0;

static UINT32 nCmdInputCount = 0;

static UINT32 nCmdInputCursor = 0;

static void App_Console_ParseCmd(const char* pCmd);

static UINT32 App_Console_ReadInput(char *input)

{

U32 nRead=0;

struct pollfd p;

struct termio term,term_old;

/* Get control of the terminal */

ioctl(STDIN_FILENO,TCGETA,(void *)&term);

term_old = term;

term.c_lflag &= ~ICANON;

term.c_lflag &= ~ECHO;

ioctl(STDIN_FILENO,TCSETAW,(void *)&term);

/* Get event we want to know */

p.fd = STDIN_FILENO;

p.events = POLLIN;

/* If we receive one thing, get the byte now */

if (poll(&p,1,-1)>0)

{

if (p.revents==POLLIN)

{

nRead=read(STDIN_FILENO,input,1);

}

}

/* Purge the byte */

/* tcflush(0,TCIOFLUSH); */

/* Leave control */

ioctl(STDIN_FILENO,TCSETAW,(void *)&term_old);

return(nRead);

}

static void App_Console_BSChar()

{

char szTemp[3];

szTemp[0] = '/b';

szTemp[1] = ' ';

szTemp[2] = '/b';

write(STDOUT_FILENO,szTemp,3);

}

static void App_Console_OnPrintChar(char input)

{

if(nCmdInputCount == MAX_CMD_LEN) return;

if(nCmdInputCursor < nCmdInputCount) // 光标不在末尾

{

char szTemp[MAX_CMD_LEN] = {0};

char* pCmd = szCmdNow;

int nBackCount = nCmdInputCount-nCmdInputCursor;

szTemp[0] = input;

memcpy(&szTemp[1],&pCmd[nCmdInputCursor],nBackCount);

write(STDOUT_FILENO,szTemp,nBackCount+1);

memcpy(&pCmd[nCmdInputCursor],&szTemp,nBackCount+1);

memset(szTemp,'/b',nBackCount);

write(STDOUT_FILENO,szTemp,nBackCount);

}

else

{

write(STDOUT_FILENO,&input,1);

szCmdNow[nCmdInputCount] = input;

}

nCmdInputCursor++;

nCmdInputCount++;

}

static void App_Console_OnBackspace()

{

if(nCmdInputCursor > 0)

{

if(nCmdInputCursor == nCmdInputCount) // 光标在末尾

App_Console_BSChar();

else// 光标不在末尾

{

char szTemp[MAX_CMD_LEN] = {0};

char* pCmd = szCmdNow;

int nBackCount = nCmdInputCount-nCmdInputCursor;

szTemp[0] = '/b';

memcpy(&szTemp[1],&pCmd[nCmdInputCursor],nBackCount);

szTemp[nBackCount+1] = ' ';

write(STDOUT_FILENO,szTemp,nBackCount+2);

memcpy(&pCmd[nCmdInputCursor-1],&szTemp[1],nBackCount);

memset(szTemp,'/b',nBackCount+1);

write(STDOUT_FILENO,szTemp,nBackCount+1);

}

nCmdInputCount --;

nCmdInputCursor--;

}

}

static void App_Console_OnDel()

{

if(nCmdInputCursor < nCmdInputCount) // 光标不在末尾

{

char szTemp[MAX_CMD_LEN] = {0};

char* pCmd = szCmdNow;

int nBackCount = nCmdInputCount-nCmdInputCursor-1;

memcpy(szTemp,&pCmd[nCmdInputCursor+1],nBackCount);

szTemp[nBackCount] = ' ';

write(STDOUT_FILENO,szTemp,nBackCount+1);

memcpy(&pCmd[nCmdInputCursor],szTemp,nBackCount);

memset(szTemp,'/b',nBackCount+1);

write(STDOUT_FILENO,szTemp,nBackCount+1);

nCmdInputCount--;

}

}

static void App_Console_OnDoubleEsc()

{

if(nCmdInputCount > 0)

{

char* pCmd = szCmdNow;

// 将光标移动到最末尾

while(nCmdInputCursor < nCmdInputCount)

{

write(STDOUT_FILENO,&pCmd[nCmdInputCursor],1);

nCmdInputCursor++;

}

// 清除所有输入的数据

int i=0;

for(i=0;i

nCmdInputCount = 0;

nCmdInputCursor = 0;

}

}

static void App_Console_OnUp()

{

if(nCmdCursor == 0) return;

nCmdCursor --;

// 清除掉现在所有的输入

App_Console_OnDoubleEsc();

char* pCmdHistory = &szCmdHistory[nCmdCursor][0];

memcpy(szCmdNow,pCmdHistory,MAX_CMD_LEN);

nCmdInputCount = strlen(szCmdNow);

nCmdInputCursor= nCmdInputCount;

write(STDOUT_FILENO,szCmdNow,nCmdInputCount);

}

static void App_Console_OnDown()

{

if(nCmdCursor >= (nCmdIndex-1)) return;

nCmdCursor ++;

// 清除掉现在所有的输入

App_Console_OnDoubleEsc();

char* pCmdHistory = &szCmdHistory[nCmdCursor][0];

memcpy(szCmdNow,pCmdHistory,MAX_CMD_LEN);

nCmdInputCount = strlen(szCmdNow);

nCmdInputCursor= nCmdInputCount;

write(STDOUT_FILENO,szCmdNow,nCmdInputCount);

}

static void App_Console_OnLeft()

{

if(nCmdInputCursor > 0)

{

char c = '/b';

write(STDOUT_FILENO,&c,1);

nCmdInputCursor--;

}

}

static void App_Console_OnRight()

{

if(nCmdInputCursor < nCmdInputCount)

{

char* pCmd = szCmdNow;

char c = pCmd[nCmdInputCursor];

write(STDOUT_FILENO,&c,1);

nCmdInputCursor++;

}

}

static void App_Console_OnEnter()

{

szCmdNow[nCmdInputCount] = '/0';

char szTemp[] = {"/r/n"};

write(STDOUT_FILENO,szTemp,strlen(szTemp));

nCmdInputCount = 0;

nCmdInputCursor = 0;

if(strlen(szCmdNow) == 0) return;

if(nCmdIndex == MAX_CMD_HISTORY) // 命令队列满了,移动

{

char szTempCmd[MAX_CMD_HISTORY][MAX_CMD_LEN];

memcpy(szTempCmd,&szCmdHistory[1][0],MAX_CMD_LEN*(MAX_CMD_HISTORY-1));

memcpy(szCmdHistory,szTempCmd,MAX_CMD_LEN*(MAX_CMD_HISTORY-1));

nCmdIndex = MAX_CMD_HISTORY-1;

nCmdCursor = nCmdIndex;

}

memcpy(szCmdHistory[nCmdIndex],szCmdNow,MAX_CMD_LEN);

nCmdIndex++;

nCmdCursor = nCmdIndex;

// 解析命令

App_Console_ParseCmd(szCmdNow);

}

static void App_Console_CmdLoop()

{

BOOL bGetEnter = FALSE;

while(TRUE)

{

// 读取一个console输入

UINT32 nReturn = 0;

char input;

nReturn = App_Console_ReadInput (&input);

if(nReturn > 0)

{

switch(waitKeyState)

{

case WKS_WAIT :

if(isprint(input))// 可打印字符

App_Console_OnPrintChar(input);

else

{

if(input == KEY_BACKSPACE)

App_Console_OnBackspace();

else if(input == KEY_DEL)

App_Console_OnDel();

else if(input == KEY_ENTER)

{

App_Console_OnEnter();

bGetEnter = TRUE;

}

else if(input == '/x1b')

waitKeyState = WKS_RECV1B;

else

waitKeyState = WKS_WAIT;

}

break;

case WKS_RECV1B:

if(input == '/x1b') // 按了ESC 又按了方向键,或者是 ESC

{

//App_Console_OnDoubleEsc();

waitKeyState = WKS_RECV1B;

}

else

if(input == '[') //可能为 上下左右 4个键

waitKeyState = WKS_UDLR;

else//下面的情况为 按了 ESC 键之后,按了其他的键的处理

{

if(isprint(input)) App_Console_OnPrintChar(input);

waitKeyState = WKS_WAIT;

}

break;

case WKS_UDLR:

if(input == 'A')// 上

App_Console_OnUp();

else if(input == 'B')// 下

App_Console_OnDown();

else if(input == 'D')// 左

App_Console_OnLeft();

else if(input == 'C')// 右

App_Console_OnRight();

else

{

if(isprint(input)) App_Console_OnPrintChar(input);

}

waitKeyState = WKS_WAIT;

break;

default:

break;

}

}

if(bGetEnter)

{

break;

}

}

}

void App_Console_Start()

{

// 清空 sdtout 缓冲

fflush(stdout);

fflush(stdin);

char szTemp[] = {"/r/nStart TR Console.../r/n/r/n"};

write(STDOUT_FILENO,szTemp,strlen(szTemp));

while(TRUE)

{

write(STDOUT_FILENO,szPrompt,strlen(szPrompt));

App_Console_CmdLoop();

}

}

// 解析命令

static void App_Console_ParseCmd(const char* pCmd)

{

int length = strlen(pCmd);

// 全部转小写

int i=0;

char szTempCmd[MAX_CMD_LEN];

for (i=0; i < length; i++) szTempCmd[i] = tolower(pCmd[i]);

// 将输入的命令各个 part 分开

char szPart[MAX_PAR_COUNT][MAX_CMD_LEN];

int nPartCount = 0;

int nPartCursor = 0;

int nCmdCursor = 0;

memset(szPart,0,sizeof(szPart));

while(TRUE)

{

if(nCmdCursor == length)

{

if(nPartCursor > 0)

{

nPartCount++;

nPartCursor = 0;

}

break;

}

if( (szTempCmd[nCmdCursor] == ',') || (szTempCmd[nCmdCursor] == ' ') ) // part 分割符

{

szPart[nPartCount][nPartCursor] = '/0';

nPartCount++;

nPartCursor = 0;

}

else

{

szPart[nPartCount][nPartCursor] = szTempCmd[nCmdCursor];

nPartCursor++;

}

nCmdCursor++;

}

App_Test_OnCmd(szPart,nPartCount);

}

命令实现头文件(app_test.h)

#ifndef __APP_TEST_H__

#define __APP_TEST_H__

#ifdef __cplusplus

extern"C"

{

#endif

#include "type_def.h"

#define MAX_CMD_LEN 512

voidApp_Test_OnCmd(charszPart[][MAX_CMD_LEN],intnPartCount);

#ifdef __cplusplus

}

#endif

#endif#ifndef __APP_TEST_H__

#define __APP_TEST_H__

#ifdef __cplusplus

extern "C"

{

#endif

#include "type_def.h"

#define MAX_CMD_LEN 512

void App_Test_OnCmd(char szPart[][MAX_CMD_LEN],int nPartCount);

#ifdef __cplusplus

}

#endif

#endif

命令实现c文件(app_test.c)

#include "app_test.h"

#include "stapp_main.h"

#include "app_qam.h"

#include "api_av.h"

#include "api_video.h"

#include "api_audio.h"

#include "api_pcr.h"

staticvoidApp_Test_OnHelp();

staticvoidApp_Test_OnWriteReg8(charszPart[][MAX_CMD_LEN],intnPartCount);

staticvoidApp_Test_OnReadReg8(charszPart[][MAX_CMD_LEN],intnPartCount);

staticvoidApp_Test_OnQamConnect(charszPart[][MAX_CMD_LEN],intnPartCount);

staticvoidApp_Test_OnAVPlayMpeg(charszPart[][MAX_CMD_LEN],intnPartCount);

staticvoidApp_Test_OnAVStop();

staticvoidApp_Test_OnVolumeSet(charszPart[][MAX_CMD_LEN],intnPartCount);

staticvoidApp_Test_OnMute();

staticvoidApp_Test_OnUnmute();

staticvoidApp_Test_OnDENCRegDum();

staticvoidApp_Test_OnDENCRegSet(charszPart[][MAX_CMD_LEN],intnPartCount);

voidApp_Test_OnCmd(charszPart[][MAX_CMD_LEN],intnPartCount)

{

// 这里处理私有的命令

if(nPartCount == 0)return;

if( strcmp(szPart[0],"help") == 0)

{

App_Test_OnHelp();

}

elseif( strcmp(szPart[0],"writereg8") == 0)

{

if(nPartCount > 2) App_Test_OnWriteReg8(szPart,nPartCount);

}

elseif( strcmp(szPart[0],"readreg8") == 0)

{

if(nPartCount > 1) App_Test_OnReadReg8(szPart,nPartCount);

}

elseif( strcmp(szPart[0],"qamconnect") == 0)

{

if(nPartCount > 1) App_Test_OnQamConnect(szPart,nPartCount);

}

elseif( strcmp(szPart[0],"avplaympeg") == 0)

{

if(nPartCount > 1) App_Test_OnAVPlayMpeg(szPart,nPartCount);

}

elseif( strcmp(szPart[0],"avstop") == 0)

{

App_Test_OnAVStop();

}

elseif( strcmp(szPart[0],"volumeset") == 0)

{

if(nPartCount > 1) App_Test_OnVolumeSet(szPart,nPartCount);

}

elseif( strcmp(szPart[0],"mute") == 0)

{

App_Test_OnMute();

}

elseif( strcmp(szPart[0],"unmute") == 0)

{

App_Test_OnUnmute();

}

elseif( strcmp(szPart[0],"dencregdump") == 0)

{

App_Test_OnDENCRegDum();

}

elseif( strcmp(szPart[0],"dencregset") == 0)

{

if(nPartCount > 1) App_Test_OnDENCRegSet(szPart,nPartCount);

}

}

staticvoidApp_Test_OnHelp()

{

printf("**************************************************************/n");

printf("* Help        PARAM MUST 0 MAX 0 Eg. help/n");

printf("* WriteReg8   PARAM MUST 2 MAX 2 Eg. WriteReg8 0x1920C114 128/n");

printf("* ReadReg8    PARAM MUST 1 MAX 1 Eg. ReadReg8 0x1920C114/n");

printf("* QamConnect  PARAM MUST 1 MAX 3 Eg. QamConnect 546000/n");

printf("* AVPlayMpeg  PARAM MUST 1 MAX 3 Eg. AVPlayMpeg 64 63 32/n");

printf("* AVStop      PARAM MUST 0 MAX 0 Eg. AVStop/n");

printf("* VolumeSet   PARAM MUST 1 MAX 1 Eg. VolumeSet 63/n");

printf("* Mute        PARAM MUST 0 MAX 0 Eg. Mute/n");

printf("* Unmute      PARAM MUST 0 MAX 0 Eg. Unmute/n");

printf("* DENCRegDump PARAM MUST 0 MAX 0 Eg. DENCRegDump/n");

printf("* DENCRegSet  PARAM MUST 1 MAX 1 Eg. DENCRegSet 1/n");

printf("*************************************************************/n");

}

staticvoidApp_Test_OnWriteReg8(charszPart[][MAX_CMD_LEN],intnPartCount)

{

char* pAddress = &szPart[1][0];

char* pValue = &szPart[2][0];

DWORDdwAddress = 0;

UINT8 nValue = atoi(pValue);

sscanf(pAddress,"0x%08x",&dwAddress);

SYS_WriteRegDev8(dwAddress,nValue);

}

staticvoidApp_Test_OnQamConnect(charszPart[][MAX_CMD_LEN],intnPartCount)

{

char* pFreq = &szPart[1][0];

UINT32nFreq = atoi(pFreq);

UINT32nSymbolRate = 6875;

T_DMD_Modulation nQAMMode = QAM_64;

if(nPartCount > 2)

{

char* pSymbolRate = &szPart[2][0];

nSymbolRate = atoi(pSymbolRate);

}

if(nPartCount > 3)

{

char* pQAMMode = &szPart[3][0];

nQAMMode = atoi(pQAMMode);

}

App_Qam_Locking(TRUE,nFreq,nSymbolRate,nQAMMode);

}

staticvoidApp_Test_OnAVPlayMpeg(charszPart[][MAX_CMD_LEN],intnPartCount)

{

UINT16 nVideoPid = 0xFFFF;

UINT16 nAudioPid = 0xFFFF;

UINT16 nPcrPid = 0xFFFF;

char* pAudioPid = &szPart[1][0];

nAudioPid = atoi(pAudioPid);

if(nPartCount > 2)

{

char* pVideoPid = &szPart[2][0];

nVideoPid = atoi(pVideoPid);

}

if(nPartCount > 3)

{

char* pPcr = &szPart[3][0];

nPcrPid = atoi(pPcr);

}

Api_Av_Stop();

Api_Av_Start(nAudioPid,STREAMTYPE_MP2A,nVideoPid,STREAMTYPE_MP2V,nPcrPid);

}

staticvoidApp_Test_OnVolumeSet(charszPart[][MAX_CMD_LEN],intnPartCount)

{

UINT16 nVolume = 0;

char* pVolume = &szPart[1][0];

nVolume = atoi(pVolume);

Api_Audio_Volume_Set(nVolume);

}

staticvoidApp_Test_OnMute()

{

Api_Audio_Mute();

}

staticvoidApp_Test_OnUnmute()

{

Api_Audio_Unmute();

}

staticvoidApp_Test_OnAVStop()

{

Api_Av_Stop();

}

staticvoidApp_Test_OnDENCRegDum()

{

printf("* Brightness   0x1920C114 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C114));

printf("* Contrast     0x1920C118 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C118));

printf("* Saturation   0x1920C11c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C11c));

printf("* CHROMA_COEF0 0x1920C120 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C120));

printf("* CHROMA_COEF1 0x1920C124 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C124));

printf("* CHROMA_COEF2 0x1920C128 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C128));

printf("* CHROMA_COEF3 0x1920C12c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C12c));

printf("* CHROMA_COEF4 0x1920C130 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C130));

printf("* CHROMA_COEF5 0x1920C134 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C134));

printf("* CHROMA_COEF6 0x1920C138 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C138));

printf("* CHROMA_COEF7 0x1920C13c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C13c));

printf("* CHROMA_COEF8 0x1920C140 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C140));

printf("* LUM_COEF0    0x1920C148 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C148));

printf("* LUM_COEF1    0x1920C14c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C14c));

printf("* LUM_COEF2    0x1920C150 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C150));

printf("* LUM_COEF3    0x1920C154 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C154));

printf("* LUM_COEF4    0x1920C158 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C158));

printf("* LUM_COEF5    0x1920C15c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C15c));

printf("* LUM_COEF6    0x1920C160 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C160));

printf("* LUM_COEF7    0x1920C164 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C164));

printf("* LUM_COEF8    0x1920C168 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C168));

printf("* LUM_COEF9    0x1920C16c value is 0x%02x/n",SYS_ReadRegDev8(0x1920C16c));

printf("* CFG9         0x1920C144 value is 0x%02x/n",SYS_ReadRegDev8(0x1920C144));

}

staticvoidApp_Test_OnDENCRegSet(charszPart[][MAX_CMD_LEN],intnPartCount)

{

UINT16 nScheme = 1;

char* pScheme = &szPart[1][0];

nScheme = atoi(pScheme);

switch(nScheme)

{

case1:

break;

case2:

break;

case3:

break;

case4:

break;

default:

break;

}

}

staticvoidApp_Test_OnReadReg8(charszPart[][MAX_CMD_LEN],intnPartCount)

{

char* pAddress = &szPart[1][0];

DWORDdwAddress = 0;

sscanf(pAddress,"0x%08x",&dwAddress);

printf("* 0x%08x value is 0x%02x/n",dwAddress,SYS_ReadRegDev8(dwAddress));

}0b1331709591d260c1c78e86d0c51c18.png

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐