⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse.c

📁 一款MP3 Player Firmware 的原代码,非常有参考价值
💻 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 + -