📄 parse.c
字号:
#include "as31glue.h"#include "printf.h"#include "main.h"#include "parse.h"#include "display.h"/* definition of the configure table */struct lexcfg { code char *string; void (*function) (unsigned char) reentrant; event_t event; unsigned char button_cfg;};/* This table is the complete list of commands the serial input * parser will recognize. The input parser operates similar to * a command line, where your input is stored in a buffer and * the parser only attempts to act on it when it receices an * end-of-line character, either CR or LF (ascii 13 or 10). * * The parser also recognizes CTRL-C (ascii 3) as an abort of * any previous entry and the input buffer is immediately * flushed. When sending commands to the player after a period * of inactivity, you might want to send a CTRL-C to clear any * "garbage" that might have been received and could be sitting * in the input buffer. * */static code struct lexcfg commandlist[] = {/*Cmd String Funtion Param to Pass Button to Config *//*---------- ------- ------------- ---------------- */{"NEXT", parse_event, E_NEXT, BUTTON_6 | B_UP},{"PREVIOUS", parse_event, E_PREV, BUTTON_4 | B_UP},{"PLAY", parse_event, E_PLAY_PAUSE, BUTTON_5 | B_DOWN},{"RANDOM", parse_event, E_PLAYMODE_UP, BUTTON_NONE},{"INC", parse_event, E_INC, BUTTON_0 | B_DOWN | B_REPEAT},{"DEC", parse_event, E_DEC, BUTTON_1 | B_DOWN | B_REPEAT},{"NXT_LIST", parse_event, E_NEXT_LIST, BUTTON_3 | B_DOWN | B_REPEAT},{"PRV_LIST", parse_event, E_PREV_LIST, BUTTON_2 | B_DOWN | B_REPEAT},{"UP", parse_event, E_UP, BUTTON_7 | B_DOWN | B_REPEAT},{"DOWN", parse_event, E_DOWN, BUTTON_10 | B_DOWN | B_REPEAT},{"RIGHT", parse_event, E_RIGHT, BUTTON_9 | B_DOWN | B_REPEAT},{"LEFT", parse_event, E_LEFT, BUTTON_8 | B_DOWN | B_REPEAT},{"ENTER", parse_event, E_ENTER, BUTTON_11 | B_DOWN},{"FORWARD", parse_event, E_FWD, BUTTON_6 | B_REPEAT},{"REVERSE", parse_event, E_REV, BUTTON_4 | B_REPEAT},{"VOL+", parse_event, E_VOL_UP, BUTTON_NONE},{"VOL-", parse_event, E_VOL_DOWN, BUTTON_NONE},{"PLMODE+", parse_event, E_PLAYMODE_UP, BUTTON_NONE},{"PLMODE-", parse_event, E_PLAYMODE_DOWN,BUTTON_NONE},{"DEBUG", parse_toggle_debug, 0, BUTTON_NONE},{"QUIT", parse_quit, 0, BUTTON_NONE},{"PLAY_FILE", parse_playfile, 0, BUTTON_NONE}};/* pushbutton actions not defined above should be specified here * so that they will be initialized not to send anything */static code unsigned char undefined_buttons[] = { BUTTON_0 | B_UP, BUTTON_1 | B_UP, BUTTON_2 | B_UP, BUTTON_3 | B_UP, BUTTON_4 | B_DOWN, BUTTON_5 | B_UP | B_REPEAT, BUTTON_6 | B_DOWN, BUTTON_7 | B_UP, BUTTON_8 | B_UP, BUTTON_9 | B_UP, BUTTON_10 | B_UP, BUTTON_11 | B_UP | B_REPEAT};// funtion prototypes#pragma CALLEE-SAVES hex32static unsigned long hex32(xdata char *str) _naked;/* The input buffer used to store incoming commands */#define INPUT_BUFFER_SIZE 64static xdata char input_buffer[INPUT_BUFFER_SIZE];static data unsigned char in_num;/* event handlers - these are called when the parser detects one * of the input commands (which ones is called depends on the * third column in the config table above) */static void parse_event(unsigned char this_event) reentrant{ add_new_event(this_event);}static void parse_toggle_debug(unsigned char unused) reentrant{ unused; _asm cpl _debug _endasm;}static void parse_quit(unsigned char unused) reentrant{ unused; _asm clr ea ljmp 0x006D ;return to PM2 _endasm;}static void parse_playfile(unsigned char unused) reentrant{ unused; if (in_num == 18) { print("\r\nPlay_File command: "); print_hex32(hex32(input_buffer + 10)); print_crlf(); e_play_selected_file = state_to_playlist(hex32(input_buffer + 10)); add_new_event(E_PLAY_SELECTED); }}void parse_init(void){ in_num = 0;}#define COUT 0x2030#define CIN 0x2032#define PSTR 0x2038#define AUXR1 0xA2#pragma CALLEE-SAVES is_input_cmd,is_uninitialized_lcd_button#pragma SAVE#pragma LESS_PEDANTIC/* return 1 if the command in the input buffer matches the specified string */static charis_input_cmd(code char *str) _naked{ str; // passed in DPTR _asm inc AUXR1 mov dptr, #_input_bufferis_cmd_loop: movx a, @dptr ;fetch byte of input string inc dptr cjne a, #32, is_cmd_2 clr a ;treat space as end of input stringis_cmd_2: mov b, a inc AUXR1 clr a movc a, @a+dptr ;fetch byte of command string inc dptr inc AUXR1 cjne a, b, is_not_cmd jnz is_cmd_loop inc AUXR1 mov dpl, #1 retis_not_cmd: inc AUXR1 mov dpl, #0 ret _endasm;}/* if the buffer looks like B0_DOWN to B11_DOWN, return 1 */static charis_uninitialized_lcd_button(void) _naked{ _asm mov dptr, #_input_buffer movx a, @dptr cjne a, #0x42, 00002$ inc dptr movx a, @dptr anl a, #0xF0 cjne a, #0x30, 00002$ inc dptr movx a, @dptr anl a, #0xFE cjne a, #0x30, 00001$ inc dptr00001$: movx a, @dptr cjne a, #0x5F, 00002$ inc dptr movx a, @dptr cjne a, #0x44, 00002$ inc dptr movx a, @dptr cjne a, #0x4F, 00002$ inc dptr movx a, @dptr cjne a, #0x57, 00002$ inc dptr movx a, @dptr cjne a, #0x4E, 00002$ inc dptr movx a, @dptr jnz 00002$ mov dpl, #1 ret00002$: mov dpl, #0 ret _endasm;}#pragma RESTORE/* check the input buffer for all known commands, and if one matches * call its event routine */static void parse_line(void){ unsigned char i; for(i=0; i < sizeof(commandlist)/sizeof(struct lexcfg); i++) { if (is_input_cmd(commandlist[i].string)) { (*commandlist[i].function)(commandlist[i].event); return; } } //print("\r\nUnrecognized command"); //print_str(input_buffer); //print_crlf(); if (is_uninitialized_lcd_button()) { parse_event_setup(); // reinitialize the LCD and state associated with it lcd_screen_dynamic(1); }}//static void parse_debug(void)//{// input_buffer[in_num] = 0;// print("input buffer: '");// print_str(input_buffer);// print("'\r\n");//}/* Fetch and new serial input, store it into the input_buffer, and * handle CTRL-C and end-of-line characters, and call parse_line * when we've received a complete command */void parse_serial_input(void){ _asmparse_loop: lcall CIN ;get next character from serial port jnz parse_char_3 //lcall _parse_debug ret ;done when no more inputparse_char_3: cjne a, #3, parse_char_10 ;CTRL-C flushes input bufferparse_flush_buffer: mov _in_num, #0 sjmp parse_loopparse_char_10: cjne a, #10, parse_char_13 ;NL acts as end-of-line sjmp parse_eolparse_char_13: cjne a, #13, parse_char_any ;CR also acts as end-of-line sjmp parse_eolparse_char_any: cjne a, #97, toup1 ;convert to uppercase if lowercasetoup1: jc updone cjne a, #123, toup2toup2: jnc updone add a, #224 ;-32 to convert to uppercaseupdone: mov r2, a ;keep input char in r2 lcall COUT ;echo the char mov a, _in_num cjne a, #(INPUT_BUFFER_SIZE-1), parse_buffer_ok sjmp parse_loop ;discard buffer overflowparse_buffer_ok: lcall parse_store inc _in_num sjmp parse_loopparse_eol: mov a, _in_num jz parse_loop ;ignore zero-length input mov r2, #0 lcall parse_store ;NULL terminate input_buffer lcall _parse_line sjmp parse_flush_bufferparse_store: add a, #_input_buffer mov dpl, a clr a addc a, #_input_buffer >> 8 mov dph, a mov a, r2 movx @dptr, a ;store input char into input_buffer ret _endasm;}/* Configure one pushbutton to send a string when it is pressed */#pragma CALLEE-SAVES button_setupstatic void button_setup(code char *str, unsigned char n){ //printf("\\H%c%s ", (char)n, str); str; // passed in DPTR n; // passed @ _button_setup_PARM_2 _asm push dpl push dph mov a, #0x5C // 0x5C = '\' lcall COUT mov a, #0x48 // 0x48 = 'H' lcall COUT mov dptr, #_button_setup_PARM_2 movx a, @dptr lcall COUT pop dph pop dpl mov b, #1200001$: clr a movc a, @a+dptr jz 00002$ lcall COUT inc dptr djnz b, 00001$ ret00002$: mov a, #32 lcall COUT djnz b, 00002$ _endasm;}/* Configure all 12 pushbuttons to send the strings specified in the * config table at the top of this file, and set all the undefined * button presses to send nothing */void parse_event_setup(void){ unsigned char i, num, cfg; static code char *nil_str=""; for(i=0; i < sizeof(commandlist)/sizeof(struct lexcfg); i++) { cfg = commandlist[i].button_cfg; num = cfg & 15; if (num != BUTTON_NONE) { if (cfg & B_DOWN) { button_setup(commandlist[i].string, num + 0x30); } if (cfg & B_UP) { button_setup(commandlist[i].string, num + 0x40); } if (cfg & B_REPEAT) { button_setup(commandlist[i].string, num + 0x50); } } } for(i=0; i < sizeof(undefined_buttons); i++) { cfg = undefined_buttons[i]; num = cfg & 15; if (cfg & B_DOWN) { button_setup(nil_str, num + 0x30); } if (cfg & B_UP) { button_setup(nil_str, num + 0x40); } if (cfg & B_REPEAT) { button_setup(nil_str, num + 0x50); } }}#pragma SAVE#pragma LESS_PEDANTICstatic unsigned longhex32(xdata char *str) _naked{ str; // passed in DPTR _asm lcall hex_2digits push acc lcall hex_2digits push acc lcall hex_2digits push acc lcall hex_2digits mov dpl, a pop dph pop b pop acc ret // convert 2 characters and return 8 bit number in Acchex_2digits: movx a, @dptr inc dptr lcall asc2hex swap a mov b, a movx a, @dptr inc dptr lcall asc2hex orl a, b ret // convert character 0-9,A-F to number 0-15 // copied from paulmon21.asmasc2hex: add a, #208 jnc hex_not add a, #246 jc hex_maybe add a, #10 rethex_maybe: add a, #249 jnc hex_not add a, #250 jc hex_not add a, #16 rethex_not: clr a // return zero if none hex character ret _endasm;}#pragma RESTORE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -