📄 jw002.asm
字号:
lcall pushbutton mov c, pb_recv_4 mov r0, #pb_state+9 mov r1, #pb_config+9 lcall pushbutton mov pb_scan_state, #2 setb pb_xmit_1 setb pb_xmit_2 clr pb_xmit_3 pop reg1 pop reg0 pop acc pop psw retipb_row_3: mov c, pb_recv_1 mov r0, #pb_state+3 mov r1, #pb_config+3 lcall pushbutton mov c, pb_recv_2 mov r0, #pb_state+2 mov r1, #pb_config+2 lcall pushbutton mov c, pb_recv_3 mov r0, #pb_state+7 mov r1, #pb_config+7 lcall pushbutton mov c, pb_recv_4 mov r0, #pb_state+11 mov r1, #pb_config+11 lcall pushbutton mov pb_scan_state, #0 clr pb_xmit_1 setb pb_xmit_2 setb pb_xmit_3 pop reg1 pop reg0 pop acc pop psw reti ;Let's be really paranoid, and only reset the watchdog if some ;sanity checks are valid. If any of these checks fail, something ;has done horribly wrong and we must reboot. ;Checks: uart and timer1 confired, stack pointer is legalwatchdog: mov a, th1 cjne a, #baud_const, reboot mov a, tmod cjne a, #0x21, reboot mov a, tcon anl a, #01010000b cjne a, #0x50, reboot mov a, scon anl a, #11110000b cjne a, #0x50, reboot mov a, pcon jnb acc.7, reboot mov a, sp add a, #256 - stack jnc reboot cpl watchdog_pin retreboot: ljmp locationretinow: reti .equ event_dn, 0x10 .equ event_up, 0x20 .equ event_ar, 0x30 ;C = pushbutton state ;r0 = ptr to pb_state ;r1 = ptr to pb_configpushbutton: jc pb_uppb_dn: ;the button is being pressed right now! mov a, @r0 jz pb_dn_wait dec a jnz pb_ar mov @r0, #2 mov a, r0 add a, #(event_dn - pb_state) & 255 sjmp emit_pb_eventpb_dn_wait: mov @r0, #1 retpb_ar: ;the button has been down for a while inc @r0 mov a, @r1 anl a, #3 add a, #2 movc a, @a+pc ;grab auto-repeat threshold sjmp pb_ar2 .db 120, 90, 65, 43pb_ar2: clr c subb a, @r0 jnc pb_end ;did we hit the auto-repeat threshold? mov a, @r1 rr a rr a anl a, #7 add a, #2 movc a, @a+pc ;grab auto-repeat speed sjmp pb_ar3 .db 40, 34, 29, 23, 18, 15, 12, 8pb_ar3: cpl a inc a add a, @r0 mov @r0, a mov a, r0 add a, #(event_ar - pb_state) & 255 sjmp emit_pb_eventpb_up: ;the button is not presssed mov a, @r0 jz pb_end dec a jz pb_up_ignore mov @r0, #0 mov a, r0 add a, #(event_up - pb_state) & 255 sjmp emit_pb_eventpb_up_ignore: mov @r0, #0pb_end: retemit_pb_event: mov r0, a mov a, pb_event_head inc a cjne a, pb_event_tail, evt_ok ret ;event queue is full! discard eventevt_ok: mov pb_event_head, a push dpl mov r1, dph mov dph, #pb_events_page mov dpl, a mov a, r0 movx @dptr, a ;put event into the event queue mov dph, r1 pop dpl ret ;get the next event from the event queue, Acc=0 for noneget_event: clr et0 mov a, pb_event_tail cjne a, pb_event_head, getevt2 ;check if buffer empty setb et0 clr a ret ;no pending eventsgetevt2:inc a mov pb_event_tail, a mov dpl, a mov dph, #pb_events_page movx a, @dptr ;read event from queue setb et0 retprint_event: ;push acc ;lcall phex ;mov a, #'-' ;lcall cout ;pop acc acall event2addr mov r2, #14 movx a, @dptr jz pr_evt_done ;don't print anything if null stringpr_evt_loop: movx a, @dptr jz pr_evt_end lcall cout inc dptr djnz r2, pr_evt_looppr_evt_end: lcall newlinepr_evt_done: retevent2addr: mov r2, a ;store the event in r2 anl a, #15 add a, #244 jc illegal_event_addr mov a, r2 swap a anl a, #15 dec a mov r3, a add a, #253 jc illegal_event_addr mov a, r2 anl a, #15 mov b, #3 mul ab add a, r3 mov b, #14 ;strlen max of 14 bytes mul ab mov dpl, a mov a, b add a, #pb_strings_page mov dph, a clr c retillegal_event_addr: mov dpl, #248 mov dph, #pb_strings_page+1 setb c ret ;***********************************************************************;** **;** Serial Port Routines **;** **;***********************************************************************init_uart_intr: clr ea orl pcon, #10000000b ;set double baud rate anl tmod, #00001111b ;clear all timer1 bits in tmod orl tmod, #00100000b ;set timer1 as 8 bit auto reload clr tr1 ;make sure timer1 isn't running clr tf1 mov a, #baud_const mov th1, a ;set timer1 rate mov tl1, a mov scon, #01010000b ;config serial port (ri and ti cleared) mov rx_buf_head, #0 ;set up empty receive buffer mov rx_buf_tail, #0 mov tx_buf_head, #0 ;set up transmit buffer as empty mov tx_buf_tail, #0 clr tx_intr_expected ;and no tx interrupt expected setb tr1 ;start timer1 setb es ;enable serial port interrupt setb ea ;also turn on interrupts in general ret;service interrupts generated by the uart... put a received character;into the receive buffer or get a character from the transmit buffer;and send it.uart_intr: push psw push acc jb ti, xmitrecv: clr ri mov a, rx_buf_head inc a cjne a, rx_buf_tail, recv_ok ;check for buffer full ;If we got here, the recv buffer is full, so we just ;discard this character. Maybe there should be an overrun ;flag so the main program can know some data was lost... mov a, sbuf pop acc pop psw retirecv_ok:mov rx_buf_head, a ;update rx_buf_head while it's still in Acc. push dpl push dph mov dph, #rx_buf_page mov dpl, a mov a, sbuf ;get the incoming data movx @dptr, a ;and put it in the buffer pop dph pop dpl pop acc pop psw retixmit: clr ti mov a, tx_buf_tail cjne a, tx_buf_head, xmit_ok ;check for buffer empty ;If we got here, there is no data waiting to transmit. The ;uart won't generate more interrupts, so the cout routine had ;better check set ti. tx_buf_head is loaded with zero to that ;cout will know to set ti. clr tx_intr_expected pop acc pop psw retixmit_ok:inc a mov tx_buf_tail, a ;update tx_buf_tail while it's still in Acc. push dpl push dph mov dph, #tx_buf_page mov dpl, a movx a, @dptr mov sbuf, a pop dph pop dpl setb tx_intr_expected pop acc pop psw reti;Get a character from the receive buffer. C=0 if char recv, C=1 if nonecin: setb cin_serviced clr es mov a, rx_buf_tail cjne a, rx_buf_head, cin_ok ;check if buffer empty setb es setb c retcin_ok: inc a mov rx_buf_tail, a push dpl push dph mov dpl, a mov dph, #rx_buf_page movx a, @dptr pop dph pop dpl setb es clr c ret;Put the character in Acc into the transmit buffer. If the buffer is;full, wait until these is a space to put it.cout: push psw xch a, r0 ;put char to send into r0 push acc ;keep r0 on stackcout_wt:clr es jb tx_intr_expected, cout2 ;check if not transmitting setb ti ;set ti in software since buffer is empty clr a mov tx_buf_head, a mov tx_buf_tail, a setb tx_intr_expectedcout2: mov a, tx_buf_head inc a cjne a, tx_buf_tail, cout4 ;check if buffer full setb es nop ;wait for space in buffer sjmp cout_wtcout4: mov tx_buf_head, a ;update tx_buf_head push dph push dpl mov dph, #tx_buf_page mov dpl, a xch a, r0 movx @dptr, a pop dpl pop dph setb es xch a, r0 ;restore r0 value and Acc pop acc xch a, r0 pop psw ret; Highly code efficient resursive call phex contributed; by Alexander B. Alexandrov <abalex@cbr.spb.ru>phex:phex8: acall phex_bphex_b: swap a ;SWAP A will be twice => A unchangedphex1: push acc anl a, #15 add a, #0x90 ; acc is 0x9X, where X is hex digit da a ; if A to F, C=1 and lower four bits are 0..5 addc a, #0x40 da a lcall cout pop acc retnewline:push acc ;print one newline mov a, #13 lcall cout mov a, #10 lcall cout pop acc retpstr: clr a movc a, @a+dptr inc dptr jz pstr2 lcall cout sjmp pstrpstr2: ret;***********************************************************************;** **;** Fonts and Font Manipulation **;** **;*********************************************************************** ;use the character in Acc and "font" to lookup the 5 byte ;data to draw a character, and copy it into "char_buf".lookup_char: push acc mov b, #5 mul ab mov dpl, a ;compute offset within font mov dph, b mov a, font mov b, #5 mul ab ;compute font's location add a, #fonts_start_page add a, dph mov dph, a ;dptr points to the character we need movx a, @dptr mov char_buf+0, a inc dptr movx a, @dptr mov char_buf+1, a inc dptr movx a, @dptr mov char_buf+2, a inc dptr movx a, @dptr mov char_buf+3, a inc dptr movx a, @dptr mov char_buf+4, a pop acc rettest_font: ;r6 has the first character to draw push mode_bits clr vscroll_mode clr wrap_mode lcall init_display mov r4, #0tfont2: mov r5, #16 mov x_pos, #8 mov y_pos, r4tfont3: mov a, r6 push acc lcall lookup_char lcall cache_char pop acc mov r6, a inc r6 djnz r5, tfont3 inc r4 cjne r4, #8, tfont2 pop mode_bits ret;**************************************************************************;** **;** Character Caching Routines **;** **;**************************************************************************cache_char: jb hscroll_fill_en, hscroll_fill mov a, y_pos ;ignore updates to scrolling rows lcall check_hscroll_en jnc cache_char_ok retcache_char_ok: jnb update_mode, cache_char_only lcall draw_charcache_char_only: mov a, x_pos add a, #244 jnc cache_char_left add a, #244 jnc cache_char_right retcache_char_right: subb a, #244 mov dph, #display_cache+2 sjmp cache_display_contcache_char_left: mov dph, #display_cache mov a, x_poscache_display_cont: mov b, #5 ;x_pos*5 to give column address mul ab anl a, #00111111b mov dpl, a mov a, vscroll_offset ;calculate row address swap a rl a add a, y_pos anl a, #00000111b swap a ;mult row address * 64 clr c rlc a clr c rlc a jnc cache_char_noovr ;handle overflow into dph inc dphcache_char_noovr: orl a, dpl mov dpl, a ;write 5 vertical slices of character mov a, char_buf+0 movx @dptr, a inc dptr mov a, char_buf+1 movx @dptr, a inc dptr mov a, char_buf+2 movx @dptr, a inc dptr mov a, char_buf+3 movx @dptr, a inc dptr mov a, char_buf+4 movx @dptr, a mov a, #1 lcall move_cursor_right rethscroll_fill: mov a, hscroll_fill_row orl a, #hscroll_buffer mov dph, a anl a, #00000111b add a, #hscroll_end0 mov r0, a mov dpl, @r0 mov a, r2 movx @dptr, a inc @r0 retclear_cached_display: mov dph, #display_cache mov dpl, #0 clr aclear_cached_display_loop: movx @dptr, a inc dptr mov r0, dph cjne r0, #display_cache+4, clear_cached_display_loop retcopy_fonts_to_sram: mov dptr, #fonts ;dptr = source address mov r0, #0 ;r0/r1 = destination address mov r1, #fonts_start_pagecpy_fonts_loop1: mov p2, r1cpy_fonts_loop2: clr a movc a, @a+dptr inc dptr movx @r0, a inc r0 cjne r0, #0, cpy_fonts_loop2 inc r1 cjne r1, #fonts_start_page + (num_rom_fonts * 5), cpy_fonts_loop1 mov p2, #255 retcopy_strings_to_sram: mov dptr, #default_event_strings ;dptr = source address mov r0, #0 ;r0/r1 = destination address mov r1, #pb_strings_pagecpy_str_loop1: mov p2, r1cpy_str_loop2: clr a movc a, @a+dptr inc dptr movx @r0, a inc r0 cjne r0, #0, cpy_str_loop2 inc r1 cjne r1, #pb_strings_page + 2, cpy_str_loop1 mov p2, #255 ret msg_font: .db "Font #",0msg_f0: .db "0 to",0 .db "127",0msg_f128: .db "128 to",0 .db "255",0mesg_abort: .db "Press ESC twice to return to PAULMON2",13,10,13,10,0mesg_version: .db "VERSION",0mesg_io_read: .db "IOREAD",0default_event_strings: .db "b0_down",0,0,0,0,0,0,0 .db "b0_up",0,0,0,0,0,0,0,0,0 .db "b0_repeat",0,0,0,0,0 .db "b1_down",0,0,0,0,0,0,0 .db "b1_up",0,0,0,0,0,0,0,0,0 .db "b1_repeat",0,0,0,0,0 .db "b2_down",0,0,0,0,0,0,0 .db "b2_up",0,0,0,0,0,0,0,0,0 .db "b2_repeat",0,0,0,0,0 .db "b3_down",0,0,0,0,0,0,0 .db "b3_up",0,0,0,0,0,0,0,0,0 .db "b3_repeat",0,0,0,0,0 .db "b4_down",0,0,0,0,0,0,0 .db "b4_up",0,0,0,0,0,0,0,0,0 .db "b4_repeat",0,0,0,0,0 .db "b5_down",0,0,0,0,0,0,0 .db "b5_up",0,0,0,0,0,0,0,0,0 .db "b5_repeat",0,0,0,0,0 .db "b6_down",0,0,0,0,0,0,0 .db "b6_up",0,0,0,0,0,0,0,0,0 .db "b6_repeat",0,0,0,0,0 .db "b7_down",0,0,0,0,0,0,0 .db "b7_up",0,0,0,0,0,0,0,0,0 .db "b7_repeat",0,0,0,0,0 .db "b8_down",0,0,0,0,0,0,0 .db "b8_up",0,0,0,0,0,0,0,0,0 .db "b8_repeat",0,0,0,0,0 .db "b9_down",0,0,0,0,0,0,0 .db "b9_up",0,0,0,0,0,0,0,0,0 .db "b9_repeat",0,0,0,0,0 .db "b10_down",0,0,0,0,0,0 .db "b10_up",0,0,0,0,0,0,0,0 .db "b10_repeat",0,0,0,0 .db "b11_down",0,0,0,0,0,0 .db "b11_up",0,0,0,0,0,0,0,0 .db "b11_repeat",0,0,0,0 .db "error",0,0,0fonts: ; this must be the last label of the file, because the build ; process in the makefile will add the fonts after this point
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -