#include "cli.h" extern void *cli_cmd$$Base; extern void *cli_cmd$$Limit; void cli_write(cli_t *p_cli) { for (int i = 0; i < p_cli->chartemplen; i++) p_cli->char_put(p_cli->tempbuf[i]); } int ringbufcmp(unsigned char *ringbuf, unsigned char ringbufis, const char *cr, int len) { unsigned char i = ringbufis; for (int j = 0; j < len; j++) { if (ringbuf[i] != cr[j]) return 1; i++; } return 0; } /** * @brief CLI colors for @ref nrf_cli_fprintf function. */ #define NRF_CLI_DEFAULT NRF_CLI_VT100_COLOR_DEFAULT /**< Turn off character attributes. */ #define NRF_CLI_NORMAL NRF_CLI_VT100_COLOR_WHITE /**< Normal color printf. */ #define NRF_CLI_INFO NRF_CLI_VT100_COLOR_GREEN /**< Info color printf. */ #define NRF_CLI_OPTION NRF_CLI_VT100_COLOR_CYAN /**< Option color printf. */ #define NRF_CLI_WARNING NRF_CLI_VT100_COLOR_YELLOW /**< Warning color printf. */ #define NRF_CLI_ERROR NRF_CLI_VT100_COLOR_RED /**< Error color printf. */ static void vt100_color_set(cli_t *p_cli, nrf_cli_vt100_color_t color) { if (p_cli->col.col == color) { return; } p_cli->col.col = color; cli_printf(p_cli, "\033[3%dm", color); //设置颜色 } static void vt100_bgcolor_set(cli_t *p_cli, nrf_cli_vt100_color_t bgcolor) { if (p_cli->col.bgcol == bgcolor) { return; } p_cli->col.bgcol = bgcolor; cli_printf(p_cli, "\033[4%dm", bgcolor); //设置颜色 } static inline void vt100_colors_store(cli_t *p_cli, nrf_cli_vt100_colors_t *p_color) { memcpy(p_color, &p_cli->col, sizeof(nrf_cli_vt100_colors_t)); } static void vt100_colors_restore(cli_t *p_cli, nrf_cli_vt100_colors_t const *p_color) { vt100_color_set(p_cli, p_color->col); vt100_bgcolor_set(p_cli, p_color->bgcol); } #define print_name cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_GREEN, "\033[1m \r%s", p_cli->p_name) void Tab_pcs(cli_t *p_cli) { int temp = 0; cli_section_cmd_t *stmy; if (p_cli->cmdwp == p_cli->cmdrp) { cli_printf(p_cli, "\n\r\t"); for (int p = (unsigned int)&cli_cmd$$Base; p < (unsigned int)&cli_cmd$$Limit; p += sizeof(cli_section_cmd_t)) { stmy = ((cli_section_cmd_t *)p); cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "%s\t", stmy->_p_cmd_str); temp++; if (temp % 5 == 0) cli_printf(p_cli, "\n\r\t"); } cli_printf(p_cli, "\n"); print_name; } else { for (int p = (unsigned int)&cli_cmd$$Base; p < (unsigned int)&cli_cmd$$Limit; p += sizeof(cli_section_cmd_t)) { stmy = ((cli_section_cmd_t *)p); if (ringbufcmp(p_cli->cmdbuf, p_cli->cmdrp, stmy->_p_cmd_str, p_cli->cmdwp - p_cli->cmdrp) == 0) { for (int i = p_cli->cmdwp - p_cli->cmdrp; i < strlen(stmy->_p_cmd_str); i++) p_cli->cmdbuf[p_cli->cmdwp++] = stmy->_p_cmd_str[i]; cli_printf(p_cli, "\n\r"); print_name; cli_printf(p_cli, "%s", stmy->_p_cmd_str); break; } } } } void Backspace_pcs(cli_t *p_cli) { if (p_cli->cmdwp != p_cli->cmdrp) { NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEAREOL); //清除光标后面的内容 p_cli->cmdwp--; } else { cli_printf(p_cli, "\033[1C"); //光标右移动 } } void Delete_pcs(cli_t *p_cli) { } #define Historyshowlen 50 void Up_pcs(cli_t *p_cli) { unsigned char showH_p = 0; unsigned char fir = 1; nrf_cli_vt100_colors_t col; if (p_cli->cmdbuf[(unsigned char)(p_cli->historyrp - 1)] != '*') return; if (p_cli->historyrp != p_cli->cmdwp) { p_cli->cmdwp = p_cli->cmdrp; cli_printf(p_cli, "\r"); print_name; cli_printf(p_cli, "\033[K"); } for (unsigned char i = (unsigned char)p_cli->historyrp - 2; i != (unsigned char)(p_cli->historyrp - Historyshowlen); i--) { if (p_cli->cmdbuf[i] == '*') { if (fir) { for (int j = 0; j < showH_p; j++) { p_cli->char_put(p_cli->cmdbuf[(unsigned char)(i + j + 1)]); p_cli->cmdbuf[p_cli->cmdwp++] = p_cli->cmdbuf[(unsigned char)(i + j + 1)]; } cli_printf(p_cli, "\033[s"); p_cli->char_put(' '); p_cli->historyrp = i + 1; fir = 0; vt100_colors_store(p_cli, &col); vt100_color_set(p_cli, NRF_CLI_VT100_COLOR_CYAN); p_cli->char_put('['); } else { for (int j = 0; j < showH_p; j++) p_cli->char_put(p_cli->cmdbuf[(unsigned char)(i + j + 1)]); p_cli->char_put(' '); } showH_p = 0; } else showH_p++; if ((p_cli->cmdbuf[i] == 0) || (i == p_cli->cmdwp)) break; } if (fir == 0) { p_cli->char_put(']'); vt100_colors_restore(p_cli, &col); cli_printf(p_cli, "\033[u"); } } void Down_pcs(cli_t *p_cli) { for (unsigned char j = 0; j < p_cli->cmdwp; j++) p_cli->char_put(p_cli->cmdbuf[j]); } void Left_pcs(cli_t *p_cli) { cli_printf(p_cli, "\033[1D"); } void Right_pcs(cli_t *p_cli) { cli_printf(p_cli, "\033[1C"); } #define ARGVCUNMAX 25 char *cmd_argv[ARGVCUNMAX]; //最多存放25个参数的指针 void cmd_pcs(cli_t *p_cli) { cli_section_cmd_t *stmy; int stmy_len = 0; char sgv_tag = 0; unsigned short agvc = 0; char argvtrg = 0; for (int p = (unsigned int)&cli_cmd$$Base; p < (unsigned int)&cli_cmd$$Limit; p += sizeof(cli_section_cmd_t)) { stmy = ((cli_section_cmd_t *)p); stmy_len = strlen(stmy->_p_cmd_str); if ( ((unsigned char)stmy_len == (unsigned char)(p_cli->cmdwp - p_cli->cmdrp))|| (((unsigned char)stmy_len < (unsigned char)(p_cli->cmdwp - p_cli->cmdrp))&&(p_cli->cmdbuf[(unsigned char)(p_cli->cmdrp + stmy_len)] == ' ')) ) { if (ringbufcmp(p_cli->cmdbuf, p_cli->cmdrp, stmy->_p_cmd_str, stmy_len) == 0) { cli_printf(p_cli, "\r\n"); if ((unsigned char)stmy_len == (unsigned char)(p_cli->cmdwp - p_cli->cmdrp)) { (*(cli_cmd_t *)(&(stmy->_p_cmd_hander)))(p_cli, 0, NULL); //调用没参数的命令 } else { agvc = 0; p_cli->cmdbuf[p_cli->cmdwp++] = ' '; //找出所有参数的指针 for (unsigned char i = (unsigned char)(p_cli->cmdrp + stmy_len); (unsigned char)i != p_cli->cmdwp; i++) { switch (sgv_tag) { case 0: if (p_cli->cmdbuf[i] != ' ') { cmd_argv[agvc++] = (char *)(&(p_cli->cmdbuf[i])); sgv_tag++; } break; default: if (p_cli->cmdbuf[i] == ' ') { p_cli->cmdbuf[i] = 0; sgv_tag = 0; } else if ((i == 255) && (p_cli->cmdbuf[0] != ' ')) //参数不连续 { argvtrg = 1; } break; } } if (argvtrg == 0) //没有出现参数不连续的情况 { //调用命令,带参数 (*(cli_cmd_t *)(&(stmy->_p_cmd_hander)))(p_cli, agvc, cmd_argv); } else { cli_fprintf(p_cli, NRF_CLI_ERROR, "\tPlase try once again! "); } if(agvc>0)p_cli->cmdwp = (unsigned char)((unsigned int)(&cmd_argv[agvc - 1][strlen(cmd_argv[agvc - 1])]) - (unsigned int)&p_cli->cmdbuf[0]); for (int i = 0; i < agvc; i++) { cmd_argv[i][strlen(cmd_argv[i])] = ' '; } } cli_printf(p_cli, "\n"); print_name; p_cli->cmdbuf[p_cli->cmdwp++] = '*'; for(unsigned char i=p_cli->cmdwp-1;i>p_cli->cmdrp-1;i--) { if(p_cli->cmdbuf[i]!= p_cli->cmdbuf[(unsigned char)(i-(p_cli->cmdwp-p_cli->cmdrp))]) { //添加到运行历史 p_cli->cmdrp = p_cli->cmdwp; return ; } } p_cli->cmdwp = p_cli->cmdrp; return; } } } p_cli->cmdbuf[p_cli->cmdwp] = 0; cli_fprintf(p_cli, NRF_CLI_ERROR, "\tCan not find cmd ["); for (unsigned char i = p_cli->cmdrp; i != p_cli->cmdwp; i++) p_cli->char_put(p_cli->cmdbuf[i]); cli_fprintf(p_cli, NRF_CLI_ERROR, "]\n"); print_name; p_cli->cmdwp = p_cli->cmdrp; } void Enter_pcs(cli_t *p_cli) { if (p_cli->cmdwp == p_cli->cmdrp) { print_name; } else { cmd_pcs(p_cli); } p_cli->historyrp = p_cli->cmdwp; } void F4_pcs(cli_t *p_cli) { NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CURSORHOME); NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEARSCREEN); print_name; } void F5_pcs(cli_t *p_cli) { Up_pcs(p_cli); cli_printf(p_cli, "\r\n"); Enter_pcs(p_cli); } void cli_process(cli_t *p_cli) { static unsigned char FN = 0; unsigned char key = 0; if (p_cli->char_ok()) { key = p_cli->char_get(); switch (key) { #if 1 case 0x08: //Backspace Backspace_pcs(p_cli); break; case 0x09: //Tab Tab_pcs(p_cli); break; case 0x0d: FN = 20; break; case 0x0a: //Enter if (FN == 20) { Enter_pcs(p_cli); FN = 0; } break; case 0x1B: //Esc FN = 1; break; case 'A': if (FN == 1) { Up_pcs(p_cli); FN = 0; } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case 'B': if (FN == 1) { Down_pcs(p_cli); FN = 0; } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case 'C': if (FN == 1) { Right_pcs(p_cli); FN = 0; } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case 'D': if (FN == 1) { Left_pcs(p_cli); FN = 0; } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case 'O': // if (FN == 1) FN = 2; else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case 'P': if (FN == 2) { FN = 0; p_cli->char_put('F'); p_cli->char_put('1'); } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case 'Q': if (FN == 2) { FN = 0; p_cli->char_put('F'); p_cli->char_put('2'); } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case 'R': if (FN == 2) { FN = 0; p_cli->char_put('F'); p_cli->char_put('3'); } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case 'S': if (FN == 2) { FN = 0; F4_pcs(p_cli); //F4按钮 } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case '[': FN = 1; break; case '0': if (FN == 2) FN = 9; else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case '1': if (FN == 2) FN = 10; else if (FN == 1) FN = 2; else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case '2': if (FN == 1) FN = 2; else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case '3': if (FN == 2) FN = 11; else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case '4': if (FN == 2) FN = 12; else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case '5': if (FN == 2) { FN = 5; } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case '7': if (FN == 2) { FN = 6; } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case '8': if (FN == 2) { FN = 7; } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case '9': if (FN == 2) { FN = 8; } else p_cli->cmdbuf[p_cli->cmdwp++] = key; break; case '~': switch (FN) { case 5: F5_pcs(p_cli); break; case 6: p_cli->char_put('F'); p_cli->char_put('6'); FN = 0; break; case 7: p_cli->char_put('F'); p_cli->char_put('7'); FN = 0; break; case 8: p_cli->char_put('F'); p_cli->char_put('8'); FN = 0; break; case 9: p_cli->char_put('F'); p_cli->char_put('9'); FN = 0; break; case 10: p_cli->char_put('F'); p_cli->char_put('1'); p_cli->char_put('0'); FN = 0; break; case 11: p_cli->char_put('F'); p_cli->char_put('1'); p_cli->char_put('1'); FN = 0; break; case 12: p_cli->char_put('F'); p_cli->char_put('1'); p_cli->char_put('2'); FN = 0; break; default: SEGGER_RTT_Write(0, &key, 1); break; } break; case 0x7f: //Delete Delete_pcs(p_cli); break; #endif default: p_cli->cmdbuf[p_cli->cmdwp++] = key; break; } } extern void recall_cmd_pcs(cli_t *p_cli); recall_cmd_pcs(p_cli); } void cli_exe_cmd(cli_t *p_cli,char *cmd) { int len =strlen(cmd); if(len>128)return; for(unsigned char i= 0;icmdbuf[p_cli->cmdwp++]=cmd[i]; } Enter_pcs(p_cli); } void clc_pcs(cli_t *p_cli, unsigned short argc, char **argv) { NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CURSORHOME); NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEARSCREEN); } CLI_CMD_REGISTER(clc, "clear sereen", clc_pcs); CLI_CMD_REGISTER(clear, "clear sereen", clc_pcs); void History_pcs(cli_t *p_cli, unsigned short argc, char **argv) { cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "[1]History"); } CLI_CMD_REGISTER(history, "Cli cmd history", History_pcs); void print_param_pcs(cli_t *p_cli, unsigned short argc, char **argv) { for (int i = 0; i < argc; i++) { cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "%s\r\n", argv[i]); } } CLI_CMD_REGISTER(print_param, "Cli cmd history", print_param_pcs); #define RECALL_CMD_LEN_MAX 30 unsigned char recall_cmd_buff[RECALL_CMD_LEN_MAX]; static int recall_cmd_buff_len=0; static unsigned int recall_cmd_pcs_interval = 0; static int recall_cmd_times = 0; static char allcall=0; void recall_cmd_pcs(cli_t *p_cli) { static unsigned int cun = 0; if ((recall_cmd_times > 0)||(allcall)) { if (cun >= recall_cmd_pcs_interval) { cun = 0; for(int i=0;icmdbuf[p_cli->cmdwp++]=recall_cmd_buff[i]; } cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "recall times %d ...\r\n",recall_cmd_times); Enter_pcs(p_cli); if(!allcall)recall_cmd_times--; } cun++; } } void recall_pcs(cli_t *p_cli, unsigned short argc, char **argv) { if (argc == 0) { recall_cmd_times = 0; allcall=0; cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "help: recall interval times cmd ..."); } else if (argc >= 3) { recall_cmd_pcs_interval = atoi(argv[0]); recall_cmd_times = atoi(argv[1]); if((recall_cmd_times==0)||(recall_cmd_pcs_interval==0)) { if((recall_cmd_times==0)&&(recall_cmd_pcs_interval!=0)&&(argv[1][0]=='*')) { allcall=1; } else { cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "help: recall interval times cmd ...\r\n"); cli_fprintf(p_cli, NRF_CLI_VT100_COLOR_CYAN, "interval and times is a number\r\n"); return ; } } recall_cmd_buff_len=0; for (int i = 2; i < argc; i++) { memcpy(&recall_cmd_buff[recall_cmd_buff_len],argv[i],strlen(argv[i])); recall_cmd_buff_len+=strlen(argv[i]); recall_cmd_buff[recall_cmd_buff_len++]=' '; } cli_printf(p_cli, "recall [ "); for(int i=0;ichar_put(recall_cmd_buff[i]); } if(allcall){cli_printf(p_cli, " ] interval =%d times= **** success\r\n",recall_cmd_pcs_interval); }else {cli_printf(p_cli, " ] interval =%d times= %d success\r\n",recall_cmd_pcs_interval,recall_cmd_times); }SEGGER_RTT_Write(0,recall_cmd_buff,recall_cmd_buff_len); } else { cli_printf(p_cli, "recall_pcs -> param err"); } } CLI_CMD_REGISTER(recall, "Cli cmd history", recall_pcs); char rttok(void) { if (SEGGER_RTT_HasKey()) return 1; return 0; } unsigned char rttget(void) { unsigned char buf[60]; SEGGER_RTT_Read(0, buf, 60); return buf[0]; } void rttput(unsigned char p) { unsigned char buf[60]; buf[0] = p; SEGGER_RTT_Write(0, buf, 1); } CLI_DEFINE(clirtt, "CLI^$:", rttok, rttget, rttput); int mai5n(void) { while (1) cli_process(&clirtt); }