;;*************************************** ;;***** RS-232 keyboard monitor ;;*************************************** ;To be included into a program under test ;************************************ ; receive ISR and keyboard monitor ;returns a user char UNLESS the char is "esc" or entry was via rcall .def RXtemp=r29 ;a temp register .def RXparm=r28 ;subroutine parameter .def RXsave=r27 ;save the SREG .equ npush=5 ;the number of saved registers in RXisr RXisr: ;save processor status push ZH push ZL push RXtemp push RXparm push RXsave in RXsave, SREG sbis USR, RXC ;is a char available rjmp RXcmd ;if not go to cmd handler in RXparm, UDR ;get the character cpi RXparm, 0x1b ;is the char an "esc" breq RXcmd ;if so go to cmd handler mov RXchar, RXparm ;if not then this is a user char RXexit: out SREG, RXsave ;restore proc status pop RXsave pop RXparm ;restore program state pop RXtemp pop ZL pop ZH reti ;back to pgm ; ; ; monitor command interperter RXcmd: ldi RXparm, 0x0d ;emit "cr" for a prompt rcall RXputc ldi RXparm, 0x0a ;emit "lf" for a prompt rcall RXputc ldi RXparm, '>' ;emit ">" for a prompt rcall RXputc ;wait for a command char rcall RXgetc ;is it a go command? RXgo: cpi RXparm, 'g' ;if so return to user code breq RXexit ;is it a reg read command? RXreg: cpi RXparm, 'r' ;dump a register brne RXmem rcall RXputc ;echo the 'r' rcall RXget2digit ;find out which reg cpi RXparm, 27 ;is the reg stored on the stack brge _stkreg mov ZL, RXparm ;if not, just read it back clr ZH ld RXparm, Z ;remember that 0-1f is reg rcall RXput2char rjmp RXcmd _stkreg:in ZL, SPL ;if the reg is stacked compute the address in ZH, SPH ;on the stack subi RXparm, 27-1 ;regs were stacked in numerical order add ZL, RXparm ;stack offset clr RXparm adc ZH, RXparm ld RXparm, Z rcall RXput2char rjmp RXcmd ;memory read RXmem: cpi RXparm, 'm' brne RXio rcall RXputc ;echo rcall RXget2digit ;get a 4 digit address mov ZH, RXparm rcall RXget2digit mov ZL, RXparm ld RXparm, Z ;load mem data rcall RXput2char rjmp RXcmd ;i/o register read RXio: cpi RXparm, 'i' brne RXsreg rcall RXputc ;echo rcall RXget2digit subi RXparm, -0x20 ;i/o register offset mov ZL, RXparm ;pointer to i/o reg clr ZH ld RXparm, Z ;now get it rcall RXput2char rjmp RXcmd ;get SREG RXsreg: cpi RXparm, 's' brne RXpc rcall RXputc ;echo mov Rxparm, RXsave ;get the saved SREG rcall RXput2char rjmp RXcmd ;get the program counter RXpc: cpi RXparm, 'p' brne RXhuh rcall RXputc ;echo in ZL, SPL ;get prog counter from the stack in ZH, SPH ldd RXparm, Z+npush+1 ;stack offset to high byte of PC rcall RXput2char ldd RXparm, Z+npush+2 ;stack offset to low byte of PC rcall RXput2char2 rjmp RXcmd ;unknown command trap RXhuh: ldi RXparm, '?' rcall RXputc rjmp RXcmd ; ;utility routine to output one char ;enter with char in RXparm RXputc: sbis USR, UDRE ;wait until clear then send one char rjmp RXputC out UDR, RXparm ret ;utility routine to input one char ;exit with char in RXparm RXgetc: sbis USR, RXC ;wait until ready then get one char rjmp RXgetc in RXparm, UDR ret ;utility routine to make a ascii char into a hex value ;enter with char in RXparm RXcharTohex: cpi RXparm, 'a' brge _aboveA cpi RXparm, '0' ;error check-- is digit <'0'? brge _n1 rjmp RXcmd _n1: cpi RXparm, ':' ;error check -- is digit <':' brlt _n2 rjmp RXcmd ;if here then digit is 0 to 9 _n2: subi RXparm, '0' ret _aboveA: cpi RXparm, 'g' ;error check -- is digit>'f' brlt _ab1 rjmp RXcmd _ab1: subi RXparm, 'a'-10 ret ;utility routine to input rwo ascii chars and ; convert into a hex value returned in RXparm RXget2digit: rcall RXgetc ;get the highorder reg # nibble rcall RXputc ;echo it rcall RXcharTohex ;convert to hex swap RXparm ;make it the highorder bits mov RXtemp, RXparm ;and save it rcall RXgetc ;get the loworder reg # nibble rcall RXputc rcall RXcharTohex or RXparm, RXtemp ;combine high and low nibbles ret ;utility routine to output two ascii chars given a ;hex value in RXparm RXput2char: mov RXtemp, RXparm ;a copy ldi RXparm, '=' ;a delimiter rcall RXputc ;print the delimiter mov RXparm, RXtemp ;restore input RXput2char2: ;entry used only for the second byte of PC dump mov RXtemp, RXparm andi RXparm, 0xf0 ;mask high digits swap RXparm ;and make them loworder cpi RXparm, 10 ;numbers or letters? brge _f8f1 subi RXparm, -'0' ;convert a numeric digit to ascii rjmp _f8tx1 _f8f1: subi RXparm, -'a'+10 ;convert a letter to ascii _f8tx1: rcall RXputc mov RXparm, RXtemp ;now repeat for the other digit andi RXparm, 0x0f cpi RXparm, 10 brge _f8f2 subi RXparm, -'0' rjmp _f8tx2 _f8f2: subi RXparm, -'a'+10 _f8tx2: rcall RXputc ret ;***********************************