📄 pm2_mp3.asm
字号:
setb c
esc1: clr ri
esc2: pop acc
ret
find_h: ljmp find
;---------------------------------------------------------;
; ;
; 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
lcall get_bank
clr a
addc a, #'0'
acall cout
mov a, r7
acall phex
mov a, r6
acall phex
;mov dptr, #prompt2
acall pstr
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_h
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 dptr, #erfr_cmd
acall pcstr_h
ajmp erfr
menu1m: cjne a, #intm_key, menu1n
mov dptr, #intm_cmd
acall pcstr_h
ljmp intm
menu1n: cjne a, #'0', menu1o
acall newline
ljmp set_bank0
menu1o: cjne a, #'1', menu1p
acall newline
ljmp set_bank1
menu1p:
;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_addr20:
cjne r0, #2, dnld_unknown_h ;addr records always 2 bytes
acall dnld_ghex
swap a
rrc a
lcall set_bank
acall dnld_ghex
sjmp dnld_get_cksum
dnld_addr32:
cjne r0, #2, dnld_unknown_h ;addr records always 2 bytes
acall dnld_ghex
acall dnld_ghex
rrc a
lcall set_bank
sjmp dnld_get_cksum
dnld_unknown_h:
ajmp dnld_unknown
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
ajmp 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: cjne a, #2, dnld4b
sjmp dnld_addr20
dnld4b: cjne a, #4, dnld4c
sjmp dnld_addr32
dnld4c: 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
;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 dptr, #prompt8
acall pcstr_h
acall r6r7todptr
acall phex16
mov dptr, #prompt4
acall pcstr_h
acall ghex16
jb psw.5, jump3
jnc jump2
ajmp abort2
jump2:
acall dptrtor6r7
jump3: acall newline
mov dptr, #runs1
acall pcstr_h
acall r6r7todptr
jump_doit: ;jump to user code @dptr (this used by run command also)
clr a
mov psw, a
mov b, a
mov r0, #7
jditclr:mov @r0, a ;clear r7 to r1
djnz r0, jditclr ;clear r0
mov sp, #8 ;start w/ sp=7, like a real reset
push acc ;unlike a real reset, push 0000
push acc ;in case they end with a RET
jmp @a+dptr
;---------------------------------------------------------;
dump:
mov r2, #16 ;number of lines to print
acall newline2
dump1:
lcall get_bank
clr a
addc a, #'0'
acall cout
acall r6r7todptr
acall phex16 ;tell 'em the memory location
mov a,#':'
acall cout_sp
mov r3, #16 ;r3 counts # of bytes to print
acall r6r7todptr
dump2: clr a
movc a, @a+dptr
inc dptr
acall phex ;print each byte in hex
acall space
djnz r3, dump2
acall dspace ;print a couple extra space
mov r3, #16
acall r6r7todptr
dump3: clr a
movc a, @a+dptr
inc dptr
anl a, #01111111b ;avoid unprintable characters
cjne a, #127, dump3b
clr a ;avoid 127/255 (delete/rubout) char
dump3b: add a, #224
jc dump4
clr a ;avoid control characters
dump4: add a, #32
acall cout
djnz r3, dump3
acall newline
acall line_dly
acall dptrtor6r7
acall esc
jc dump5
djnz r2, dump1 ;loop back up to print next line
dump5: ajmp newline
;---------------------------------------------------------;
edit: ;edit external ram...
mov dptr, #edits1
acall pcstr_h
acall r6r7todptr
edit1: acall phex16
mov a,#':'
acall cout_sp
mov a,#'('
acall cout
acall dptrtor6r7
clr a
movc a, @a+dptr
acall phex
mov dptr,#prompt10
acall pcstr_h
acall ghex
jb psw.5,edit2
jc edit2
acall r6r7todptr
lcall smart_wr
acall newline
acall r6r7todptr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -