📄 paulmon.txt
字号:
; anl a, #15
; add a, #246
; jnc phex_b
; add a, #7
;phex_b:add a, #58
; acall cout
; pop acc
;phex1: push acc
; anl a, #15
; add a, #246
; jnc phex_c
; add a, #7
;phex_c:add a, #58
; acall cout
; pop acc
; ret
phex16:
push acc
mov a, dph
acall phex
mov a, dpl
acall phex
pop 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 acc
pstr1: clr a
movc a, @a+dptr
inc dptr
jz pstr2
mov c, acc.7
anl a, #0x7F
acall cout
jc pstr2
sjmp pstr1
pstr2: pop acc
ret
;converts the ascii code in Acc to uppercase, if it is lowercase
; Code efficient (saves 6 byes) upper contributed
; by Alexander B. Alexandrov <abalex@cbr.spb.ru>
upper:
cjne a, #97, upper2
upper2: jc upper4 ;end if acc < 97
cjne a, #123, upper3
upper3: jnc upper4 ;end if acc >= 123
add a, #224 ;convert to uppercase
upper4: ret
lenstr: mov r0, #0 ;returns length of a string in r0
push acc
lenstr1:clr a
movc a,@a+dptr
jz lenstr2
mov c,acc.7
inc r0
Jc lenstr2
inc dptr
sjmp lenstr1
lenstr2:pop acc
ret
esc: ;checks to see if <ESC> is waiting on serial port
;C=clear if no <ESC>, C=set if <ESC> pressed
;buffer is flushed
push acc
clr c
jnb ri,esc2
mov a,sbuf
cjne a,#27,esc1
setb c
esc1: clr ri
esc2: pop acc
ret
;---------------------------------------------------------;
; ;
; The 'high-level' stuff to interact with the user ;
; ;
;---------------------------------------------------------;
menu: ;first we print out the prompt, which isn't as simple
;as it may seem, since external code can add to the
;prompt, so we've got to find and execute all of 'em.
mov dptr, #prompt1 ;give 'em the first part of prompt
acall pcstr_h
mov a, r7
acall phex
mov a, r6
acall phex
;mov dptr, #prompt2
acall pstr
;now we're finally past the prompt, so let's get some input
acall cin_filter_h ;get the input, finally
cjne a, #':', menu0
acall dnld_now
sjmp menu
menu0: acall upper
;push return address onto stack so we can just jump to the program
mov b, #(menu & 255) ;we push the return address now,
push b ;to save code later...
mov b, #(menu >> 8) ;if bogus input, just ret for
push b ;another prompt.
;first we'll look through memory for a program header that says
;it's a user installed command which matches what the user pressed
;user installed commands need to avoid changing R6/R7, which holds
;the memory pointer. The stack pointer can't be changed obviously.
;all the other general purpose registers should be available for
;user commands to alter as they wish.
menux: mov b, a ;now search for external commands...
mov dptr, #bmem
menux1: acall find
jnc menuxend ;searched all the commands?
mov dpl, #4
clr a
movc a,@a+dptr
cjne a, #254, menux2 ;only FE is an ext command
inc dpl
clr a
movc a,@a+dptr
cjne a, b, menux2 ;only run if they want it
acall space
mov dpl, #32
acall pstr ;print command name
acall newline
mov dpl, #64
clr a
jmp @a+dptr ;take a leap of faith and jump to it!
menux2: inc dph
mov a, dph
cjne a, #((emem+1) >> 8) & 255, menux1
menuxend:
mov a, b
;since we didn't find a user installed command, use the builtin ones
menu1a:
menu1b: cjne a, #help_key, menu1c
mov dptr, #help_cmd2
acall pcstr_h
ajmp help
menu1c: cjne a, #dir_key, menu1d
mov dptr, #dir_cmd
acall pcstr_h
ajmp dir
menu1d: cjne a, #run_key, menu1e
mov dptr, #run_cmd
acall pcstr_h
ajmp run
menu1e: cjne a, #dnld_key, menu1f
mov dptr, #dnld_cmd
acall pcstr_h
ajmp dnld
menu1f: cjne a, #upld_key, menu1g
mov dptr, #upld_cmd
acall pcstr_h
ajmp upld
menu1g: cjne a, #nloc_key, menu1h
mov dptr, #nloc_cmd
acall pcstr_h
ajmp nloc
menu1h: cjne a, #jump_key, menu1i
mov dptr, #jump_cmd
acall pcstr_h
ajmp jump
menu1i: cjne a, #dump_key, menu1j
mov dptr, #dump_cmd
acall pcstr_h
ajmp dump
menu1j: cjne a, #edit_key, menu1k
mov dptr, #edit_cmd
acall pcstr_h
ajmp edit
menu1k: cjne a, #clrm_key, menu1l
mov dptr, #clrm_cmd
acall pcstr_h
ajmp clrm
menu1l: cjne a, #erfr_key, menu1m
mov a, #has_flash
jz menu_end
mov dptr, #erfr_cmd
acall pcstr_h
ajmp erfr
menu1m: cjne a, #intm_key, menu1n
mov dptr, #intm_cmd
acall pcstr_h
ljmp intm
menu1n:
;invalid input, no commands to run...
menu_end: ;at this point, we have not found
ajmp newline ;anything to run, so we give up.
;remember, we pushed menu, so newline
;will just return to menu.
;..........................................................
;---------------------------------------------------------;
;dnlds1 = "Begin sending Intel HEX format file <ESC> 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 dptr, #dnlds1
acall pcstr_h ;"begin sending file <ESC> to abort"
acall dnld_init
;look for begining of line marker ':'
dnld1: acall cin
cjne a, #27, dnld2 ;Test for escape
sjmp dnld_esc
dnld2: cjne a, #':', dnld2b
sjmp dnld2d
dnld2b: ;check to see if it's a hex digit, error if it is
acall asc2hex
jc dnld1
mov r1, #6
acall dnld_inc
sjmp dnld1
dnld_now: ;entry point for main menu detecting ":" character
mov a, #'^'
acall cout
acall dnld_init
dnld2d: mov r1, #0
acall dnld_inc
;begin taking in the line of data
dnld3: ;mov a, #'.'
;acall cout
mov r4, #0 ;r4 will count up checksum
acall dnld_ghex
mov r0, a ;R0 = # of data bytes
mov a, #'.'
acall cout
acall dnld_ghex
mov dph, a ;High byte of load address
acall dnld_ghex
mov dpl, a ;Low byte of load address
acall dnld_ghex ;Record type
cjne a, #1, dnld4 ;End record?
sjmp dnld_end
dnld4: jnz dnld_unknown ;is it a unknown record type???
dnld5: mov a, r0
jz dnld_get_cksum
acall dnld_ghex ;Get data byte
mov r2, a
mov r1, #1
acall dnld_inc ;count total data bytes received
mov a, r2
lcall smart_wr ;c=1 if an error writing
clr a
addc a, #2
mov r1, a
; 2 = bytes written
; 3 = bytes unable to write
acall dnld_inc
inc dptr
djnz r0, dnld5
dnld_get_cksum:
acall dnld_ghex ;get checksum
mov a, r4
jz dnld1 ;should always add to zero
dnld_sumerr:
mov r1, #4
acall dnld_inc ;all we can do it count # of cksum errors
sjmp dnld1
dnld_unknown: ;handle unknown line type
mov a, r0
jz dnld_get_cksum ;skip data if size is zero
dnld_ukn2:
acall dnld_ghex ;consume all of unknown data
djnz r0, dnld_ukn2
sjmp dnld_get_cksum
dnld_end: ;handles the proper end-of-download marker
mov a, r0
jz dnld_end_3 ;should usually be zero
dnld_end_2:
acall dnld_ghex ;consume all of useless data
djnz r0, dnld_ukn2
dnld_end_3:
acall dnld_ghex ;get the last checksum
mov a, r4
jnz dnld_sumerr
acall dnld_dly
mov dptr, #dnlds3
acall pcstr_h ;"download went ok..."
;consume any cr or lf character that may have been
;on the end of the last line
jnb ri, dnld_sum
acall cin
sjmp dnld_sum
dnld_esc: ;handle esc received in the download stream
acall dnld_dly
mov dptr, #dnlds2
acall pcstr_h ;"download aborted."
sjmp 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 r0, #0
dnlddly2:mov r1, #0
djnz r1, * ;roughly 128k cycles, appox 0.1 sec
djnz r0, dnlddly2
ret
dnld_inc: ;increment parameter specified by R1
;note, values in Acc and R1 are destroyed
mov a, r1
anl a, #00000111b ;just in case
rl a
add a, #dnld_parm
mov r1, a ;now r1 points to lsb
inc @r1
mov a, @r1
jnz dnldin2
inc r1
inc @r1
dnldin2:ret
dnld_gp: ;get parameter, and inc to next one (@r1)
;carry clear if parameter is zero.
;16 bit value returned in dptr
setb c
mov dpl, @r1
inc r1
mov dph, @r1
inc r1
mov a, dpl
jnz dnldgp2
mov a, dph
jnz dnldgp2
clr c
dnldgp2:ret
;a spacial 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.
dnld_ghex:
dnldgh1:acall cin
acall upper
cjne a, #27, dnldgh3
dnldgh2:pop acc
pop acc
sjmp dnld_esc
dnldgh3:cjne a, #':', dnldgh5
dnldgh4:mov r1, #5 ;handle unexpected beginning of line
acall dnld_inc
pop acc
pop acc
ajmp dnld3 ;and now we're on a new line!
dnldgh5:acall asc2hex
jnc dnldgh6
mov r1, #7
acall dnld_inc
sjmp dnldgh1
dnldgh6:mov r2, a ;keep first digit in r2
dnldgh7:acall cin
acall upper
cjne a, #27, dnldgh8
sjmp dnldgh2
dnldgh8:cjne a, #':', dnldgh9
sjmp dnldgh4
dnldgh9:acall asc2hex
jnc dnldghA
mov r1, #7
acall dnld_inc
sjmp dnldgh7
dnldghA:xch a, r2
swap a
orl a, r2
mov r2, a
add a, r4 ;add into checksum
mov r4, a
mov a, r2 ;return value in acc
ret
;dnlds4 = "Summary:"
;dnlds5 = " lines received"
;dnlds6a = " bytes received"
;dnlds6b = " bytes written"
dnld_sum: ;print out download summary
mov a, r6
push acc
mov a, r7
push acc
mov dptr, #dnlds4
acall pcstr_h
mov r1, #dnld_parm
mov r6, #dnlds5 & 255
mov r7, #dnlds5 >> 8
acall dnld_i0
mov r6, #dnlds6a & 255
mov r7, #dnlds6a >> 8
acall dnld_i0
mov r6, #dnlds6b & 255
mov r7, #dnlds6b >> 8
acall dnld_i0
dnld_err: ;now print out error summary
mov r2, #5
dnlder2:acall dnld_gp
jc dnlder3 ;any errors?
djnz r2, dnlder2
;no errors, so we print the nice message
mov dptr, #dnlds13
acall pcstr_h
sjmp dlnd_sum_done
dnlder3: ;there were errors, so now we print 'em
mov dptr, #dnlds7
acall pcstr_h
;but let's not be nasty... only print if necessary
mov r1, #(dnld_parm+6)
mov r6, #dnlds8 & 255
mov r7, #dnlds8 >> 8
acall dnld_item
mov r6, #dnlds9 & 255
mov r7, #dnlds9 >> 8
acall dnld_item
mov r6, #dnlds10 & 255
mov r7, #dnlds10 >> 8
acall dnld_item
mov r6, #dnlds11 & 255
mov r7, #dnlds11 >> 8
acall dnld_item
mov r6, #dnlds12 & 255
mov r7, #dnlds12 >> 8
acall dnld_item
dlnd_sum_done:
pop acc
mov r7, a
pop acc
mov r6, a
ajmp newline
dnld_item:
acall dnld_gp ;error conditions
jnc dnld_i3
dnld_i2:acall space
lcall pint16u
acall r6r7todptr
acall pcstr_h
dnld_i3:ret
dnld_i0:acall dnld_gp ;non-error conditions
sjmp dnld_i2
dnld_init:
;init all dnld parms to zero.
mov r0, #dnld_parm
dnld0: mov @r0, #0
inc r0
cjne r0, #dnld_parm + 16, dnld0
ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -