; this copy is hacked to write to page 0Fxxxx when receiving ; an intel-hex download... so it hopefully work on Matt's ; 16-bit board layout. ;$pagewidth 132t ; This is a hacked copy of paulmon2 which is intended to work ; with the XA processor. Automatic baud rate detection is not ; supported, and the extras package is not avaialble. Flash ; ROM is not supported. Paulmon2 only understands the first 64k ; of memory, and only recognizes intel-hex with 64k address ; space. Due to differences in arrangement of the XA, Paulmon2 ; may crash if it receives invalid intel-hex code (untested). ; See comments in "dnld_ghex" for details about this. ; Other bugs may exist, but the system seems to work. ; Paulmon2 does NOT run in the XA's special 8051 compatibility ; mode. Paulmon2 shuts off the watchdog timer and runs all ; code in system mode (highest priority). ;$include xa-g3.equ acc reg R4L dpl reg R6L dph reg R6H s0con sfr 420h ri_0 bit s0con.0 ti_0 bit s0con.1 pswl sfr 400h psw51 sfr 402h tcon sfr 410h tr1 bit tcon.6 s0buf sfr 460h wdcon sfr 41fh wfeed1 sfr 45dh wfeed2 sfr 45eh tl1 sfr 452h tmod sfr 45ch rtl1 sfr 456h ssel sfr 403h cs sfr 443h ; PAULMON2, a user-friendly 8051 monitor, by Paul Stoffregen ; Please email comments, suggestions, bugs to paul@ece.orst.edu ; It's free. You may copy sections of code from PAULMON2 ; into your own programs, even for commercial purposes. ; PAULMON2 should only be distributed free of charge, but may ; be bundled as 'value-added' with other products, such as ; development boards, CDROMs, etc. Please distribute the ; PAULMON2.DOC file and other files, not just the object code! ; The PAULMON2.EQU and PAULMON2.HDR files contain valuable ; information that could help you to write programs for use ; with PAULMON2. ; PAULMON2 is in the public domain. PAULMON2 is distributed in ; the hope that it will be useful, but without any warranty; ; without even the implied warranty of merchantability or fitness ; for a particular purpose. carry bit pswl.7 flag0 bit psw51.5 flag1 bit psw51.1 ;---------------------------------------------------------; ; ; ; PAULMON2's default configuration ; ; ; ;---------------------------------------------------------; ; PAULMON2 should be assembled using the modified AS31 assembler, ; originally written by Ken Stauffer, many small changes by Paul ; Stoffregen. This free assembler is available on the web at ; http://www.ece.orst.edu/~paul/8051-goodies/goodies-index.html ; As well, these web pages have a fill-out form which makes it ; very easy to custom configure PAULMON2. Using this form will ; edit the code for you, run the AS31 assmebler, and send you the ; object code to program into your chip. vector equ $8000 ; These three parameters tell PAULMON2 where the user's memory is ; installed. "bmem" and "emem" define the space that will be searched ; for program headers, user installed commands, start-up programs, etc. ; "bmem" and "emem" should be use so they exclude memory areas where ; perphreal devices may be mapped, as reading memory from an io chip ; may reconfigure it unexpectedly. If flash rom is used, "bmem" and "emem" ; should also include the space where the flash rom is mapped. pgm EQU $F000 ;default location for the user program bmem EQU $0000 ;where is the beginning of memory emem EQU $FFFF ;end of the memory ; Please note... much of the memory management code only looks at the ; upper 8 bits of an address, so it's not a good idea to somehow map ; your memory chips (with complex address decoding logic) into chunks ; less than 256 bytes. In other words, only using a piece of a flash ; rom chip and mapping it between C43A to F91B would confuse PAULMON2 ; (as well as require quit a bit of address decoding logic circuitry) ; To set the baud rate, use this formula or set to 0 for auto detection ; baud_const = 256 - (crystal / (4 * 16 * baud)) <-- for XA chip ;baud_const EQU 247 ;19200 baud w/ 11.0592 MHz (XA) ;baud_const EQU 253 ;57600 baud w/ 11.0592 MHz (XA) baud_const EQU 251 ;57600 baud w/ 18.432 MHz (XA) ;baud_const EQU 241 ;19200 baud w/ 18.432 MHz (XA) ;baud_const EQU 236 ;19531 baud w/ 25 MHz (XA) ; About download speed: when writing to ram, PAULMON2 can accept data ; at the maximum baud rate (baud_const=255 or 57600 baud w/ 11.0592 MHz). ; Most terminal emulation programs introduce intentional delays when ; sending ascii data, which you would want to turn off for downloading ; larger programs into ram. For Flash ROM, the maximum speed is set by ; the time it takes to program each location... 9600 baud seems to work ; nicely for the AMD 28F256 chip. The "character pacing" delay in a ; terminal emulation program should be sufficient to download to flash ; rom and any baud rate. ; Several people didn't like the key definations in PAULMON1. ; Actually, I didn't like 'em either, but I never took the time ; to change it. Eventually I got used to them, but now it's ; really easy to change which keys do what in PAULMON2. You ; can guess what to do below, but don't use lowercase. help_key EQU '?' ;help screen dir_key EQU 'M' ;directory run_key EQU 'R' ;run program dnld_key EQU 'D' ;download upld_key EQU 'U' ;upload nloc_key EQU 'N' ;new memory location jump_key EQU 'J' ;jump to memory location dump_key EQU 'H' ;hex dump memory intm_key EQU 'I' ;hex dump internal memory edit_key EQU 'E' ;edit memory clrm_key EQU 'C' ;clear memory erfr_key EQU 'Z' ;erase flash rom xdump_key EQU 'X' ;hex dump ext data memory ;location of parameter table used by download command ;sixteen bytes of internal memory are required beginning at this ;location dnld_parm EQU $01F0 stack EQU $01EE ;---------------------------------------------------------; ; ; ; Interrupt Vectors ; ; (and little bits of code crammed in the empty spaces) ; ; ; ;---------------------------------------------------------; ORG 0 dw $8f00, poweron breakvec: dw $8f00, vector + breakvec tracevec: dw $8f00, vector + tracevec stackovvec: dw $8f00, vector + stackovvec div0vec: dw $8f00, vector + div0vec uretivec: dw $8f00, vector + uretivec org $40 trap0vec: dw $8800, vector + trap0vec trap1vec: dw $8800, vector + trap1vec trap2vec: dw $8800, vector + trap2vec trap3vec: dw $8800, vector + trap3vec trap4vec: dw $8800, vector + trap4vec trap5vec: dw $8800, vector + trap5vec trap6vec: dw $8800, vector + trap6vec trap7vec: dw $8800, vector + trap7vec trap8vec: dw $8800, vector + trap8vec trap9vec: dw $8800, vector + trap9vec trap10vec: dw $8800, vector + trap10vec trap11vec: dw $8800, vector + trap11vec trap12vec: dw $8800, vector + trap12vec trap13vec: dw $8800, vector + trap13vec trap14vec: dw $8800, vector + trap14vec trap15vec: dw $8800, vector + trap15vec org $80 int0vec: dw $8900, vector + int0vec tmr0vec: dw $8900, vector + tmr0vec int1vec: dw $8900, vector + int1vec tmr1vec: dw $8900, vector + tmr1vec tmr2vec: dw $8900, vector + tmr2vec org $A0 rxd0vec: dw $8900, vector + rxd0vec txd0vec: dw $8900, vector + txd0vec rxd1vec: dw $8900, vector + rxd1vec txd1vec: dw $8900, vector + txd1vec org $100 swi1vec: dw $8100, vector + swi1vec swi2vec: dw $8200, vector + swi2vec swi3vec: dw $8300, vector + swi3vec swi4vec: dw $8400, vector + swi4vec swi5vec: dw $8500, vector + swi5vec swi6vec: dw $8600, vector + swi6vec swi7vec: dw $8700, vector + swi7vec org $120 jmp poweron space: MOV.B R4L,#' ' CALL cout RET dash: MOV.B R4L,#'-' CALL cout RET ;---------------------------------------------------------; ; ; ; The jump table for user programs to call ; ; subroutines within PAULMON ; ; ; ;---------------------------------------------------------; ; no jump table anymore... use TRAP or conditional assembly. ;---------------------------------------------------------; ; ; ; Subroutines for serial I/O ; ; ; ;---------------------------------------------------------; ;these are the only three routines which access the serial port directly ;but poweron/autobaud to the initial setup cin: JNB ri_0,cin CLR ri_0 MOV.B R4L,s0buf RET cout: JNB ti_0,cout CLR ti_0 ;clr ti before the mov to sbuf! MOV.B s0buf,R4L RET esc: ;checks to see if is waiting on serial port ;C=clear if no , C=set if pressed ;buffer is flushed PUSH.B acc CLR carry JNB ri_0,esc2 clr ri_0 MOV.B R4L, s0buf CJNE.B R4L,#27,esc2 SETB carry esc2: POP.B acc RET ;everything else from here on should only access the serial ;port using cin/cout/etc newline: PUSH.B acc MOV.B R4L,#13 CALL cout MOV.B R4L,#10 CALL cout POP.B acc RET ;get 2 digit hex number from serial port ; c = set if ESC pressed, clear otherwise ; flag0 = set if return w/ no input, clear otherwise ghex: ghex8: CLR flag0 ghex8c: CALL cin ;get first digit CALL upper CJNE.B R4L,#27,ghex8f ghex8d: SETB carry MOVS R4L,#0 RET ghex8f: CJNE.B R4L,#13,ghex8h SETB flag0 CLR carry MOVS R4L,#0 RET ghex8h: MOV.B R1L,R4L CALL asc2hex BCS ghex8c XCH.B R4L,R1L ;r2 will hold hex value of 1st digit CALL cout ghex8j: CALL cin ;get second digit CALL upper CJNE.B R4L,#27,ghex8k BR ghex8d ghex8k: CJNE.B R4L,#13,ghex8m MOV.B R4L,R1L CLR carry RET ghex8m: CJNE.B R4L,#8,ghex8p ghex8n: CALL cout BR ghex8c ghex8p: CJNE.B R4L,#21,ghex8q BR ghex8n ghex8q: MOV.B R1H,R4L CALL asc2hex BCS ghex8j XCH.B R4L,R1H CALL cout MOV.B R4L,R1L RL.B R4L,#4 OR.B R4L,R1H CLR carry RET ;carry set if esc pressed ;flag0 set if return pressed w/ no input ghex16: MOV.B R1L,#0 ;start out with 0 MOV.B R1H,#0 MOV.B R2L,#4 ;number of digits left CLR flag0 ghex16c: CALL cin CALL upper CJNE.B R4L,#27,ghex16d SETB carry ;handle esc key MOVS R4L,#0 MOV.B dph,R4L MOV.B dpl,R4L RET ghex16d: CJNE.B R4L,#8,ghex16f BR ghex16k ghex16f: CJNE.B R4L,#127,ghex16g ;handle backspace ghex16k: CJNE.B R2L,#4,ghex16e ;have they entered anything yet? BR ghex16c ghex16e: CALL cout CALL ghex16y ADDS.B R2L,#1 BR ghex16c ghex16g: CJNE.B R4L,#13,ghex16i ;return key MOV.B dph,R1H MOV.B dpl,R1L CJNE.B R2L,#4,ghex16h MOVS R4L,#0 MOV.B dph,R4L MOV.B dpl,R4L SETB flag0 ghex16h: CLR carry RET ghex16i: MOV.B R2H,R4L ;keep copy of original keystroke CALL asc2hex BCS ghex16c XCH.B R4L,R2H CALL cout MOV.B R4L,R2H PUSH.B acc CALL ghex16x POP.B acc ADD.B R4L,R1L MOV.B R1L,R4L MOVS R4L,#0 ADDC.B R4L,R1H MOV.B R1H,R4L DJNZ.B R2L,ghex16c CLR carry MOV.B dpl,R1L MOV.B dph,R1H RET ghex16x: ;multiply r3-r2 by 16 (shift left by 4) MOV.B R4L,R1H RL.B R4L,#4 AND.B R4L,#11110000Q MOV.B R1H,R4L MOV.B R4L,R1L RL.B R4L,#4 AND.B R4L,#00001111Q OR.B R4L,R1H MOV.B R1H,R4L MOV.B R4L,R1L RL.B R4L,#4 AND.B R4L,#11110000Q MOV.B R1L,R4L RET ghex16y: ;divide r3-r2 by 16 (shift right by 4) MOV.B R4L,R1L RL.B R4L,#4 AND.B R4L,#00001111Q MOV.B R1L,R4L MOV.B R4L,R1H RL.B R4L,#4 AND.B R4L,#11110000Q OR.B R4L,R1L MOV.B R1L,R4L MOV.B R4L,R1H RL.B R4L,#4 AND.B R4L,#00001111Q MOV.B R1H,R4L RET asc2hex: ;carry set if invalid input CLR carry PUSH.B R4H SUBB.B R4L,#'0' MOV.B R4H,R4L SUBB.B R4L,#10 BCS a2h1 MOV.B R4L,R4H SUBB.B R4L,#7 MOV.B R4H,R4L a2h1: MOV.B R4L,R4H CLR carry AND.B R4L,#11110000Q ;just in case JZ a2h2 SETB carry a2h2: MOV.B R4L,R4H POP.B R4H RET phex: phex8: PUSH.B acc RL.B R4L,#4 AND.B R4L,#15 ADD.B R4L,#246 BCC phex_b ADD.B R4L,#7 phex_b: ADD.B R4L,#58 CALL cout POP.B acc phex1: PUSH.B acc AND.B R4L,#15 ADD.B R4L,#246 BCC phex_c ADD.B R4L,#7 phex_c: ADD.B R4L,#58 CALL cout POP.B acc RET phex16: PUSH.B acc MOV.B R4L,dph CALL phex MOV.B R4L,dpl CALL phex POP.B acc RET ;a not so well documented feature of pstr is that you can print ;multiple consecutive strings without needing to reload dptr ;(which takes 3 bytes of code!)... this is useful for inserting ;numbers or spaces between strings. pstr: PUSH.B acc pstr1: MOVS R4L,#0 MOVC.B A,[A+dptr] ADDS.W R6,#1 JZ pstr2 MOV C,R4L.7 AND.B R4L,#0x7F CALL cout BCS pstr2 BR pstr1 pstr2: POP.B acc RET ;---------------------------------------------------------; ; ; ; The 'high-level' stuff to interact with the user ; ; ; ;---------------------------------------------------------; menu: ;first we print out the prompt MOV.W R6,#prompt1 ;give 'em the first part of prompt CALL pcstr MOV.B R4L,R3H CALL phex MOV.B R4L,R3L CALL phex CALL space MOV.W R6,#prompt2 CALL pstr ;now we're past the prompt, so let's get some input CALL cin ;get the input CALL upper menu1a: CJNE.B R4L,#help_key,menu1b MOV.W R6,#help_cmd2 CALL pcstr call help jmp menu menu1b: CJNE.B R4L,#dir_key,menu1c MOV.W R6,#dir_cmd CALL pcstr call dir jmp menu menu1c: CJNE.B R4L,#run_key,menu1d MOV.W R6,#run_cmd CALL pcstr call run jmp menu menu1d: CJNE.B R4L,#dnld_key,menu1e MOV.W R6,#dnld_cmd CALL pcstr call dnld jmp menu menu1e: CJNE.B R4L,#upld_key,menu1f MOV.W R6,#upld_cmd CALL pcstr call upld jmp menu menu1f: CJNE.B R4L,#nloc_key,menu1g MOV.W R6,#nloc_cmd CALL pcstr call nloc jmp menu menu1g: CJNE.B R4L,#jump_key,menu1h MOV.W R6,#jump_cmd CALL pcstr call jump jmp menu menu1h: CJNE.B R4L,#dump_key,menu1i MOV.W R6,#dump_cmd CALL pcstr call dump jmp menu menu1i: CJNE.B R4L,#edit_key,menu1j MOV.W R6,#edit_cmd CALL pcstr call edit jmp menu menu1j: CJNE.B R4L,#clrm_key,menu1l MOV.W R6,#clrm_cmd CALL pcstr call clrm jmp menu menu1l: CJNE.B R4L,#intm_key,menu1m MOV.W R6,#intm_cmd CALL pcstr call intm jmp menu menu1m: CJNE.B R4L,#xdump_key,menu1n MOV.W R6,#xdump_cmd CALL pcstr call xdump jmp menu menu1n: ;invalid input, no commands to run... menu_end: ;at this point, we have not found CALL newline ;anything to run, so we give up. jmp menu ;.......................................................... ;---------------------------------------------------------; ;dnlds1 = "Begin sending Intel HEX format file to abort" ;dnlds2 = "Download aborted" ;dnlds3 = "Download completed" ;16 byte parameter table: (eight 16 bit values) ; * 0 = lines received ; * 1 = bytes received ; * 2 = bytes written ; * 3 = bytes unable to write ; * 4 = incorrect checksums ; * 5 = unexpected begin of line ; * 6 = unexpected hex digits (while waiting for bol) ; * 7 = unexpected non-hex digits (in middle of a line) dnld: MOV.W R6,#dnlds1 CALL pcstr ;"begin sending file to abort" mov.w r5,#dnld_parm mov.b R1L,#8 dnld0: movs.w [r5+],#0 ;initialize all parameters to 0 DJNZ.B R1L,dnld0 ;look for begining of line marker ':' dnld1: CALL cin CJNE.B R4L,#27,dnld2 ;Test for escape BR dnld_esc dnld2: CJNE.B R4L,#':',dnld2b mov.w r5, #dnld_parm adds.w [r5+0], #1 BR dnld3 dnld2b: ;check to see if it's a hex digit, error if it is CALL asc2hex BCS dnld1 mov.w r5, #dnld_parm adds.w [r5+12], #1 BR dnld1 ;begin taking in the line of data dnld3: MOV.B R4L,#'.' CALL cout MOV.B R2L,#0 ;r4 will count up checksum CALL dnld_ghex MOV.B R0L,R4L ;R0 = # of data bytes MOV.B R2L,R4L CALL dnld_ghex MOV.B dph,R4L ;High byte of load address ADD.B R4L,R2L MOV.B R2L,R4L CALL dnld_ghex MOV.B dpl,R4L ;Low byte of load address ADD.B R4L,R2L MOV.B R2L,R4L CALL dnld_ghex ;Record type MOV.B R1L,R4L ADD.B R4L,R2L MOV.B R2L,R4L MOV.B R4L,R1L CJNE.B R4L,#1,dnld4 ;End record? BR dnld_end dnld4: dnld5: CALL dnld_ghex ;Get data byte MOV.B R1L,R4L mov.w r5, #dnld_parm adds.w [r5+2], #1 MOV.B R4L,R1L ADD.B R4L,R2L MOV.B R2L,R4L MOV.B R4L,R1L CALL smart_wr ;c=1 if an error writing MOVS R4L,#0 ADDC.B R4L,#2 MOV.B R0H,R4L ; 2 = bytes written ; 3 = bytes unable to write rl.b r4l, #1 movs.b r4h, #0 mov.w r5, #dnld_parm add.w r5, r4 adds.w [r5], #1 ADDS.W R6,#1 DJNZ.B R0L,dnld5 CALL dnld_ghex ;get checksum ADD.B R4L,R2L JZ dnld1 ;should always add to zero dnld_sumerr: mov.w r5, #dnld_parm adds.w [r5+8], #1 BR dnld1 dnld_end: ;handles the proper end-of-download marker CALL dnld_ghex ;get the last checksum ;assume no data in this line. ADD.B R4L,R2L JNZ dnld_sumerr CALL dnld_dly MOV.W R6,#dnlds3 CALL pcstr ;"download went ok..." ;consume any cr or lf character that may have been ;on the end of the last line JNB ri_0,dnld_sum CALL cin BR dnld_sum dnld_esc: ;handle esc received in the download stream CALL dnld_dly MOV.W R6,#dnlds2 CALL pcstr ;"download aborted." BR dnld_sum dnld_dly: ;a short delay since most terminal emulation programs ;won't be ready to receive anything immediately after ;they've transmitted a file... even on a fast Pentium(tm) ;machine with 16550 uarts! MOV.B R0L,#0 dnlddly2: MOV.B R0H,#0 dnlddly3: DJNZ.B R0H,dnlddly3 ;roughly 128k cycles, appox 0.1 sec DJNZ.B R0L,dnlddly2 RET ;a special version of ghex just for the download. Does not ;look for carriage return or backspace. Handles ESC key by ;poping the return address (I know, nasty, but it saves many ;bytes of code in this 4k ROM) and then jumps to the esc ;key handling. This ghex doesn't echo characters, and if it ;sees ':', it pops the return and jumps to an error handler ;for ':' in the middle of a line. Non-hex digits also jump ;to error handlers, depending on which digit. ; XA compatibility issue: This code pops the return address ; off the stack and does a jump to an error handler. The ; code should examine the mode bit to see if return addresses ; are 16 or 32 bits on the stack. As it is, it will probably ; work in non 16-bit mode (default), but this code could ; use some attention to this detail nonetheless. dnld_ghex: dnldgh1: CALL cin CALL upper CJNE.B R4L,#27,dnldgh3 dnldgh2: POP.B acc ;<-- compatibility problem!!! Check XA mode POP.B acc ;<-- and pop correct number of words off stack BR dnld_esc dnldgh3: CJNE.B R4L,#':',dnldgh5 dnldgh4: mov.w r5, #dnld_parm adds.w [r5+10], #1 ;handle unexpected beginning of line POP.B acc ;<-- compatibility problem!!! Check XA mode POP.B acc ;<-- and pop correct number of words off stack JMP dnld3 ;and now we're on a new line! dnldgh5: CALL asc2hex BCC dnldgh6 mov.w r5, #dnld_parm adds.w [r5+14], #1 BR dnldgh1 dnldgh6: MOV.B R1L,R4L ;keep first digit in r2 dnldgh7: CALL cin CALL upper CJNE.B R4L,#27,dnldgh8 BR dnldgh2 dnldgh8: CJNE.B R4L,#':',dnldgh9 BR dnldgh4 dnldgh9: CALL asc2hex BCC dnldghA mov.w r5, #dnld_parm adds.w [r5+14], #1 BR dnldgh7 dnldghA: XCH.B R4L,R1L RL.B R4L,#4 OR.B R4L,R1L RET ;dnlds4 = "Summary:" ;dnlds5 = " lines received" ;dnlds6a = " bytes received" ;dnlds6b = " bytes written" dnld_sum: ;print out download summary MOV.W R6,#dnlds4 CALL pcstr MOV.w r5, #dnld_parm mov.w r6, [r5+] CALL space CALL pint16u MOV.W R6,#dnlds5 CALL pcstr mov.w r6, [r5+] CALL space CALL pint16u MOV.W R6,#dnlds6a CALL pcstr mov.w r6, [r5+] CALL space CALL pint16u MOV.W R6,#dnlds6b CALL pcstr dnld_err: ;now print out error summary MOV.w r5, #dnld_parm + 6 mov r1l, #5 dnlder2: mov.w r6, [r5+] bne dnlder3 ;any errors? DJNZ.B R1L,dnlder2 ;no errors, so we print the nice message MOV.W R6,#dnlds13 CALL pcstr RET dnlder3: ;there were errors, so now we print 'em MOV.W R6,#dnlds7 CALL pcstr ;but let's not be nasty... only print if necessary mov r5, #dnld_parm+6 mov r6, [r5+] beq dnlder4 CALL space CALL pint16u MOV.W R6,#dnlds8 CALL pcstr dnlder4: mov r6, [r5+] beq dnlder5 CALL space CALL pint16u MOV.W R6,#dnlds9 CALL pcstr dnlder5: mov r6, [r5+] beq dnlder6 CALL space CALL pint16u MOV.W R6,#dnlds10 CALL pcstr dnlder6: mov r6, [r5+] beq dnlder7 CALL space CALL pint16u MOV.W R6,#dnlds11 CALL pcstr dnlder7: mov r6, [r5+] beq dnlder8 CALL space CALL pint16u MOV.W R6,#dnlds12 CALL pcstr dnlder8: CALL newline RET ;dnlds7: = "Errors:" ;dnlds8: = " bytes unable to write" ;dnlds9: = " incorrect checksums" ;dnlds10: = " unexpected begin of line" ;dnlds11: = " unexpected hex digits" ;dnlds12: = " unexpected non-hex digits" ;dnlds13: = "No errors detected" ;---------------------------------------------------------; jump: MOV.W R6,#prompt8 CALL pcstr mov.w r6, r3 CALL phex16 MOV.W R6,#prompt4 CALL pcstr CALL ghex16 JB flag0,jump3 BCC jump2 MOV.W R6,#abort CALL pcstr CALL newline RET jump2: mov.w r3, r6 jump3: CALL newline MOV.W R6,#runs1 CALL pcstr mov.w r6, r3 call phex16 call newline mov.w r6, r3 jump_doit: ;jump to user code @dptr (this used by run command also) movs.w r0, #0 push.w r0 mov.w r0, #$120 push.w r0 jmp [r6] ;---------------------------------------------------------; dump: MOV.B R1L,#16 ;number of lines to print CALL newline CALL newline dump1: push r6 mov r6, #msg_code call pstr pop r6 MOV.B dpl,R3L MOV.B dph,R3H CALL phex16 ;tell 'em the memory location MOV.B R4L,#':' CALL cout CALL space MOV.B R1H,#16 ;r3 counts # of bytes to print MOV.B dpl,R3L MOV.B dph,R3H dump2: MOVS R4L,#0 MOVC.B A,[A+dptr] ADDS.W R6,#1 CALL phex ;print each byte in hex CALL space DJNZ.B R1H,dump2 CALL space ;print a couple extra space CALL space MOV.B R1H,#16 MOV.B dpl,R3L MOV.B dph,R3H dump3: MOVS R4L,#0 MOVC.B A,[A+dptr] ADDS.W R6,#1 AND.B R4L,#01111111Q ;avoid unprintable characters CLR carry SUBB.B R4L,#20h BCC dump4 ;avoid control characters MOV.B R4L,#(' ' - 20h) dump4: ADD.B R4L,#20h CALL cout DJNZ.B R1H,dump3 CALL newline MOV.B R3L,dpl MOV.B R3H,dph CALL esc BCS dump5 DJNZ.B R1L,dump1 ;loop back up to print next line dump5: CALL newline RET msg_code: db "Code:",0 msg_xram: db "Xram:",0 ;---------------------------------------------------------; xdump: MOV.B R1L,#16 ;number of lines to print CALL newline CALL newline xdump1: push r6 mov r6, #msg_xram call pstr pop r6 MOV.B dpl,R3L MOV.B dph,R3H CALL phex16 ;tell 'em the memory location MOV.B R4L,#':' CALL cout CALL space MOV.B R1H,#16 ;r3 counts # of bytes to print MOV.B dpl,R3L MOV.B dph,R3H xdump2: MOVS R4L,#0 MOVX r4l,[r6] ADDS.W R6,#1 CALL phex ;print each byte in hex CALL space DJNZ.B R1H,xdump2 CALL space ;print a couple extra space CALL space MOV.B R1H,#16 MOV.B dpl,R3L MOV.B dph,R3H xdump3: MOVS R4L,#0 MOVX r4l,[r6] ADDS.W R6,#1 AND.B R4L,#01111111Q ;avoid unprintable characters CLR carry SUBB.B R4L,#20h BCC xdump4 ;avoid control characters MOV.B R4L,#(' ' - 20h) xdump4: ADD.B R4L,#20h CALL cout DJNZ.B R1H,xdump3 CALL newline MOV.B R3L,dpl MOV.B R3H,dph CALL esc BCS xdump5 DJNZ.B R1L,xdump1 ;loop back up to print next line xdump5: CALL newline RET ;---------------------------------------------------------; nloc: MOV.W R6,#prompt6 CALL pcstr CALL ghex16 BCS nloc2 JB flag0,nloc2 MOV.B R3L,dpl MOV.B R3H,dph CALL newline CALL newline RET nloc2: MOV.W R6,#abort CALL pcstr CALL newline RET ;---------------------------------------------------------; edit: ;edit external ram... MOV.W R6,#edits1 CALL pcstr MOV.B dpl,R3L MOV.B dph,R3H edit1: CALL phex16 MOV.B R4L,#':' CALL cout CALL space MOV.B R4L,#'(' CALL cout MOV.B R3L,dpl MOV.B R3H,dph MOVS R4L,#0 MOVC.B A,[A+dptr] CALL phex MOV.W R6,#prompt10 CALL pcstr CALL ghex JB flag0,edit2 BCS edit2 MOV.B dpl,R3L MOV.B dph,R3H MOVX.B [R6],R4L CALL newline ADDS.W R6,#1 MOV.B R3L,dpl MOV.B R3H,dph JMP edit1 edit2: MOV.W R6,#edits2 CALL pcstr RET ;---------------------------------------------------------; dir: MOV.W R6,#prompt9 CALL pcstr MOV.B R0L,#21 dir0a: CALL space DJNZ.B R0L,dir0a MOV.W R6,#prompt9b CALL pcstr MOV.B dph,#high bmem dir1: CALL find ;find the next program in memory BCS dir2 dir_end: CALL newline ;we're done if no more found RET dir2: CALL space CALL space MOV.B dpl,#32 ;print its name CALL pstr MOV.B dpl,#32 ;how long is the name CALL lenstr MOV.B R4L,#33 CLR carry SUBB.B R4L,R0L MOV.B R0L,R4L MOV.B R4L,#' ' ;print the right # of spaces dir3: CALL cout DJNZ.B R0L,dir3 MOV.B dpl,#0 CALL phex16 ;print the memory location MOV.B R0L,#6 MOV.B R4L,#' ' dir4: CALL cout DJNZ.B R0L,dir4 MOV.B dpl,#4 ;now figure out what type it is MOVS R4L,#0 MOVC.B A,[A+dptr] MOV.B R1L,dph ;save this, we're inside a search dir5: CJNE.B R4L,#254,dir5b MOV.W R6,#type1 ;it's an external command BR dir7 dir5b: CJNE.B R4L,#255,dir5c MOV.W R6,#type1a ;it's some system thing BR dir7 dir5c: CJNE.B R4L,#253,dir5d MOV.W R6,#type1b ;it's a startup routine BR dir7 dir5d: CJNE.B R4L,#35,dir5e MOV.W R6,#type2 ;it's an ordinary program BR dir7 dir5e: CJNE.B R4L,#143,dir5f MOV.W R6,#type3 ;it's a background task BR dir7 dir5f: CJNE.B R4L,#69,dir5g MOV.W R6,#type4 ;it's a data file BR dir7 dir5g: dir6: MOV.W R6,#type5 ;who knows what the hell it is dir7: CALL pcstr ;print out the type MOV.B dph,R1L ;go back and find the next one CALL newline CJNE.B dph,#high emem, dir8 ;did we just print the last one? JMP dir_end dir8: ADDS.B dph,#1 JMP dir1 ; type1=Ext Command ; type1a=Misc System Thing ; type1b=Power-Up Code ; type2=Program ; type3=Background Task ; type4=Data File ; type5=??????? ;---------------------------------------------------------; run: CALL newline CALL newline jmp 0xF000 ;---------------------------------------------------------; help: MOV.W R6,#help1txt CALL pcstr MOV.B R2L,#help_key MOV.W R6,#help_cmd CALL help2 MOV.B R2L,#dir_key MOV.W R6,#dir_cmd CALL help2 MOV.B R2L,#run_key MOV.W R6,#run_cmd CALL help2 MOV.B R2L,#dnld_key MOV.W R6,#dnld_cmd CALL help2 MOV.B R2L,#upld_key MOV.W R6,#upld_cmd CALL help2 MOV.B R2L,#nloc_key MOV.W R6,#nloc_cmd CALL help2 MOV.B R2L,#jump_key MOV.W R6,#jump_cmd CALL help2 MOV.B R2L,#dump_key MOV.W R6,#dump_cmd CALL help2 MOV.B R2L,#xdump_key MOV.W R6,#xdump_cmd CALL help2 MOV.B R2L,#intm_key MOV.W R6,#intm_cmd CALL help2 MOV.B R2L,#edit_key MOV.W R6,#edit_cmd CALL help2 MOV.B R2L,#clrm_key MOV.W R6,#clrm_cmd CALL help2 MOV.W R6,#help2txt CALL pcstr MOV.W R6,#bmem help3: CALL find BCC help4 MOV.B dpl,#4 MOVS R4L,#0 MOVC.B A,[A+dptr] CJNE.B R4L,#254,help3a ;only FE is an ext command CALL space CALL space ADDS.B dpl,#1 MOVS R4L,#0 MOVC.B A,[A+dptr] CALL cout CALL dash CALL space MOV.B dpl,#32 CALL pstr CALL newline help3a: ADDS.B dph,#1 BR help3 help4: CALL newline RET help2: ;print 11 standard lines CALL space ;given key in R4 and name in dptr CALL space MOV.B R4L,R2L CALL cout CALL dash CALL space CALL pcstr CALL newline RET ;---------------------------------------------------------; upld: CALL get_mem ;assume we've got the beginning address in r3/r2 ;and the final address in r5/r4 (r4=lsb)... ;print out what we'll be doing MOV.W R6,#uplds3 CALL pcstr MOV.B R4L,R1H CALL phex MOV.B R4L,R1L CALL phex MOV.W R6,#uplds4 CALL pcstr MOV.B R4L,R2H CALL phex MOV.B R4L,R2L CALL phex CALL newline ;need to adjust end location by 1... MOV.B dph,R2H MOV.B dpl,R2L ADDS.W R6,#1 MOV.B R2L,dpl MOV.B R2H,dph MOV.W R6,#prompt7 CALL pcstr CALL cin CJNE.B R4L,#27,upld2e JMP abort_it upld2e: CALL newline MOV.B dpl,R1L MOV.B dph,R1H upld3: MOV.B R4L,R2L ;how many more bytes to output?? CLR carry SUBB.B R4L,dpl MOV.B R1L,R4L MOV.B R4L,R2H SUBB.B R4L,dph JNZ upld4 ;if >256 left, then do next 16 MOV.B R4L,R1L JZ upld7 ;if we're all done AND.B R4L,#11110000Q JNZ upld4 ;if >= 16 left, then do next 16 BR upld5 ;otherwise just finish it off upld4: MOV.B R1L,#16 upld5: MOV.B R4L,#':' ;begin the line CALL cout MOV.B R4L,R1L CALL phex ;output # of data bytes CALL phex16 ;output memory location MOV.B R4L,dph ADD.B R4L,dpl ADD.B R4L,R1L MOV.B R1H,R4L ;r3 will become checksum MOVS R4L,#0 CALL phex ;output 00 code for data upld6: MOVS R4L,#0 MOVC.B A,[A+dptr] CALL phex ;output each byte ADD.B R4L,R1H MOV.B R1H,R4L ADDS.W R6,#1 DJNZ.B R1L,upld6 ;do however many bytes we need MOV.B R4L,R1H CPL.B R4L ADDS.B R4L,#1 CALL phex ;and finally the checksum CALL newline CALL esc BCC upld3 ;keep working if no esc pressed BR abort_it upld7: MOV.B R4L,#':' CALL cout MOVS R4L,#0 CALL phex CALL phex CALL phex ADDS.B R4L,#1 CALL phex MOV.B R4L,#255 CALL phex upld8: CALL newline CALL newline RET ;---------------------------------------------------------; get_mem: ;this thing gets the begin and end locations for ;a few commands. If an esc or enter w/ no input, ;it pops it's own return and returns to the menu ;(nasty programming, but we need tight code for 4k rom) CALL newline CALL newline MOV.W R6,#beg_str CALL pcstr CALL ghex16 BCS pop_it JB flag0,pop_it PUSH.B dph PUSH.B dpl CALL newline MOV.W R6,#end_str CALL pcstr CALL ghex16 MOV.B R2H,dph MOV.B R2L,dpl POP.B acc MOV.B R1L,R4L POP.B acc MOV.B R1H,R4L BCS pop_it JB flag0,pop_it CALL newline RET pop_it: POP.B acc POP.B acc abort_it: CALL newline MOV.W R6,#abort CALL pcstr CALL newline RET clrm: CALL get_mem MOV.W R6,#sure CALL pcstr CALL cin CALL upper CJNE.B R4L,#'Y',abort_it CALL newline CALL newline ;now we actually do it clrm2: MOV.B dph,R1H MOV.B dpl,R1L clrm3: MOVS R4L,#0 CALL smart_wr cmp.w r6, r2 bne clrm4 RET clrm4: ADDS.W R6,#1 BR clrm3 ;---------------------------------------------------------; intm: CALL newline MOVs.w r5,#0 intm2: CALL newline CJNE.w r5, #512, intm3 CALL newline RET intm3: mov.b r4l,r5h call phex MOV.B R4L,R5L CALL phex MOV.B R4L,#':' CALL cout intm4: CALL space MOV.B R4L,[r5+] CALL phex MOV.B R4L,R5L AND.B R4L,#00001111Q JNZ intm4 BR intm2 ;---------------------------------------------------------; ; ; ; Subroutines for memory managment and non-serial I/O ; ; ; ;---------------------------------------------------------; ;finds the next header in the external memory. ; Input DPTR=point to start search (only MSB used) ; Output DPTR=location of next module ; C=set if a header found, C=clear if no more headers find: MOV.B dpl,#0 MOVS R4L,#0 MOVC.B A,[A+dptr] CJNE.B R4L,#0xA5,find3 ADDS.W R6,#1 MOVS R4L,#0 MOVC.B A,[A+dptr] CJNE.B R4L,#0xE5,find3 ADDS.W R6,#1 MOVS R4L,#0 MOVC.B A,[A+dptr] CJNE.B R4L,#0xE0,find3 ADDS.W R6,#1 MOVS R4L,#0 MOVC.B A,[A+dptr] CJNE.B R4L,#0xA5,find3 MOV.B dpl,#0 ;found one here! SETB carry RET find3: CJNE.B dph, #high emem, find4 ;did we just check the end CLR carry RET find4: ADDS.B dph,#1 ;keep on searching BR find ;Write to ordinary RAM. Carry bit will indicate ;if the value was successfully written, C=1 if not written. smart_wr: PUSH.B acc PUSH.B R4H MOV.B R4H,R4L wr_ram: MOV.B R4L,R4H MOVX.B [R6],R4L ;write the value to memory MOVS R4L,#0 MOVC.B A,[A+dptr] ;read it back from code memory CLR carry SUBB.B R4L,R4H JZ smwrok MOVX.B R4L,[R6] ;read it back from data memory CLR carry SUBB.B R4L,R4H JZ smwrok smwrbad: SETB carry BR smwrxit smwrok: CLR carry smwrxit: POP.B R4H POP.B acc RET ;---------------------------------------------------------; ; ; ; Power-On initialization code and such... ; ; ; ;---------------------------------------------------------; ;first the hardware has to get initialized. poweron: mov.w r7, #stack mov.b wdcon, #0 ;shut off watchdog mov.b wfeed1, #$a5 mov.b wfeed2, #$5a ;or.b p1cfga, #$C0 ;for testing ;or.b p1cfgb, #$C0 ;for testing ;clr p1.7 ;for testing ;no automatic baud rate detection anymore autobaud: MOV.B tcon,#0 MOV.B R4L,#baud_const MOV.B tl1,R4L MOV.B rtl1,R4L MOV.B tmod,#$22 ;set timer #1 for 8 bit auto-reload MOV.B s0con,#$52 SETB tr1 ;start the baud rate timer MOV.w r5, #2000 ab_loop1: DJNZ.w r5, ab_loop1 ;clr p1.6 ;for testing welcome: MOV.B R0L,#24 welcm2: CALL newline DJNZ.B R0L,welcm2 ;setb p1.7 ;for testing MOV.B R0L,#15 MOV.B R4L,#' ' welcm4: CALL cout DJNZ.B R0L,welcm4 MOV.W R6,#logon1 CALL pcstr MOV.W R6,#logon2 CALL pcstr ;CALL dir ;skip dir for now mov.w r3, #pgm JMP menu ;---------------------------------------------------------; ; ; ; More subroutines, but less frequent used ; ; ; ;---------------------------------------------------------; pint8u: ;prints the unsigned 8 bit value in Acc in base 10 PUSH.B R4H PUSH.B acc BR pint8b pint8: ;prints the signed 8 bit value in Acc in base 10 PUSH.B R4H PUSH.B acc JNB R4L.7,pint8b MOV.B R4L,#'-' CALL cout POP.B acc PUSH.B acc CPL.B R4L ADD.B R4L,#1 pint8b: MOV.B R4H,#100 DIVU.B R4L,R4H SETB flag0 JZ pint8c CLR flag0 ADD.B R4L,#'0' CALL cout pint8c: MOV.B R4L,R4H MOV.B R4H,#10 DIVU.B R4L,R4H JNB flag0,pint8d JZ pint8e pint8d: ADD.B R4L,#'0' CALL cout pint8e: MOV.B R4L,R4H ADD.B R4L,#'0' CALL cout POP.B acc POP.B R4H RET ;print 16 bit unsigned integer in DPTR (r6), using base 10. pint16u: push.w r2, r3, r4 CLR flag0 pint16a: ;ten-thousands digit mov.w r2, r6 movs.w r3, #0 div.d r2, #10000 xch r2, r3 mov.b r4l, r3l JZ pint16b ADD.B R4L,#'0' CALL cout SETB flag0 pint16b: ;thousands digit movs.w r3, #0 div.d r2, #1000 xch r2, r3 mov.b r4l, r3l JNZ pint16c JNB flag0,pint16d pint16c: ADD.B R4L,#'0' CALL cout SETB flag0 pint16d: ;hundreds digit div.w r2, #100 xch r2h, r2l mov.b r4l, r2h JNZ pint16e JNB flag0,pint16f pint16e: ADD.B R4L,#'0' CALL cout SETB flag0 pint16f: ;tens digit DIVU.B R2L, #10 mov.b r4l, r2l JNZ pint16g JNB flag0,pint16h pint16g: ADD.B R4L,#'0' CALL cout pint16h: ;ones digit MOV.B R4L,R2h ;and finally the ones digit ADD.B R4L,#'0' CALL cout pop.w r2, r3, r4 RET upper: ;converts the ascii code in Acc to uppercase, if it is lowercase PUSH.B acc CLR carry SUBB.B R4L,#97 BCS upper2 ;is it a lowercase character SUBB.B R4L,#26 BCC upper2 POP.B acc ADD.B R4L,#224 ;convert to uppercase RET upper2: POP.B acc ;don't change anything RET lenstr: MOV.B R0L,#0 ;returns length of a string in r0 PUSH.B acc lenstr1: MOVS R4L,#0 MOVC.B A,[A+dptr] JZ lenstr2 MOV C,R4L.7 ADDS.B R0L,#1 BCS lenstr2 ADDS.W R6,#1 BR lenstr1 lenstr2: POP.B acc RET ;pcstr prints the compressed strings. A dictionary of 128 words is ;stored in 4 bit packed binary format. When pcstr finds a byte in ;a string with the high bit set, it prints the word from the dictionary. ;A few bytes have special functions and everything else prints as if ;it were an ordinary string. ; special codes for pcstr: ; 0 = end of string ; 13 = CR/LF ; 14 = CR/LF and end of string ; 31 = next word code should be capitalized pcstr: push r0, r2, r4 SETB flag1 SETB flag0 pcstr1: MOVS R4L,#0 MOVC.B A,[A+dptr] ADDS.W R6,#1 JZ pcstr2 JB R4L.7,decomp AND.B R4L,#0x7F pcstrs1: CJNE.B R4L,#13,pcstrs2 CALL newline SETB flag1 BR pcstr1 pcstrs2: CJNE.B R4L,#31,pcstrs3 CLR flag0 BR pcstr1 pcstrs3: CJNE.B R4L,#14,pcstrs4 CALL newline BR pcstr2 pcstrs4: CLR flag1 CALL cout BR pcstr1 pcstr2: pop r0, r2, r4 RET ;dcomp actually takes care of printing a word from the dictionary ; dptr = position in packed words table ; r4=0 if next nibble is low, r4=255 if next nibble is high decomp: AND.B R4L,#0x7F MOV.B R0L,R4L ;r0 counts which word JB flag1,decomp1 ;avoid leading space if first word CALL space decomp1: CLR flag1 push r6 MOV.W R6,#words MOV.B R2L,#0 MOV.B R4L,R0L JZ dcomp3 ;here we must seek past all the words in the table ;that come before the one we're supposed to print MOV.B R0H,R4L dcomp2: CALL get_next_nibble JNZ dcomp2 ;when we get here, a word has been skipped... keep doing ;this until we're pointing to the correct one DJNZ.B R0H,dcomp2 dcomp3: ;now we're pointing to the correct word, so all we have ;to do is print it out CALL get_next_nibble JZ dcomp_end CJNE.B R4L,#15,dcomp4 ;the character is one of the 12 least commonly used CALL get_next_nibble ADDS.B R4L,#1 MOVC.B A,[A+pc] BR dcomp5 DB "hfwgybxvkqjz" dcomp4: ;the character is one of the 14 most commonly used ADDS.B R4L,#1 MOVC.B A,[A+pc] BR dcomp5 DB "etarnisolumpdc" dcomp5: ;decide if it should be uppercase or lowercase MOV C,flag0 MOV R4L.5,C SETB flag0 CJNE.B R0L,#20,dcomp6 CLR R4L.5 dcomp6: CJNE.B R0L,#12,dcomp7 CLR R4L.5 dcomp7: CALL cout BR dcomp3 dcomp_end: pop r6 JMP pcstr1 get_next_nibble: ;...and update dptr and r4, of course MOVS R4L,#0 MOVC.B A,[A+dptr] CJNE.B R2L,#0,gnn2 MOV.B R2L,#255 AND.B R4L,#00001111Q RET gnn2: MOV.B R2L,#0 ADDS.W R6,#1 RL.B R4L,#4 AND.B R4L,#00001111Q RET ;---------------------------------------------------------; ; ; ; Here begins the data tables and strings ; ; ; ;---------------------------------------------------------; ;this is the dictionary of 128 words used by pcstr. words: DB 0x82,0x90,0xE8,0x23,0x86,0x05,0x4C,0xF8 DB 0x44,0xB3,0xB0,0xB1,0x48,0x5F,0xF0,0x11 DB 0x7F,0xA0,0x15,0x7F,0x1C,0x2E,0xD1,0x40 DB 0x5A,0x50,0xF1,0x03,0xBF,0xBA,0x0C,0x2F DB 0x96,0x01,0x8D,0x3F,0x95,0x38,0x0D,0x6F DB 0x5F,0x12,0x07,0x71,0x0E,0x56,0x2F,0x48 DB 0x3B,0x62,0x58,0x20,0x1F,0x76,0x70,0x32 DB 0x24,0x40,0xB8,0x40,0xE1,0x61,0x8F,0x01 DB 0x34,0x0B,0xCA,0x89,0xD3,0xC0,0xA3,0xB9 DB 0x58,0x80,0x04,0xF8,0x02,0x85,0x60,0x25 DB 0x91,0xF0,0x92,0x73,0x1F,0x10,0x7F,0x12 DB 0x54,0x93,0x10,0x44,0x48,0x07,0xD1,0x26 DB 0x56,0x4F,0xD0,0xF6,0x64,0x72,0xE0,0xB8 DB 0x3B,0xD5,0xF0,0x16,0x4F,0x56,0x30,0x6F DB 0x48,0x02,0x5F,0xA8,0x20,0x1F,0x01,0x76 DB 0x30,0xD5,0x60,0x25,0x41,0xA4,0x2C,0x60 DB 0x05,0x6F,0x01,0x3F,0x26,0x1F,0x30,0x07 DB 0x8E,0x1D,0xF0,0x63,0x99,0xF0,0x42,0xB8 DB 0x20,0x1F,0x23,0x30,0x02,0x7A,0xD1,0x60 DB 0x2F,0xF0,0xF6,0x05,0x8F,0x93,0x1A,0x50 DB 0x28,0xF0,0x82,0x04,0x6F,0xA3,0x0D,0x3F DB 0x1F,0x51,0x40,0x23,0x01,0x3E,0x05,0x43 DB 0x01,0x7A,0x01,0x17,0x64,0x93,0x30,0x2A DB 0x08,0x8C,0x24,0x30,0x99,0xB0,0xF3,0x19 DB 0x60,0x25,0x41,0x35,0x09,0x8E,0xCB,0x19 DB 0x12,0x30,0x05,0x1F,0x31,0x1D,0x04,0x14 DB 0x4F,0x76,0x12,0x04,0xAB,0x27,0x90,0x56 DB 0x01,0x2F,0xA8,0xD5,0xF0,0xAA,0x26,0x20 DB 0x5F,0x1C,0xF0,0xF3,0x61,0xFE,0x01,0x41 DB 0x73,0x01,0x27,0xC1,0xC0,0x84,0x8F,0xD6 DB 0x01,0x87,0x70,0x56,0x4F,0x19,0x70,0x1F DB 0xA8,0xD9,0x90,0x76,0x02,0x17,0x43,0xFE DB 0x01,0xC1,0x84,0x0B,0x15,0x7F,0x02,0x8B DB 0x14,0x30,0x8F,0x63,0x39,0x6F,0x19,0xF0 DB 0x11,0xC9,0x10,0x6D,0x02,0x3F,0x91,0x09 DB 0x7A,0x41,0xD0,0xBA,0x0C,0x1D,0x39,0x5F DB 0x07,0xF2,0x11,0x17,0x20,0x41,0x6B,0x35 DB 0x09,0xF7,0x75,0x12,0x0B,0xA7,0xCC,0x48 DB 0x02,0x3F,0x64,0x12,0xA0,0x0C,0x27,0xE3 DB 0x9F,0xC0,0x14,0x77,0x70,0x11,0x40,0x71 DB 0x21,0xC0,0x68,0x25,0x41,0xF0,0x62,0x7F DB 0xD1,0xD0,0x21,0xE1,0x62,0x58,0xB0,0xF3 DB 0x05,0x1F,0x73,0x30,0x77,0xB1,0x6F,0x19 DB 0xE0,0x19,0x43,0xE0,0x58,0x2F,0xF6,0xA4 DB 0x14,0xD0,0x23,0x03,0xFE,0x31,0xF5,0x14 DB 0x30,0x99,0xF8,0x03,0x3F,0x64,0x22,0x51 DB 0x60,0x25,0x41,0x2F,0xE3,0x01,0x56,0x27 DB 0x93,0x09,0xFE,0x11,0xFE,0x79,0xBA,0x60 DB 0x75,0x42,0xEA,0x62,0x58,0xA0,0xE5,0x1F DB 0x53,0x4F,0xD1,0xC0,0xA3,0x09,0x42,0x53 DB 0xF7,0x12,0x04,0x62,0x1B,0x30,0xF5,0x05 DB 0xF7,0x69,0x0C,0x35,0x1B,0x70,0x82,0x2F DB 0x2F,0x14,0x4F,0x51,0xC0,0x64,0x25,0x00 ;STR logon1: DB "Welcome",128,148,"2 (beta7,XA) by",31,248,31,254,13,14 logon2: DB 32,32,"See",148,"2.DOC,",148,"2.EQU",164 DB 148,"2.HDR",180,213,141,".",14 abort: DB " ",31,158,31,160,"!",14 prompt1: DB 148,"2 (beta7,XA) Loc:",0 prompt2: DB ">",160 prompt3: DB 134,202,130,'(',0 prompt4: DB "),",149,140,128,200,": ",0 prompt5: DB 31,151,130,195,"s",199,166,131,"," DB 186," JUMP",128,134,161,"r",130,13,14 prompt6: DB 13,13,31,135,131,129,": ",0 prompt7: DB 31,228,251," key: ",0 prompt8: DB 13,13,31,136,128,131,129," (",0 prompt9: DB 13,13,31,130,31,253,0 prompt9b: DB 31,129,32,32,32,32,32,31,201,14 prompt10: DB ") ",31,135,31,178,": ",0 beg_str: DB "First",31,129,": ",0 end_str: DB "Last",31,129,":",32,32,0 sure: DB 31,185,161," sure?",0 edits1: DB 13,13,31,156,154,146,",",140,128,200,14 edits2: DB " ",31,156,193,",",142,129,247,13,14 dnlds1: DB 13,13,31,159," ascii",249,150,31,152,132,137 DB ",",149,140,128,160,13,14 dnlds2: DB 13,31,138,160,"ed",13,14 dnlds3: DB 13,31,138,193,"d",13,14 dnlds4: DB "Summary:",14 dnlds5: DB " ",198,"s",145,"d",14 dnlds6a: DB " ",139,145,"d",14 dnlds6b: DB " ",139," written",14 dnlds7: DB 31,155,":",14 dnlds8: DB " ",139," unable",128," write",14 dnlds9: DB 32,32,"bad",245,"s",14 dnlds10: DB " ",133,159,150,198,14 dnlds11: DB " ",133,132,157,14 dnlds12: DB " ",133," non",132,157,14 dnlds13: DB 31,151,155," detected",13,14 runs1: DB 13,134,"ning",130,":",13,14 uplds3: DB 13,13,"Sending",31,152,132,137,172,32,32,0 uplds4: DB " ",128,32,32,0 help1txt: DB 13,13,"Standard",31,158,"s",14 help2txt: DB 31,218,31,244,"ed",31,158,"s",14 type1: DB 31,154,158,0 type1a: DB 31,223,0 type1b: DB 31,143,31,226,31,170,0 type2: DB 31,130,0 type3: DB "Reserved",0 type4: DB 31,239,137,0 type5: DB "???",0 help_cmd: DB 31,142,215,209,0 help_cmd2: DB 31,215,0 dir_cmd: DB 31,209,130,"s",0 run_cmd: DB 31,134,130,0 dnld_cmd: DB 31,138,0 upld_cmd: DB 31,147,0 nloc_cmd: DB 31,135,129,0 jump_cmd: DB 31,136,128,131,129,0 dump_cmd: DB 31,132,219,154," code",131,0 xdump_cmd: db 31,132,219,154," data",131,0 intm_cmd: DB 31,132,219,192,131,0 edit_cmd: DB 31,156,154,146,0 clrm_cmd: DB 31,237,131,0 erfr_cmd: DB 31,203,153,144,0 ;this code attempts to switch from development mode to run mode ;on the xa_tiny (8-bit data bus) development board. org 0x7000 es sfr 442h pswh sfr 401h ; a bunch of nops, to hopefully flush the xa prefetch buffer nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop ;make a read from location 0x0EF000 to switch modes mov.b es, #0x0E mov r0, #0xF000 setb ssel.0 mov.b r4l, [r0] ;make the mode switch mov.b r4l, [r0] ;make the mode switch mov.b r4l, [r0] ;make the mode switch mov.b r4l, [r0] ;make the mode switch ;now read the start vector from location zero movs.b es, #0 movs r0, #0 movc r1l, [r0+] ;read psw value into r1 movc r1h, [r0+] movc r2l, [r0+] ;read start address into r2 movc r2h, [r0+] movs.b ssel, #0 mov.b pswl, r1l mov.b pswh, r1h jmp [r2]