;====================================================================== ; NMRA DATA TO TRACK - also, initially deals with all incoming RS232 ; ;====================================================================== ; TESTING INSTRUCTIONS ; ; can be tested with liberator's mic input: ; 1k1, 110k resistor divider from track gives 1/100 track ; voltage to mic input ; then ; sox -r 96000 -u -b -t ossdsp /dev/dsp t.dat ; perl -pe '$_= m/\-/ ? "_" : "~"' u ; in an xterm showing font "tiny" and then resized to eg 295x54 ; less u ; ;====================================================================== clock equ mclock ; this part runs really only on master include common.inc udata_acs nmractrl res 1 ; state relevant to NMRA control transmitbit equ 7 ; bit 7: 0/1 bit currently being transmitted nextaction equ 6 ; bit 6: change polarity on next interrupt y/n ; nmractrl is a bitmask, and only the bits above are used fromserial res 1 ; from-serial buffer location (in buffer bank) totrack equ FSR2L ; to-track buffer location (in buffer bank) totrackbit res 1 ; bit location of pointer within byte ; ; buffers are each 16 bytes (this is hardwired) ; and there are four of them starting at 0x500, 0x510, 0x520, 0x530. ; plus a copy of the watchdog `stop everything' command at 0x540. ; ; fromserial and totrack are pointers into the buffer page ; ; fromserial points to the first empty byte, where we will put new ; data provided by the host; this means that (fromserial & 0xf0) is ; the first buffer which fails to contain a complete nmra message. ; fromserial is updated only by the (low priority) serial receive ; interrupt handler. Furthermore, it always maintains a correct ; and valid value for use by the high-priority nmra readout ISR. ; ; totrack points to the first remaining full byte, which is currently ; being transmitted; if nothing is currently being transmitted ; because there is no nmra data at all then totrack points to the ; start of the same buffer as fromserial ; ; We maintain the following properties, notionally: ; ; totrack <= fromserial < totrack ; ; \ \ ; \ `- equal would mean overrun ; \ ; `- equal if we have nothing but ; idle to trasmit ; bufferpage equ 5 buffer_section udata bufferpage << 8 buffer0 res 16 buffer1 res 16 buffer2 res 16 buffer3 res 16 bufferw res 16 code ;**************************************************************************** macros ; macro to call subroutine to transmit over serial port for debugging ; takes 8-bit value, puts in W, invokes debug_serial_transmit ifndef SLOW_VERSION debug macro debugvalue endm endif ifdef SLOW_VERSION debug macro debugvalue mov_lw debugvalue call debug_serial_transmit endm endif debug_serial_transmit mov_wfa TXREG ; move contents of W (i.e. debugvalue) ; to TXREG for transmission waitfortsr bt_fa_if0 TXSTA,1 bra waitfortsr return ;**************************************************************************** serial_init @ ; serial set-up ; initial config - TXSTA register p181 bc_fa TXSTA,6 ; p181, set 8-bit mode bs_fa TXSTA,5 ; transmit enable bc_fa TXSTA,4 ; asynchronous mode bsc_txsta_brgh ; initial config - RCSTA register p182 bs_fa RCSTA,7 ; serial port enable (p182) bc_fa RCSTA,6 ; 8-bit reception bs_fa RCSTA,4 ; enable continuous receive ; set SPBRG to get correct baud rate according to table top right p186 ; (Tosc = 20MHz, desired baud rate = 9600) movlw_movwf_spbrg mov_lw ~((1< 16bit mode (testing) endif ifndef SLOW_VERSION bs_fa T0CON,6 ; p107 Timer0 -> 8bit mode (not-testing) endif bc_fa T0CON,5 ; timer0 use internal clock ifndef SLOW_VERSION mov_fw T0CON and_lw ~((1<1 then we are mid-bit, so copy transmitbit to ; nextaction in preparation for 2nd half of bit and then return debug 'm' ; write 'm' to serial port bc_fa nmractrl,nextaction bt_fa_if1 nmractrl,transmitbit bs_fa nmractrl,nextaction debug '2' ; write 'k' to serial port retfie_r decide_next_bit debug 'n' ; write 'n' to serial port ; check whether current to-track buffer = current from-serial buffer ; if yes, transmit 1s (set transmitbit=1, nextaction=1 and return) mov_fw fromserial xor_wfwa totrack and_lw 0x70 bra_nz read_from_buffer bs_fa nmractrl,transmitbit bs_fa nmractrl,nextaction debug '3' retfie_r read_from_buffer debug 'o' ; if currently on bit 7, want to skip to bit 6 ;*** wouldn't it be easier to start on bit 6 ? :-) -iwj bt_fa_if1 totrackbit,7 rr_fa totrackbit ; rotate mask right ; if not on bit 7 , ; set na=cb=bit value, advance bit (i.e. rotate transmitbit right), ; check if bit7, if so, advance byte, return debug 'p' mov_fw INDF2 and_wfwa totrackbit ; select bit to be transmitted bra_z zero_bit_to_track bra one_bit_to_track zero_bit_to_track debug '_' ; write 'q' to serial port debug '0' ; write 'q' to serial port debug '_' ; write 'q' to serial port bc_fa nmractrl,transmitbit bc_fa nmractrl,nextaction bra advance_bit one_bit_to_track debug '_' ; write 'q' to serial port debug '1' ; write 'r' to serial port debug '_' ; write 'q' to serial port bs_fa nmractrl,transmitbit bs_fa nmractrl,nextaction bra advance_bit advance_bit ; rotate transmitbit to next position debug 's' ; write 's' to serial port rr_fa totrackbit ; rotate mask right ;*** surely rrnc (`rotate right not through carry' I assume) ;*** will leave a copy of the top bit in the N flag ? Then you ;*** can use branch if negative. -iwj bt_fa_if1 totrackbit,7 rcall advance_pointer debug '5' ; write 's' to serial port retfie_r advance_pointer debug 't' ; write 't' to serial port ; currently on bit 7 of the byte, after having read rest of byte to ; track; check whether it is 1 or 0 ; if set, move to next buffer bt_fa_if0 INDF2,7 rcall advance_read_buffer ; if not set, move to next byte of samebuffer (increment totrack) ; (will be on bit 7 at this point anyway so no need to change totrackbit) bt_fa_if1 INDF2,7 inc_fa totrack return advance_read_buffer ; move pointer to next buffer ; clear low 4 bits of totrack and increment top 4 bits ; aaaabbbb -> bbbbaaaa -> bbbb(aaaa+1) -> 0000(aaaa+1) -> (aaaa+1)0000 bt_f_if1 totrack, 6 ; were we doing watchdog broadcasts ? bra advance_read_buffer_ifwatchdog mov_fw totrack add_lw 0x10 and_lw 0x30 mov_wf totrack debug '9' ; write 'v' to serial port inc_f acknmra bs_f PIE1, TXIE ; ensure we tell host to send us more bt_f_if0 acknmra, 2 return ; oops: panic morse_HM advance_read_buffer_ifwatchdog ; just loop round the buffer mov_lw 0x40 mov_wf totrack return ;**************************************************************************** panic_oerr panic morse_HO panic_ferr panic morse_HF ;**************************************************************************** include final.inc