Peter Verkaik says:
Unable to find an existing uart for 8 databits + parity I wrote one myself. I saw a few posts on the basic stamp forum about this so I share this. It is an assembly source.The program itself contains more than just the uart as it is written as a template to be extended for applications.
;***************************************************************************************** ; ELX1 board, co-procesor template ; ---------------------------------------------------------------------------------------- ; ; version 0.9 beta ; december 9, 2004 ; compile with SASM ; ; Author: Peter Verkaik ; Email: peterverkaik@boselectro.nl ; ; This program is a SX28 template providing a 2-wire host interface (halfduplex serial line + ; write enable line used for synchronization), and a 2-wire serial interface for terminal or ; other serial device. This terminal interface can be configured at runtime for: ; TX/RX with or without xon/xoff handshake, TX only with CTS handshake, RX only with RTS handshake ; four selectable baudrates (default 1200,2400,9600,19200) ; 7 or 8 databits ; parity odd, even or none ; powerup default is TX/RX without handshake, 1200 baud, 8 databits, no parity ; Port A is dedicated to the host and terminal. ; Ports B and C are not used and are available for the application. ; Code pages 2 and 3 are empty ; Ram banks 4, 5, 6 and 7 are empty ; 5 free global ram bank bytes ; four 8-byte buffers for terminal and host uarts ; Host command interface is expandable for up to 128 commands ; ;***************************************************************************************** ; Connection diagram. Both wires should have 4.7k-10k pullup resistor. ; ; MCU co-processor (this device) ; -------+ +------------------------+ ; | | | ; pinWE o------o RA.1 = /WE | ; pinDQ o------o RA.0 = DQ | ; | | RC.0-RC.7 o-- application ; -------+ | RB.0-RB.7 o-- application ; | | ; | RA.2 o-- terminal TX (or RTS in case of RX/RTS) ; | RA.3 o-- terminal RX (or CTS in case of TX/CTS) ; +------------------------+ ; ;***************************************************************************************** ; Communication protocol between this device and the host MCU. ; ; ------+ +-+ +------+----- ; pinWE S0 | S1 | S2 | | S3 | S4 | S5 | S0 ; +-----+-------------------+ +-----+-----------------------+ ; <--- pulled low by MCU ---> <- pulled low by this device -> ; ; ------+ +-+ +------+----- ; pinDQ <cmd> <param1>...<paramN> <rsp> <data1>...<dataN> ; - hiZ +- - - - - input - - - - -+-+ - - - - output - - - - - - -+ - - hiZ - - ; ; State S0: idle ; State S1: receive command byte ; State S2: receive parameter bytes ; State S3: transmit response byte ; State S4: transmit data bytes ; State S5: finalize ; ; Each command sequence starts at the H->L transition on pinWE. ; This may be follwed by <cmd> and <param> bytes. ; A L->H transition on pinWE (from MCU) is ALWAYS follewed by ; a H->L transition and <rsp>. ; <data> bytes are optional and determined by command or status. ; The command sequence stops after this device releases pinWE. ; ;----------------------------------------------------------------------------------------- ; program modules ;----------------------------------------------------------------------------------------- device SX28,oschs1,turbo,stackx,optionx ;sx device options irc_cal IRC_SLOW id 'ELX1TMPL' ;Elx1 board template reset reset_entry ;set reset vector ;select one of these freq ;freq 4_000_000 ;freq 10_000_000 freq 20_000_000 ;select according to freq ;RESONATOR equ 4 ;RESONATOR equ 10 RESONATOR equ 20 ERROR p2w 'Assembled assuming a ' RESONATOR ' MHz oscillator' ; The host interface (pins ra.0 and ra.1) is used to accept commands and data ; from a host mcu and delivers status and data to that mcu. ; The terminal interface (pins ra.2 and ra.3) is used to accept key input from a terminal(program) ; and delivers display/control characters to that terminal(program). ;----------------------------------------------------------------------------------------- ; uart constants ;----------------------------------------------------------------------------------------- IF RESONATOR = 20 ;128*1200=64*2400=32*4800=16*9600=8*19200 ;uartfs=128*1200=153600 ;int_period=20000000/153600=130 uartfs equ 153600 ; uart's basic frequency 128*1200 = 153600 int_period equ 130 ; 6.5uS used as seed for uart baud rate. THREADS equ 1 ENDIF IF RESONATOR = 10 ;64*1200=32*2400=16*4800=8*9600=4*19200 ;uartfs=64*1200=76800 ;int_period=10000000/76800=130 uartfs equ 76800 ; uart's basic frequency 64*1200 = 76800 int_period equ 130 ; 13uS used as seed for uart baud rate. THREADS equ 1 ENDIF IF RESONATOR = 4 ;32*1200=16*2400=8*4800=4*9600=2*19200 ;uartfs=32*1200=38400 ;int_period=4000000/38400=104 uartfs equ 38400 ; uart's basic frequency 32*1200 = 38400 int_period equ 104 ; 26uS used as seed for uart baud rate. THREADS equ 1 ENDIF mscount equ ((2000*RESONATOR/int_period)+1)/2 ;number of int cycles for 1 msec ERROR p2w '# of cycles per interrupt = ' mscount XON equ 17 ;XON character (ctrl-Q) XOFF equ 19 ;XOFF character (ctrl-S) ;The following baudrates are available baud0 equ 1200 baud1 equ 2400 baud2 equ 4800 baud3 equ 9600 baud4 equ 19200 ; 20MHz 10MHz 4MHz divide0 equ uartfs / (baud0 * THREADS) ; 128 64 32 StDelay0 equ divide0 + (divide0 / 2) ; 192 96 48 divide1 equ uartfs / (baud1 * THREADS) ; 64 32 16 StDelay1 equ divide1 + (divide1 / 2) ; 96 48 24 divide2 equ uartfs / (baud2 * THREADS) ; 32 16 8 StDelay2 equ divide2 + (divide2 / 2) ; 48 24 12 divide3 equ uartfs / (baud3 * THREADS) ; 16 8 4 StDelay3 equ divide3 + (divide3 / 2) ; 24 12 6 divide4 equ uartfs / (baud4 * THREADS) ; 8 4 2 StDelay4 equ divide4 + (divide4 / 2) ; 12 6 3 hostDivide equ divide3 ;baud used by host hostStDelay equ StDelay3 ;----------------------------------------------------------------------------------------- ; Pin definitions & Port assignments ;----------------------------------------------------------------------------------------- ;host and term pin definitions hostDQ equ 0 hostWE equ 1 pinDQ equ ra.hostDQ ;host uart transmit/receive pinWE equ ra.hostWE ;host write enable input termTX equ 2 termRX equ 3 pinTX equ ra.termTX ;term uart transmit pinRX equ ra.termRX ;term uart receive ; ra changes output level by changing direction register!! Never drive output high!! RA_latch equ %00000000 ;port A output latch init 1=high 0=low RA_tris equ %11111111 ;port A direction register 1=input 0=output RA_plp equ %00000000 ;port A pull up register 1=off 0=on RA_lvl equ %11111111 ;port A level register 1=ttl 0=cmos ; rb changes output level by changing direction register!! Never drive output high!! RB_latch equ %00000000 ;port B output latch 1=high 0=low RB_tris equ %11111111 ;port B direction register 1=input 0=output RB_plp equ %00000000 ;port B pull up register 1=off 0=on RB_lvl equ %00000000 ;port B level register 1=ttl 0=cmos RB_st equ %11111111 ;port B schmitt trigger register 1=off 0=on RB_wken equ %11111111 ;port B wake up enable register 1=off 0=on ** KEEP OFF RB_wked equ %11111111 ;port B wake up edge register 1=neg 0=pos ; rc changes output level by changing direction register!! Never drive output high!! RC_latch equ %00000000 ;port C output latch 1=high 0=low RC_tris equ %11111111 ;port C direction register 1=input 0=output RC_plp equ %00000000 ;port C pull up register 1=off 0=on RC_lvl equ %11111111 ;port C level register 1=ttl 0=cmos RC_st equ %11111111 ;port C schmitt trigger register 1=off 0=on ;----------------------------------------------------------------------------------------- ; Code Locations ;----------------------------------------------------------------------------------------- CODEPAGE_0 equ $0 CODEPAGE_1 equ $200 CODEPAGE_2 equ $400 CODEPAGE_3 equ $600 ;----------------------------------------------------------------------------------------- ; Data Memory address definitions ;----------------------------------------------------------------------------------------- global_org equ $08 bank0_org equ $10 bank1_org equ $30 bank2_org equ $50 bank3_org equ $70 bank4_org equ $90 bank5_org equ $B0 bank6_org equ $D0 bank7_org equ $F0 ;----------------------------------------------------------------------------------------- ; Global Register definitions ;----------------------------------------------------------------------------------------- org global_org temp ds 1 ;for temporary use (buffers, calculation) ra_dir_buf ds 1 ;holds value for ra direction register status_flags ds 1 cmd_invalid equ status_flags.0 ;set if command invalid cmd_parameter_missing equ status_flags.1 ;set if missing parameter buffer_overrun equ status_flags.2 ;set if any buffer overrun term_parity_error equ status_flags.3 ;set if parity error free_global ds 5 ;----------------------------------------------------------------------------------------- ; RAM Bank Register definitions ;----------------------------------------------------------------------------------------- ; Bank 0 - host uart bank, timer bank ;--------------------------------------------------------------------------------- org bank0_org hu_bank = $ ;host uart bank hu_rx_count ds 1 ;number of bits to receive hu_rx_divide ds 1 ;receive timing counter hu_rx_byte ds 1 ;received byte hu_tx_count ds 1 ;number of bits to transmit hu_tx_divide ds 1 ;transmit timing counter hu_tx_low ds 1 ;low byte to transmit hu_tx_high ds 1 ;high byte to transmit hu_head ds 1 ;hinib=tx, lonib=rx: index of next free entry in buf hu_tail ds 1 ;hinib=tx, lonib=rx: index of next byte to read from buf hu_num ds 1 ;hinib=tx, lonib=rx: number of bytes in buf hu_rx_full equ hu_num.3 ; set if hu_rx full (num=8) hu_tx_full equ hu_num.7 ; set if hu_tx full (num=8) hu_flags ds 1 hu_rx_data equ hu_flags.0 ;set if hu_rx not empty hu_rx_overrun equ hu_flags.1 ;set if hu_rx overruns hu_rx_enable equ hu_flags.2 ;set to enable host uart receive hu_rx_flag equ hu_flags.3 ;set if byte in hu_rx_byte hu_tx_data equ hu_flags.4 ;set if hu_tx not empty hu_tx_overrun equ hu_flags.5 ;set if hu_tx overruns hu_tx_enable equ hu_flags.6 ;set to enable host uart transmit hu_tx_flag equ hu_flags.7 ;not used hu_state ds 1 ;host state ; b2-b0: state of host_command_task routine pinWE_present equ hu_state.6 ; current state of pinWE pinWE_past equ hu_state.7 ; past state of pinWE hu_command ds 1 ;received host command cmd_done equ hu_command.7 ; set if command finished timer_bank = $ timer_int ds 1 ;increments every isr timer_1m ds 1 ;decrements every msec free_bank0 ds 1 ; Bank 1 - term uart bank ;--------------------------------------------------------------------------------- org bank1_org tu_bank = $ ;term uart bank tu_rx_count ds 1 ;number of bits to receive tu_rx_divide ds 1 ;receive timing counter tu_rx_byte ds 1 ;received byte tu_tx_count ds 1 ;number of bits to transmit tu_tx_divide ds 1 ;transmit timing counter tu_tx_low ds 1 ;low byte to transmit tu_tx_high ds 1 ;high byte to transmit tu_head ds 1 ;hinib=tx, lonib=rx: index of next free entry in buf tu_tail ds 1 ;hinib=tx, lonib=rx: index of next byte to read from buf tu_num ds 1 ;hinib=tx, lonib=rx: number of bytes in buf tu_rx_full equ tu_num.3 ; set if tu_rx full (num=8) tu_tx_full equ tu_num.7 ; set if tu_tx full (num=8) tu_flags ds 1 tu_rx_data equ tu_flags.0 ;set if tu_rx not empty tu_rx_overrun equ tu_flags.1 ;set if tu_rx overruns tu_rx_enable equ tu_flags.2 ;set if transmitted XON, cleared if transmitted XOFF tu_rx_flag equ tu_flags.3 ;set if byte in tu_rx_byte tu_tx_data equ tu_flags.4 ;set if tu_tx not empty tu_tx_overrun equ tu_flags.5 ;set if tu_tx overruns tu_tx_enable equ hu_flags.6 ;set if received XON, cleared if received XOFF tu_rx_parity equ tu_flags.7 ;received parity bit tu_state ds 1 ;term state (not implemented) tu_command ds 1 ;received term command (not implemented) tu_config ds 1 ;terminal configuration ; b1-b0 = baud (1200,2400,9600,19200) tu_rts equ tu_config.2 ; 1 for rts handshake (TX used as RTS) tu_cts equ tu_config.3 ; 1 for cts handshake (RX used as CTS) tu_xonxoff equ tu_config.4 ; 1 for xon/xoff handshake (inter-character delay must be 1 msec at 9600 baud) tu_7bits equ tu_config.5 ; 1 for 7 databits (0 = 8 databits) tu_parity_even equ tu_config.6 ; 1 for even parity tu_parity_odd equ tu_config.7 ; 1 for odd parity tu_char ds 1 ;save received byte here tu_bits ds 1 ;number of bits (startbit+databits+paritybit+stopbit) ; set by command TM_SET_CONFIG (bits is 9, 10 or 11) ; Bank 2 - host uart buffers ;--------------------------------------------------------------------------------- org bank2_org hu_buf_bank = $ hu_rx_buf ds 8 hu_tx_buf ds 8 ; Bank 3 - term uart buffers ;--------------------------------------------------------------------------------- org bank3_org tu_buf_bank = $ tu_rx_buf ds 8 tu_tx_buf ds 8 ; Bank 4 - ;--------------------------------------------------------------------------------- org bank4_org free_bank4 ds 16 ; Bank 5 - ;--------------------------------------------------------------------------------- org bank5_org free_bank5 ds 16 ; Bank 6 - ;--------------------------------------------------------------------------------- org bank6_org free_bank6 ds 16 ; Bank 7 - ;--------------------------------------------------------------------------------- org bank7_org free_bank7 ds 16 ;-------------- end of ram variables ----------------------------------------------------- ;***************************************************************************************** org CODEPAGE_0 ;***************************************************************************************** ;----------------------------------------------------------------------------------------- ; Interrupt Service Routine ;----------------------------------------------------------------------------------------- interrupt jmp _interrupt ;1 ; hooks for application ;--------------------------------------------------------------------------------- app_isr retp ;change to jmp @myapp_isr if any app_main retp ;change to jmp @myapp_main if any ; jump table for template ;--------------------------------------------------------------------------------- enqueue_hu_tx jmp _enqueue_hu_tx ;store byte for output to host enqueue_hu_rx jmp _enqueue_hu_rx ;store byte received from host dequeue_hu_tx jmp _dequeue_hu_tx ;retrieve byte for output to host dequeue_hu_rx jmp _dequeue_hu_rx ;retrieve byte received from host enqueue_tu_tx jmp _enqueue_tu_tx ;store byte for output to terminal enqueue_tu_rx jmp _enqueue_tu_rx ;store byte received from terminal dequeue_tu_tx jmp _dequeue_tu_tx ;retrieve byte for output to terminal dequeue_tu_rx jmp _dequeue_tu_rx ;retrieve byte received from terminal host_input_task jmp _host_input_task ;receives host bytes into hu_rx_buf host_output_task jmp _host_output_task ;transmit host bytes from hu_tx_buf ; get term baud parameters as determined by tu_config.0 and tu_config.1 ;--------------------------------------------------------------------------------- tu_divide mov w,tu_config and w,#$03 add pc,w retw divide0 ;1200 retw divide1 ;2400 retw divide3 ;9600 retw divide4 ;19200 tu_StDelay mov w,tu_config and w,#$03 add pc,w retw StDelay0 ;1200 retw StDelay1 ;2400 retw StDelay3 ;9600 retw StDelay4 ;19200 ; host command task ; Wait for a command received from host MCU, ; execute command and transmit results to host MCU. ;--------------------------------------------------------------------------------- STATE_IDLE equ 0 STATE_RECEIVE_COMMAND equ 1 STATE_RECEIVE_PARAMETER equ 2 STATE_TRANSMIT_RESPONSE equ 3 STATE_TRANSMIT_DATA equ 4 STATE_FINALIZE equ 5 host_command_task call @checkPinWE ;check for edges bank hu_bank mov w,hu_state and w,#$07 add pc,w jmp hostIdle ;0 jmp hostReceiveCommand ;1 jmp hostReceiveParameter ;2 jmp hostTransmitResponse ;3 jmp hostTransmitData ;4 jmp hostFinalize ;5 jmp hostIdle ;6 failsafe jmp hostIdle ;7 failsafe hostIdle clrb hu_rx_enable clrb hu_tx_enable setb ra_dir_buf.hostDQ setb ra_dir_buf.hostWE retp hostReceiveCommand sb hu_rx_data ;any received data? retp ;no call dequeue_hu_rx mov hu_command,w ;this is command mov w,#$7F snb cmd_done mov hu_command,w ;make command $7F if b7 is set clrb cmd_invalid clrb term_parity_error setb cmd_parameter_missing ;cleared by function call @host_command_handler ;execute command bank hu_bank inc hu_state ;move to next state retp hostReceiveParameter sb hu_rx_data ;any received data? retp ;no jmp @host_command_handler ;execute command hostTransmitResponse clrb ra_dir_buf.hostWE ;this device pulls pinWE low mov w,hu_flags and w,#$22 ;extract overrun flags sz setb buffer_overrun bank tu_bank mov w,tu_flags and w,#$22 ;extract overrun flags sz setb buffer_overrun mov w,status_flags ;transmit status flags call enqueue_hu_tx clrb hu_rx_overrun clrb hu_tx_overrun inc hu_state ;move to next state bank tu_bank clrb tu_rx_overrun clrb tu_tx_overrun clrb buffer_overrun retp hostTransmitData snb hu_tx_data ;output buffer empty? retp ;no call @host_command_handler ;get next data bank hu_bank snb cmd_done ;all done? inc hu_state ;yes, move to next state retp hostFinalize snb hu_tx_data ;output buffer empty retp ;no test hu_tx_count ;transmitter ready? sz retp ;no clrb hu_tx_enable ;disable transmitter setb ra_dir_buf.hostWE ;release pinWE and hu_state,#$C0 ;wait for new command retp ;-------------- start of the Interrupt Service Routines ---------------------------------- _interrupt ; Update timers ;--------------------------------------------------------------------------------- inc_timer bank timer_bank inc timer_int ;increments every isr cjne timer_int,#mscount,:it_done ; isr cycles for 1 msec clr timer_int dec timer_1m ;decrements every msec :it_done inc_timer_done call app_isr ;call application isr routines ; Update ra with buffered data ;--------------------------------------------------------------------------------- mov w,ra_dir_buf mov !ra,w ; Run uarts ;--------------------------------------------------------------------------------- hostVP bank hu_bank ;host uart receive ;receive only when enabled jnb hu_rx_enable,:hu_rx_done :receive sb pinDQ ; get current rx bit clc snb pinDQ stc test hu_rx_count ; currently receiving byte? sz jmp :hur1 ; if so, jump ahead mov w,#9 ; in case start, ready 9 bits sc ; skip ahead if not start bit mov hu_rx_count,w ; it is, so renew bit count mov w,#hostStDElay mov hu_rx_divide,w :hur1 decsz hu_rx_divide ; middle of next bit? jmp :hu_rx_done dec hu_rx_count ; last bit? sz ; if not rr hu_rx_byte ; then save bit jnz :hur2 ; and exit setb hu_rx_flag :hur2 mov w,#hostDivide mov hu_rx_divide,w :hu_rx_done ;host uart transmit ;transmit only when enabled jnb hu_tx_enable,:hu_tx_done :transmit decsz hu_tx_divide ; only execute the transmit routine jmp :hu_tx_done mov w,#hostDivide mov hu_tx_divide,w test hu_tx_count ; are we sending? snz jmp :hu_tx_done clc ; yes, ready stop bit rr hu_tx_high ; and shift to next bit rr hu_tx_low dec hu_tx_count ; decrement bit counter snb hu_tx_low.6 ; output next bit clrb ra_dir_buf.hostDQ ; update term_port_buf state sb hu_tx_low.6 ; (pin change state occurs next interrupt) setb ra_dir_buf.hostDQ :hu_tx_done termVP bank tu_bank ;term uart receive jb tu_cts,:term_rxdone ;only receive if rx is not cts :receive sb pinRX ; get current rx bit clc snb pinRX stc test tu_rx_count ; currently receiving byte? sz jmp :term_rx1 ; ;if so, jump ahead mov w,--tu_bits ; in case start, ready bits sc ; skip ahead if not start bit mov tu_rx_count,w ; it is, so renew bit count call tu_StDelay mov tu_rx_divide,w :term_rx1 decsz tu_rx_divide ; middle of next bit? jmp :term_rxdone dec tu_rx_count ; last bit? jz :term_rx2 ; if not rr tu_rx_byte ; then save bit movb tu_rx_parity,C ; and save b0 jmp :term_rx3 ; and exit :term_rx2 movb C,tu_rx_parity ;get last saved b0 movb tu_rx_parity,tu_rx_byte.7 ;save possible parity bit sb tu_bits.1 rr tu_rx_byte ;adjust for 7 databits + no parity (tu_bits=9) sb tu_bits.1 rr tu_rx_byte snb tu_bits.0 rl tu_rx_byte ;adjust for 8 databits + parity (tu_bits=11) snb tu_7bits clrb tu_rx_byte.7 ;clear b7 for 7 databits mov w,tu_rx_byte ;save byte to allow receive another byte mov tu_char,w ; while processing this one setb tu_rx_flag ;mark byte received :term_rx3 call tu_divide mov tu_rx_divide,w :term_rxdone ;term uart transmit jb tu_rts,:term_txdone ;only transmit if tx is not rts :transmit decsz tu_tx_divide ; only execute the transmit routine jmp :term_txdone call tu_divide mov tu_tx_divide,w test tu_tx_count ; are we sending? snz jmp :term_txdone clc ; yes, ready stop bit rr tu_tx_high ; and shift to next bit rr tu_tx_low dec tu_tx_count ; decrement bit counter snb tu_tx_low.5 ; output next bit clrb ra_dir_buf.termTX ; update term_port_buf state sb tu_tx_low.5 ; (pin change state occurs next interrupt) setb ra_dir_buf.termTX :term_txdone ; Set Interrupt Rate ;--------------------------------------------------------------------------------- isr_end mov w,#(-int_period)&$FF ; refresh RTCC on return retiw ; return from the interrupt ;-------------- end of the Interrupt Service Routines ------------------------------------ ;RESET VECTOR Program execution begins here on power-up or after a reset ;--------------------------------------------------------------------------------- reset_entry ; Initialise all port configuration ;--------------------------------------------------------------------------------- M_WKED equ $0A M_WKEN equ $0B M_ST equ $0C M_LVL equ $0D M_PLP equ $0E M_TRIS equ $0F mov m,#M_WKED ; point mode to WKED mov !rb,#RB_wked mov m,#M_WKEN ; point mode to WKEN mov !rb,#RB_wken mov m,#M_ST ; point mode to ST mov !rc,#RC_st mov !rb,#RB_st mov m,#M_LVL ; point mode to LVL mov !rc,#RC_lvl mov !rb,#RB_lvl mov !ra,#RA_lvl mov m,#M_PLP ; point mode to PLP mov !rc,#RC_plp mov !rb,#RB_plp mov !ra,#RA_plp mov rc,#RC_latch ; init latches mov rb,#RB_latch mov ra,#RA_latch mov m,#M_TRIS ; point mode to TRIS mov !rc,#RC_tris mov !rb,#RB_tris mov !ra,#RA_tris ; Clear all Data RAM locations ;--------------------------------------------------------------------------------- mov fsr,#global_org :zero_global clr indf inc fsr cjne fsr,#$10,:zero_global :zero_ram clr indf inc fsr jz :zero_end setb fsr.4 jmp :zero_ram :zero_end ; Initialize registers ;--------------------------------------------------------------------------------- mov ra_dir_buf,#$FF bank hu_bank mov hu_state,#$C0 ;pin levels high bank tu_bank setb tu_tx_enable ;enable transmit setb tu_rx_enable ;enable receive mov tu_bits,#10 ;set correct bits for startup (8N1,1200) ; Setup option register. ;--------------------------------------------------------------------------------- RTCC_ON equ %10000000 ;Enables RTCC at address $01 (RTW hi) ;*WREG at address $01 (RTW lo) by default RTCC_ID equ %01000000 ;Disables RTCC edge interrupt (RTE_IE hi) ;*RTCC edge interrupt (RTE_IE lo) enabled by default RTCC_INC_EXT equ %00100000 ;Sets RTCC increment on RTCC pin transition (RTS hi) ;*RTCC increment on internal instruction (RTS lo) is defalut RTCC_FE equ %00010000 ;Sets RTCC to increment on falling edge (RTE_ES hi) ;*RTCC to increment on rising edge (RTE_ES lo) is default RTCC_PS_ON equ %00000000 ;Assigns prescaler to RTCC (PSA lo) RTCC_PS_OFF equ %00001000 ;Assigns prescaler to WDT (PSA hi) PS_000 equ %00000000 ;RTCC = 1:2, WDT = 1:1 PS_001 equ %00000001 ;RTCC = 1:4, WDT = 1:2 PS_010 equ %00000010 ;RTCC = 1:8, WDT = 1:4 PS_011 equ %00000011 ;RTCC = 1:16, WDT = 1:8 PS_100 equ %00000100 ;RTCC = 1:32, WDT = 1:16 PS_101 equ %00000101 ;RTCC = 1:64, WDT = 1:32 PS_110 equ %00000110 ;RTCC = 1:128, WDT = 1:64 PS_111 equ %00000111 ;RTCC = 1:256, WDT = 1:128 mov w,#RTCC_PS_OFF ;setup option register mov !option,w ; Mainloop ;--------------------------------------------------------------------------------- mainloop call host_input_task ;handle host data input call host_output_task ;handle host data output call host_command_task ;handle host command call @term_input_task ;handle keypad input call @term_output_task ;handle display output call app_main ;call application mainloop jmp mainloop ;put w into hu_tx_buf ;--------------------------------------------------------------------------------- _enqueue_hu_tx bank hu_bank snb hu_tx_full setb hu_tx_overrun snb hu_tx_full retp mov temp,w mov w,<>hu_head and w,#$0F mov fsr,w ;calculate buffer address mov w,#hu_tx_buf add fsr,w mov w,temp ;store received byte mov indf,w bank hu_bank add hu_num,#16 ;adjust byte count add hu_head,#16 clrb hu_head.7 ;wrap around head setb hu_tx_data ;mark holding data retp ;put w into hu_rx_buf ;--------------------------------------------------------------------------------- _enqueue_hu_rx bank hu_bank snb hu_rx_full setb hu_rx_overrun snb hu_rx_full retp mov temp,w mov w,hu_head and w,#$0F mov fsr,w ;calculate buffer address mov w,#hu_rx_buf add fsr,w mov w,temp ;store received byte mov indf,w bank hu_bank add hu_num,#1 ;adjust byte count add hu_head,#1 clrb hu_head.3 ;wrap around head setb hu_rx_data ;mark holding data retp ;get w from hu_tx_buf ;--------------------------------------------------------------------------------- _dequeue_hu_tx bank hu_bank sb hu_tx_data retp mov w,<>hu_tail ;get next byte from buffer and w,#$0F mov fsr,w mov w,#hu_tx_buf add fsr,w mov w,indf mov temp,w bank hu_bank sub hu_num,#16 ;adjust byte count mov w,<>hu_num and w,#$0F snz clrb hu_tx_data add hu_tail,#16 clrb hu_tail.7 ;wrap around tail mov w,temp retp ;get w from hu_rx_buf ;--------------------------------------------------------------------------------- _dequeue_hu_rx bank hu_bank sb hu_rx_data ;test if any byte in buffer retp ;if not then exit mov w,hu_tail ;get next byte from buffer and w,#$0F mov fsr,w mov w,#hu_rx_buf add fsr,w mov w,indf mov temp,w bank hu_bank sub hu_num,#1 ;adjust byte count mov w,hu_num and w,#$0F snz clrb hu_rx_data ;mark buffer empty add hu_tail,#1 clrb hu_tail.3 ;wrap around tail mov w,temp retp ;put w into tu_tx_buf ;--------------------------------------------------------------------------------- _enqueue_tu_tx bank tu_bank snb tu_tx_full setb tu_tx_overrun snb tu_tx_full retp mov temp,w mov w,<>tu_head and w,#$0F mov fsr,w ;calculate buffer address mov w,#tu_tx_buf add fsr,w mov w,temp ;store received byte mov indf,w bank tu_bank add tu_num,#16 ;adjust byte count add tu_head,#16 clrb tu_head.7 ;wrap around head setb tu_tx_data ;mark holding data retp ;put w into tu_rx_buf ;--------------------------------------------------------------------------------- _enqueue_tu_rx bank tu_bank snb tu_rx_full setb tu_rx_overrun snb tu_rx_full retp mov temp,w mov w,tu_head and w,#$0F mov fsr,w ;calculate buffer address mov w,#tu_rx_buf add fsr,w mov w,temp ;store received byte mov indf,w bank tu_bank add tu_num,#1 ;adjust byte count add tu_head,#1 clrb tu_head.3 ;wrap around head setb tu_rx_data ;mark holding data retp ;get w from tu_tx_buf ;--------------------------------------------------------------------------------- _dequeue_tu_tx bank tu_bank sb tu_tx_data retp mov w,<>tu_tail ;get next byte from buffer and w,#$0F mov fsr,w mov w,#tu_tx_buf add fsr,w mov w,indf mov temp,w bank tu_bank sub tu_num,#16 ;adjust byte count mov w,<>tu_num and w,#$0F snz clrb tu_tx_data add tu_tail,#16 clrb tu_tail.7 ;wrap around tail mov w,temp retp ;get w from tu_rx_buf ;--------------------------------------------------------------------------------- _dequeue_tu_rx bank tu_bank sb tu_rx_data ;test if any byte in buffer retp ;if not then exit mov w,tu_tail ;get next byte from buffer and w,#$0F mov fsr,w mov w,#tu_rx_buf add fsr,w mov w,indf mov temp,w bank tu_bank sub tu_num,#1 ;adjust byte count mov w,tu_num and w,#$0F snz clrb tu_rx_data ;mark buffer empty add tu_tail,#1 clrb tu_tail.3 ;wrap around tail mov w,temp retp ; host input task ;--------------------------------------------------------------------------------- _host_input_task bank hu_bank sb hu_rx_enable ;may we receive? retp ;no sb hu_rx_flag ;byte received? retp ;no mov w,hu_rx_byte clrb hu_rx_flag jmp enqueue_hu_rx ;store byte in buffer ; host output task ;--------------------------------------------------------------------------------- _host_output_task bank hu_bank sb hu_tx_enable ;may we transmit? retp ;no sb hu_tx_data ;byte to transmit? retp ;no test hu_tx_count ;transmitter ready? sz retp ;no call dequeue_hu_tx ;get byte to transmit not w ;ready bits (inverse logic) mov hu_tx_high,w ;store data byte setb hu_tx_low.7 ;set up start bit mov w,#10 ;1 start + 8 data + 1 stop bit mov hu_tx_count,w ;VP starts transmitting retp ;-------------- codepage 0 end ----------------------------------------------------------- ;***************************************************************************************** org CODEPAGE_1 ;***************************************************************************************** jmp $ ;generates error if code above crosses page boundary term_input_task jmp _term_input_task ;receives term bytes into tu_rx_buf term_output_task jmp _term_output_task ;transmit term bytes from tu_tx_buf ; set parity and stopbits for byte in tu_tx_high (just about to transmit) ;--------------------------------------------------------------------------------- tu_set_parity snb tu_7bits ;8 databits? clrb tu_tx_high.7 ;no, ready stop bit mov w,tu_tx_high call even_parity :odd jnb tu_parity_odd,:even movb C,/temp.0 jmp :parity :even jnb tu_parity_even,:exit movb C,temp.0 :parity sb tu_7bits ;7 databits? retp ;no movb tu_tx_high.7,C ;move parity into b7 :exit clc ;ready stop bit retp ; calculate even parity for w ; result in temp.0 ;--------------------------------------------------------------------------------- even_parity mov temp,w ;calculation code by John Payson, as found on sxlist.com ;This routine will leave the parity of temp in temp.0 ;while blenderizing most of the rest of temp mov w,<>temp ; temp = abcdefgh xor temp,w mov w,>>temp xor temp,w ; at this point, the parity for half the bits ; (a, b, e, and f) is in bit 2 of temp, and the ; parity for the other half (bits c, d, g, and h) ; is in bit 0 of temp. snb temp.2 ; if the parity of (a,b,e,f) is 0, ; then the parity of (a,b,c,d,e,f,g,h) ; is equal to the parity of (c,d,g,h)... ; which is already in bit 0, so skip ahead. inc temp ; otherwise, the parity of (a,b,e,f) is 1, ; so the parity of (a,b,c,d,e,f,g,h) is ; NOT equal to the parity of (c,d,g,h). ; invert bit 0. ; at this point, bit 0 contains the parity of ; (a,b,c,d,e,f,g,h). retp ; term output handshake off (inform remote deivce to stop transmitting) ; either RTS (on TX pin) or XON/XOFF ;--------------------------------------------------------------------------------- tu_hs_off sb tu_rx_enable retp ;hs already off mov w,tu_config and w,#$14 ;test if tu_xonxoff or tu_rts set snz retp ;no handshake mov w,tu_num and w,#$0F ;extract bytes in tu_rx_buf jb tu_xonxoff,:tu_xoff ;xonxoff handshake xor w,#$05 ;disable receive if 5 bytes in tu_rx_buf sz retp clrb tu_rx_enable setb ra_dir_buf.termTX ;turn off handshake retp :tu_xoff xor w,#$02 ;disable receive if 2 byte in tu_rx_buf sz retp :tu_xoff1 test tu_tx_count jnz :tu_xoff1 ;wait for not busy clrb tu_rx_enable mov w,#XOFF ;send XOFF jmp tu_output_w ; term output handshake on (inform remote deivce to start transmitting) ; either RTS (on TX pin) or XON/XOFF ;--------------------------------------------------------------------------------- tu_hs_on snb tu_rx_enable retp ;hs already on mov w,tu_config and w,#$14 ;test if tu_xonxoff or tu_rts set snz retp ;no handshake mov w,tu_num and w,#$0F ;extract bytes in tu_rx_buf jb tu_xonxoff,:tu_xon ;xonxoff handshake xor w,#$01 ;enable receive if only 1 byte in tu_rx_buf sz retp setb tu_rx_enable clrb ra_dir_buf.termTX ;turn on handshake retp :tu_xon xor w,#$01 ;enable receive if only 1 byte in tu_rx_buf sz retp setb tu_rx_enable :tu_xon1 test tu_tx_count jnz :tu_xon1 ;wait for not busy mov w,#XON ;send XOFF jmp tu_output_w ; term input task ;--------------------------------------------------------------------------------- _term_input_task bank tu_bank snb tu_cts ;test if rx is used as cts retp ;yes, so do not receive sb tu_rx_flag ;byte received? retp ;no clrb tu_rx_flag ;clear receive flag (byte in tu_char) jnb tu_xonxoff,:tu_input ;jump ahead if no xon/xoff mov w,tu_char mov temp,w ;test for xon/xoff xor w,#XON ;test if byte received is XON snz setb tu_tx_enable ;yes, so enable tx snz retp ;and exit (XON is not stored) mov w,tu_char xor w,#XOFF ;test if byte received is XOFF snz clrb tu_tx_enable ;yes, so disable tx snz retp ;and exit (XOFF is not stored) :tu_input jb tu_parity_odd,:parity jb tu_parity_even,:parity jmp :exit :parity mov w,tu_char call even_parity snb tu_parity_odd not temp and temp,#$01 ;extract calculated parity bit addb temp,tu_rx_parity ;add received parity bit snb temp.0 ;temp=0 or temp=2 if parity bits match setb term_parity_error :exit mov w,tu_char call @enqueue_tu_rx ;put byte in queue jmp @tu_hs_off ;turn off handshake if required ; term output task ;--------------------------------------------------------------------------------- _term_output_task bank tu_bank snb tu_rts ;test if tx is used as rts retp ;tx is handshake so do not send sb tu_tx_data ;data to send? retp ;no test tu_tx_count ;transmitter busy? sz retp ;yes jb tu_xonxoff,tu_hs_soft jnb tu_cts,tu_output ;rx not used as handshake tu_hs_cts ;test if handshake input on jnb pinRX,tu_output ;if so then send retp tu_hs_soft sb tu_tx_enable ;send only if enabled retp tu_output call @dequeue_tu_tx tu_output_w not w ;ready bits (inverse logic) mov tu_tx_high,w ;store data byte setb tu_tx_low.7 ;set up start bit call tu_set_parity rr tu_tx_high ;shiftin parity bit or stop bit rr tu_tx_low mov w,tu_bits ;start + data + parity + stop mov tu_tx_count,w retp ; detect transition on pinWE ; actions when neg edge: ; - disable transmitter ; - clear buffers ; - initialize receive registers ; - enable receiver ; - move to state STATE_RECEIVE_COMMAND ; actions when pos edge: ; - disable receiver ; - initialize transmit registers ; - enable transmitter ; - move to state STATE_TRANSMIT_RESPONSE ;--------------------------------------------------------------------------------- checkPinWE bank hu_bank snb hu_tx_enable retp movb pinWE_past,pinWE_present movb pinWE_present,pinWE mov w,hu_state and w,#$C0 ;extract pinWE states xor w,#$40 ;L->H transition? jz :init_transmit ; yes xor w,#$C0 ;H->L transition sz retp ; no :init_receive clrb hu_tx_enable ;disable transmitter clr hu_head ;clear buffers parameters (tx and rx) clr hu_tail clr hu_num clrb hu_rx_data clrb hu_rx_overrun clrb hu_tx_data clrb hu_tx_overrun clr hu_rx_count ;initialize receive registers clrb hu_rx_flag setb hu_rx_enable ;enable receiver and hu_state,#$C0 ;keep pin states or hu_state,#STATE_RECEIVE_COMMAND ;move to state RECEIVE_COMMAND retp :init_transmit clrb hu_rx_enable ;disable receiver clr hu_tx_count ;initialize transmit registers setb hu_tx_enable ;enable transmitter and hu_state,#$C0 ;keep pin states or hu_state,#STATE_TRANSMIT_RESPONSE ;move to state TRANSMIT_RESPONSE retp ; Delay approx. 1 second ;-------------------------------------------------------------------- delay_1s00 mov w,#250 call delay_w delay_0s75 mov w,#250 call delay_w ; Delay approx. 0.5 second ;-------------------------------------------------------------------- delay_0s50 mov w,#250 call delay_w delay_0s25 mov w,#250 ; Delay w milliseconds ;-------------------------------------------------------------------- delay_w bank timer_bank mov timer_1m,w :wait test timer_1m jnz :wait retp ; Host command handler. ; This is the host command dispatcher entry. ; It is always called when command or parameters are received. ;--------------------------------------------------------------------------------- HOST_COMMANDS equ $08 ;number of host commands host_command_handler bank hu_bank snb cmd_done jmp clear_input ;command already finished csb hu_command,#HOST_COMMANDS jmp invalid_host_command mov w,hu_command add pc,w jmp _DV_GET_VERSION ;00 device get version jmp _TM_SET_CONFIG ;01 terminal set configuration jmp _TM_READ_DATA ;02 terminal read data jmp _TM_WRITE_DATA ;03 terminal write data jmp _IO_READ_PORTB ;04 i/o read port B jmp _IO_WRITE_PORTB_DIR ;05 i/o write port B direction jmp _IO_READ_PORTC ;06 i/o read port C jmp _IO_WRITE_PORTC_DIR ;07 i/o write port C direction ;new commands here ; Invalid commands must remove input data to prevent hu_rx_buf overrun ;--------------------------------------------------------------------------------- invalid_host_command setb cmd_invalid clear_input call @dequeue_hu_rx ;get rid of any input ; Mark command finished ;--------------------------------------------------------------------------------- host_command_exit bank hu_bank setb cmd_done retp ; Command $00 - Get device version. ; Parameters - none ; Description - This command returns 8 bytes to the host ;--------------------------------------------------------------------------------- _DV_GET_VERSION clrb cmd_parameter_missing sb hu_tx_enable ;may we transmit? retp ;no and hu_head,#$0F ;reset hu_tx_buf parameters and hu_tail,#$0F and hu_num,#$0F or hu_num,#$80 bank hu_buf_bank mov hu_tx_buf+$0,#'T' ;co-processor identification mov hu_tx_buf+$1,#'E' mov hu_tx_buf+$2,#'M' mov hu_tx_buf+$3,#'P' mov hu_tx_buf+$4,#'L' mov hu_tx_buf+$5,#'A' mov hu_tx_buf+$6,#'T' mov hu_tx_buf+$7,#'E' bank hu_bank setb hu_tx_data jmp host_command_exit ; Command $01 - terminal set configuration ; Parameters - config (default value = 0) ; b7 b6 b5 b4 b3 b2 b1 b0 ; | | | | | | +---+-- baud (0 to 3 -> see baud table) ; | | | | | +---------- 1 if TX used as RTS handshake ; | | | | +-------------- 1 if RX used as CTS handshake ; | | | +------------------ 1 if xon/xoff handshake ; | | +---------------------- 1 for 7 databits (default = 8 databits) ; | +-------------------------- 1 for even parity (default = no parity) ; +------------------------------ 1 for odd parity ; Description - set terminal baud, parity, handshake ;--------------------------------------------------------------------------------- _TM_SET_CONFIG jb hu_tx_enable,:output ;prevent deadlock if not received byte sb hu_rx_data retp clrb cmd_parameter_missing call @dequeue_hu_rx bank tu_bank mov tu_config,w mov tu_bits,#10 ;assume 8 databits and no parity snb tu_parity_even setb tu_bits.0 ;if parity set bits to 11 snb tu_parity_odd setb tu_bits.0 snb tu_7bits dec tu_bits ;if 7 databits decrement bits :output jmp host_command_exit ; Command $02 - read terminal data (one byte) ; Parameters - none ; Description - Return current terminal character, if any, else 0 ;--------------------------------------------------------------------------------- _TM_READ_DATA clrb cmd_parameter_missing sb hu_tx_enable retp clr w bank tu_bank jnb tu_rx_data,:tm_rd call @dequeue_tu_rx :tm_rd call @enqueue_hu_tx bank tu_bank call @tu_hs_on ;turn on handshake if required jmp host_command_exit ; Command $03 - write terminal data ; Parameters - bytes to write ; Description - write one or more characters to term ;--------------------------------------------------------------------------------- _TM_WRITE_DATA clrb cmd_parameter_missing jb hu_tx_enable,:output sb hu_rx_data retp call @dequeue_hu_rx call @enqueue_tu_tx retp :output jmp host_command_exit ; Command $04 - read port B ; Parameters - none ; Description - Return current port B input value to host ;--------------------------------------------------------------------------------- _IO_READ_PORTB clrb cmd_parameter_missing sb hu_tx_enable ;may we transmit retp ;no mov w,rb call @enqueue_hu_tx jmp host_command_exit ; Command $05 - write value to port B direction register ; Parameters - dirmask ; Description - Make port B pins low output (bit=0) or input (bit=1) ;--------------------------------------------------------------------------------- _IO_WRITE_PORTB_DIR jb hu_tx_enable,:output ;prevent deadlock if not received byte sb hu_rx_data retp clrb cmd_parameter_missing call @dequeue_hu_rx mov !rb,w :output jmp host_command_exit ; Command $06 - read port C ; Parameters - none ; Description - Return current port C input value to host ;--------------------------------------------------------------------------------- _IO_READ_PORTC clrb cmd_parameter_missing sb hu_tx_enable ;may we transmit retp ;no mov w,rc call @enqueue_hu_tx jmp host_command_exit ; Command $07 - write value to port C direction register ; Parameters - dirmask ; Description - Make port C pins low output (bit=0) or input (bit=1) ;--------------------------------------------------------------------------------- _IO_WRITE_PORTC_DIR jb hu_tx_enable,:output ;prevent deadlock if not received byte sb hu_rx_data retp clrb cmd_parameter_missing call @dequeue_hu_rx mov !rc,w :output jmp host_command_exit ;-------------- codepage 1 end ----------------------------------------------------------- ;***************************************************************************************** org CODEPAGE_2 ;***************************************************************************************** jmp $ ;generates error if code above crosses page boundary ;-------------- codepage 2 end ----------------------------------------------------------- ;***************************************************************************************** org CODEPAGE_3 ;***************************************************************************************** jmp $ ;generates error if code above crosses page boundary ;-------------- codepage 3 end ------------------------------------------------------
file: /Techref/scenix/lib/io/osi2/serial/elx1tmpl.htm, 45KB, , updated: 2013/7/22 17:23, local time: 2024/12/22 14:20,
3.145.44.46:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://massmind.org/techref/scenix/lib/io/osi2/serial/elx1tmpl.htm"> SX RS232 Serial IO </A> |
Did you find what you needed? |
Welcome to massmind.org! |
Welcome to massmind.org! |
.