'======================================================================= ' ' buffered smart pin serial object for P2 Eval board, buffering rx/tx in the Cog, supporting 2 full-duplex connrction ' '======================================================================= VAR long cog 'cog id of this instance ' '----------------------------------------------------------------------- 'stop cog if already running '----------------------------------------------------------------------- ' PUB stop if cog cogstop(cog-1) cog := 0 ' '----------------------------------------------------------------------- 'start COG with startparameter block address '----------------------------------------------------------------------- ' PUB start(startparameteraddress) 'the first long in the startparameter block contains the address of the later used stop 'Mailbox. So now I use long[long[]] to access the first long in the later used mailbox as Flag long[long[startparameteraddress]] := 0 'set flag (0) to know if the started cog has read its parameters cog := cognew(@cogserial_init,startparameteraddress) + 1 if cog 'if I was able to start the COG repeat until long[long[startparameteraddress]] == -1 'I wait until Flag states cog is done reading parameter and ready to roll (-1) RESULT := 1 'now start done ' '======================================================================= ' ' To use this use cogserial.spin - it will provide usual methods and include this driver. ' ' the description below is just if you want to use this directly from PASM and not SPIN ' '======================================================================= ' 'the PASM code runs in a COG and just needs 1 long for it's id and '8 longs in the HUB for communication. ' 'All code and buffers for 2 full duplex pairs is in the COG. 'The start parameter block ' '----------------------------------------------------------------------- ' ' When starting the driver you need to provide a memory address to read the parameters from. ' After COG start the memory is not needed anymore, so you can use your stack or some other ' Buffer you have. You will need 22 longs for all parameter. ' '----------------------------------------------------------------------- ' ' The first parameter in the start parameter block is the ADDRESS of your 8 long HUB mailbox ' You will use to communicate with the driver, once started. ' ' startparams[0] := @rx1_cmd 'hub address mailbox ' startparams[1] := rxpin1 'pin rx1 ' startparams[2] := 7 + ((CLKFREQ / rxbaudrate1) << 16) 'bitrate rx1 ' startparams[3] := rxmode1 'mode rx1 ' startparams[4] := rxlutstart1 'start lutbuffer rx1 ' startparams[5] := rxlutsize1 'size lutbuffer rx1 ' startparams[6] := txpin1 'pin tx1 ' startparams[7] := 7 + ((CLKFREQ / txbaudrate1) << 16) 'bitrate tx1 ' startparams[8] := txmode1 'mode tx1 ' startparams[9] := txlutstart1 'start lutbuffer tx1 ' startparams[10] := txlutsize1 'size lutbuffer tx1 ' startparams[11] := rxpin2 'pin rx2 ' startparams[12] := 7 + ((CLKFREQ / rxbaudrate2) << 16) 'bitrate rx2 ' startparams[13] := rxmode2 'mode rx2 ' startparams[14] := rxlutstart2 'start lutbuffer rx2 ' startparams[15] := rxlutsize2 'size lutbuffer rx2 ' startparams[16] := txpin2 'pin tx2 ' startparams[17] := 7 + ((CLKFREQ / txbaudrate2) << 16) 'bitrate tx2 ' startparams[18] := txmode2 'mode tx2 ' startparams[19] := txlutstart2 'start lutbuffer tx2 ' startparams[20] := txlutsize2 'size lutbuffer tx2 ' startparams[21] := tx_ct1wait 'number of sysclocks to wait between TX interrupts ' '----------------------------------------------------------------------- ' 'The mailbox interface: ' '----------------------------------------------------------------------- ' ' You need to provide 8 longs in HUB to talk to the driver. ' ' long rx1_cmd, rx1_param, tx1_cmd, tx1_param, rx2_cmd, rx2_param, tx2_cmd, tx2_param 'mailbox of this instance 8 longs ' ' and put the ADDRESS of those longs into the first parameter of your startparameter block ' '----------------------------------------------------------------------- ' ' each channel (rx1,tx1,rx2,tx2) has its own mailbox, one long for ' command/status and one long for the parameter ' '----------------------------------------------------------------------- ' ' the usual needed sequence is to ' check if mailbox ready (-1) else wait ' set parameter ' set command ' if you need to wait for a result check if mailbox ready (-1) else wait ' '----------------------------------------------------------------------- ' ' all mailboxes are independent from each other and you can run commands asyncron for each mailbox/channel ' '----------------------------------------------------------------------- ' 'rx1 mailbox ' rx1_cmd rx1_param 'mailbox for rx1 ' -1 --- 'mailbox ready last command finished ' -2 --- 'rxcheck, returns -1 if buffer empty or char in rx1_param ' -3 --- 'rxcount, returns number of bytes waiting in buffer in rx1_param ' -4 --- 'rxsize, returns size of buffer in bytes in rx1_param ' >0 ' size hubaddress 'rxblock, will read size bytes from buffer to hubaddress ' 'tx1 mailbox ' tx1_cmd tx1_param 'mailbox for tx1 ' -1 --- 'mailbox ready last command finished ' -2 --- 'txcheck, returns -1 if buffer full else bytes waiting in buffer in tx1_param ' -3 --- 'txcount, returns number of bytes waiting in buffer in tx1_param ' -4 --- 'txsize, returns size of buffer in bytes in tx1_param ' -5 hubaddress 'str, will write bytes from hubaddress to buffer until reaching a zero byte ' -6 value 'dec, will write value in tx1_param as decimal without leading zero's to buffer ' -(6+(digits<<8) value 'dec, will write last digits chars of value in tx1_param as decimal replacing leading zero's with space to buffer ' -7 value 'dec, will write 10 chars of value in tx1_param as decimal with leading zero's to buffer ' -(7+(digits<<8) value 'dec, will write last digits chars of value in tx1_param as decimal with leading zero's to buffer ' 'all dec routines will put a '-' as first char if value is negative ' -8 value 'hex, will write value in tx1_param as hex without leading zero's to buffer ' -(8+(digits<<8) value 'hex, will write last digits chars of value in tx1_param as hex replacing leading zero's with space to buffer ' -9 value 'hex, will write 8 chars of value in tx1_param as hex with leading zero's to buffer ' -(9+(digits<<8) value 'hex, will write last digits chars of value in tx1_param as hex with leading zero's to buffer ' >0 ' size hubaddress 'txblock, will write size bytes from hubaddress to buffer ' 'rx2 mailbox ' rx2_cmd rx2_param 'mailbox for rx2 ' -1 --- 'mailbox ready last command finished ' -2 --- 'rxcheck, returns -1 if buffer empty or char in rx2_param ' -3 --- 'rxcount, returns number of bytes waiting in buffer in rx2_param ' -4 --- 'rxsize, returns size of buffer in bytes in rx2_param ' >0 ' size hubaddress 'rxblock, will read size bytes from buffer to hubaddress ' 'tx2 mailbox ' tx2_cmd tx2_param 'mailbox for tx2 ' -1 --- 'mailbox ready last command finished ' -2 --- 'txcheck, returns -1 if buffer full else bytes waiting in buffer in tx2_param ' -3 --- 'txcount, returns number of bytes waiting in buffer in tx2_param ' -4 --- 'txsize, returns size of buffer in bytes in tx2_param ' -5 hubaddress 'str, will write bytes from hubaddress to buffer until reaching a zero byte ' -6 value 'dec, will write value in tx2_param as decimal without leading zero's to buffer ' -(6+(digits<<8) value 'dec, will write last digits chars of value in tx2_param as decimal replacing leading zero's with space to buffer ' -7 value 'dec, will write 10 chars of value in tx2_param as decimal with leading zero's to buffer ' -(7+(digits<<8) value 'dec, will write last digits chars of value in tx2_param as decimal with leading zero's to buffer ' 'all dec routines will put a '-' as first char if value is negative ' -8 value 'hex, will write value in tx2_param as hex without leading zero's to buffer ' -(8+(digits<<8) value 'hex, will write last digits chars of value in tx2_param as hex replacing leading zero's with space to buffer ' -9 value 'hex, will write 8 chars of value in tx2_param as hex with leading zero's to buffer ' -(9+(digits<<8) value 'hex, will write last digits chars of value in tx2_param as hex with leading zero's to buffer ' >0 ' size hubaddress 'txblock, will write size bytes from hubaddress to buffer ' '======================================================================= ' ' Now the PASM code ' ' I am reusing most of the initialisation code space for later needed Variables. ' ' Just ignore the labels on the left until the command loop ' '======================================================================= ' DAT org 0 ' cogserial_init ' '----------------------------------------------------------------------- ' 'loading parameters and reusing init code space for variables ' '----------------------------------------------------------------------- rx1_mailbox_ptr rdlong rx1_mailbox_ptr,ptra++ 'pointer to mailbox in hub and rx1 mailbox hub address rx1_pin rdlong rx1_pin, ptra++ 'serial1 rxpin1 rx1_bitperiod rdlong rx1_bitperiod, ptra++ 'bitperiod := 7 + ((CLKFREQ / baudrate) << 16) rx1_mode rdlong rx1_mode, ptra++ 'configure rx1_pin for asynchronous receive, always input rx1_lut_buff rdlong rx1_lut_buff, ptra++ 'lut rx1 receive buffer address in lut rx1_lut_btop rdlong rx1_lut_btop, ptra++ 'lut rx1 receive buffer top address in lut (size for rx1) tx1_pin rdlong tx1_pin, ptra++ 'serial1 txpin tx1_bitperiod rdlong tx1_bitperiod, ptra++ 'bitperiod := 7 + ((CLKFREQ / baudrate) << 16) tx1_mode rdlong tx1_mode, ptra++ 'configure tx1_pin for asynchronous transmit, always output tx1_lut_buff rdlong tx1_lut_buff, ptra++ 'lut tx1 send buffer address in lut tx1_lut_btop rdlong tx1_lut_btop, ptra++ 'lut tx1 send buffer top address in lut (size for tx1) rx2_pin rdlong rx2_pin, ptra++ 'serial1 rx2pin rx2_bitperiod rdlong rx2_bitperiod, ptra++ 'bitperiod := 7 + ((CLKFREQ / baudrate) << 16) rx2_mode rdlong rx2_mode, ptra++ 'configure rx2_pin for asynchronous receive, always input rx2_lut_buff rdlong rx2_lut_buff, ptra++ 'lut rx2 receive buffer address in lut rx2_lut_btop rdlong rx2_lut_btop, ptra++ 'lut rx2 receive buffer top address in lut (size for rx2) tx2_pin rdlong tx2_pin, ptra++ 'serial1 tx2pin tx2_bitperiod rdlong tx2_bitperiod, ptra++ 'bitperiod := 7 + ((CLKFREQ / baudrate) << 16) tx2_mode rdlong tx2_mode, ptra++ 'configure tx2_pin for asynchronous transmit, always output tx2_lut_buff rdlong tx2_lut_buff, ptra++ 'lut tx2 send buffer address in lut tx2_lut_btop rdlong tx2_lut_btop, ptra++ 'lut tx2 send buffer top address in lut (size for tx2) tx_ct1wait rdlong tx_ct1wait, ptra++ 'sysclocks to wait between calls to tx interrupt '----------------------------------------------------------------------- ' ' adjust tail pointers to bytes ' '----------------------------------------------------------------------- rxlutvalue shl rx1_lut_btop, #2 rxbyteindex shl rx2_lut_btop, #2 tx_lutvalue shl tx1_lut_btop, #2 tx_lutbuf shl tx2_lut_btop, #2 '----------------------------------------------------------------------- ' ' calculate mailbox pointers for later use ' '----------------------------------------------------------------------- rx1_param_ptr mov rx1_param_ptr, rx1_mailbox_ptr 'rx1 param hub address rx1_head add rx1_param_ptr, #4 'rx1 head position tx1_mailbox_ptr mov tx1_mailbox_ptr,rx1_param_ptr 'tx1 mailbox hub address rx1_tail add tx1_mailbox_ptr,#4 'rx1 tail position tx1_param_ptr mov tx1_param_ptr, tx1_mailbox_ptr 'tx1 param hub address rx1_char add tx1_param_ptr, #4 'tmp char for rx1_isr rx2_mailbox_ptr mov rx2_mailbox_ptr,tx1_param_ptr 'rx2 mailbox hub address rx1_address add rx2_mailbox_ptr,#4 'tmp address for rx1_isr rx2_param_ptr mov rx2_param_ptr, rx2_mailbox_ptr 'rx2 param hub address tx1_head add rx2_param_ptr, #4 'tx1 head position tx2_mailbox_ptr mov tx2_mailbox_ptr,rx2_param_ptr 'tx2 mailbox hub address tx1_tail add tx2_mailbox_ptr,#4 'tx1 tail position tx2_param_ptr mov tx2_param_ptr, tx2_mailbox_ptr 'tx2 param hub address tx1_char add tx2_param_ptr, #4 'tmp char for tx1_send '----------------------------------------------------------------------- ' ' clear mailboxes ' '----------------------------------------------------------------------- tx1_address wrlong minusOne, tx2_param_ptr 'tmp address for tx1_send rx2_head wrlong minusOne, tx2_mailbox_ptr 'rx2 head position rx2_tail wrlong minusOne, rx2_param_ptr 'rx2 tail position rx2_char wrlong minusOne, rx2_mailbox_ptr 'tmp char for rx2_isr rx2_address wrlong minusOne, tx1_param_ptr 'tmp address for rx2_isr tx2_head wrlong minusOne, tx1_mailbox_ptr 'tx2 head position tx2_tail wrlong minusOne, rx1_param_ptr 'tx2 tail position '----------------------------------------------------------------------- ' ' init used smartpins ' '----------------------------------------------------------------------- tx2_address cmp rx1_pin, minusOne wz 'tmp address for tx2_send 'if rx1_pin == -1 txcmd if_z jmp #end_rx1_reset 'tmp cmd used for HEX and DEC out ' skip RX1 setting smart pin '----------------------------------------------------------------------- ' ' Reset rx1 clear buffer pointers enable pin and int1 ' '----------------------------------------------------------------------- decbuf setint1 #0 'decbuf(0) reuses the next 11 longs 'disable int1 dirl rx1_pin 'decbuf(1) 'disable receiver mov rx1_head, #0 'decbuf(2) 'reset serial buffer pointers mov rx1_tail, #0 'decbuf(3) mov rx1_char, #%110<<6 'decbuf(4) add rx1_char, rx1_pin 'decbuf(5) wrpin rx1_mode, rx1_pin 'decbuf(6) 'configure rx_pin for asynchronous receive, always input wxpin rx1_bitperiod, rx1_pin 'decbuf(7) setse1 rx1_char 'decbuf(8) 'set se1 to trigger on rx1_pin (rx1_pin high) mov ijmp1, #rx1_isr 'decbuf(9) 'set int1 jump vector to rx1 ISR setint1 #4 'decbuf(10) 'set int1 to trigger on se1 rx1param dirh rx1_pin 'tmp parameter for rx1 cmd 'enable receiver end_rx1_reset '----------------------------------------------------------------------- txcmdparam cmp tx1_pin, minusOne wz 'blockaddress used in HEX/DEC 'if tx1_pin == -1 rx_char if_z jmp #end_tx1_reset 'rx_char used in command loop ' skip setting TX1 smart pin '----------------------------------------------------------------------- ' ' Reset tx1 set tx1_mode and tx1_bitperiod, enable pin ' '----------------------------------------------------------------------- rxdonewritepar dirl tx1_pin 'tmp parameter for rx1 cmd 'disable transmitter tx1param mov tx1_head, #0 'tmp parameter for tx1 cmd 'reset serial buffer pointers rxdone mov tx1_tail, #0 rx2param wrpin tx1_mode, tx1_pin 'tmp parameter for rx2 cmd 'configure tx1_pin for asynchronous transmit, always output rxlutbtop wxpin tx1_bitperiod, tx1_pin 'tmp parameter for rx2 cmd tx2param dirh tx1_pin 'tmp parameter for tx2 cmd 'enable transmitter end_tx1_reset '----------------------------------------------------------------------- rx_address cmp rx2_pin, minusOne wz 'rx_address used in command loop 'if rx2_pin == -1 tx_char if_z jmp #end_rx2_reset 'tx_char used in command loop ' skip RX2 setting smart pin '----------------------------------------------------------------------- ' ' Reset rx2 clear buffer pointers enable pin and int2 ' '----------------------------------------------------------------------- txblock setint2 #0 'tmp parameter for tx2 cmd 'disable int2 tx_address dirl rx2_pin 'tx_address used in command loop 'disable receiver tx_ct1 mov rx2_head, #0 'tx_ct1 used in tx_isr 'reset serial buffer pointers txlutbuf mov rx2_tail, #0 'tx_ct1wait used in tx_isr txdec mov rx2_char, #%110<<6 'txdec used by HEX/DEC txnumptr add rx2_char, rx2_pin 'used as pointer for output of HX/DEC txcogptr wrpin rx2_mode, rx2_pin 'used as pointer for output of HX/DEC 'configure rx_pin for asynchronous receive, always input txloopctr wxpin rx2_bitperiod, rx2_pin tx2_char setse2 rx2_char 'set se1 to trigger on rx1_pin (rx1_pin high) txdonewritepar mov ijmp2, #rx2_isr 'set int2 jump vector to rx2 ISR txdone setint2 #5 'set int2 to trigger on se2 txlutbtop dirh rx2_pin 'enable receiver end_rx2_reset '----------------------------------------------------------------------- txhead cmp tx2_pin, minusOne wz 'if tx2_pin == -1 txtail if_z jmp #end_tx2_reset ' skip setting TX2 smart pin '----------------------------------------------------------------------- ' ' Reset tx2 set tx2_mode and tx2_bitperiod, enable pin ' '----------------------------------------------------------------------- rxhead dirl tx2_pin 'disable transmitter rxtail mov tx2_head, #0 'reset serial buffer pointers rxcmd mov tx2_tail, #0 rxcmdparam wrpin tx2_mode, tx2_pin 'configure tx2_pin for asynchronous transmit, always output rx1_byte_index wxpin tx2_bitperiod, tx2_pin rx2_byte_index dirh tx2_pin 'enable transmitter end_tx2_reset '----------------------------------------------------------------------- ' ' Enable int3 for TX ' '----------------------------------------------------------------------- rx1_lut_value mov ijmp3,#tx_isr 'set int3 vector - later sysclocks to wait for in tx_isr rx2_lut_value setint3 #1 'set int3 for ct-passed-ct1 event later decimal num to send txbyteindex getct tx_ct1 'set initial tx_ct1 target txlutvalue addct1 tx_ct1, tx_ct1wait '----------------------------------------------------------------------- ' ' this tells calling cog we got the parameters and are ready to roll ' '----------------------------------------------------------------------- tx_tail wrlong minusOne, rx1_mailbox_ptr 'tmp char for tx2_send 'write -1 into rx1_mailbox_ptr in the HUB, now cogstart finished '======================================================================= ' 'command loop ' '======================================================================= rx1_cmd_check cmp rx1_pin, minusOne wz if_z jmp #tx1_cmd_check cmp rx1cmd, minusOne wz 'old cmd finished? if_z rdlong rx1cmd, rx1_mailbox_ptr 'cmd from rx1 mailbox if_z rdlong rx1param, rx1_param_ptr 'param from rx1 mailbox cmp rx1cmd, minusOne wz if_nz call #rx1_do_cmd 'do it tx1_cmd_check cmp tx1_pin, minusOne wz if_z jmp #rx2_cmd_check cmp tx1cmd, minusOne wz 'old cmd finished? if_z rdlong tx1cmd, tx1_mailbox_ptr 'cmd from tx1 mailbox if_z rdlong tx1param, tx1_param_ptr 'param from tx1 mailbox cmp tx1cmd, minusOne wz if_nz call #tx1_do_cmd 'do it rx2_cmd_check cmp rx2_pin, minusOne wz if_z jmp #tx2_cmd_check cmp rx2cmd, minusOne wz 'old cmd finished? if_z rdlong rx2cmd, rx2_mailbox_ptr 'cmd from rx2 mailbox if_z rdlong rx2param, rx2_param_ptr 'param from rx2 mailbox cmp rx2cmd, minusOne wz if_nz call #rx2_do_cmd 'do it tx2_cmd_check cmp tx2_pin, minusOne wz if_z jmp #rx1_cmd_check cmp tx2cmd, minusOne wz 'old cmd finished? if_z rdlong tx2cmd, tx2_mailbox_ptr 'cmd from tx2 mailbox if_z rdlong tx2param, tx2_param_ptr 'param from tx2 mailbox cmp tx2cmd, minusOne wz if_nz call #tx2_do_cmd 'do it jmp #rx1_cmd_check '======================================================================= ' ' INT 1 - rx1 read interrupt writes byte in lut buffer, runs if pin receives a char ' '======================================================================= rx1_isr rdpin rx1_char, rx1_pin 'get received chr shr rx1_char, #32-8 'shift to lsb justify mov rx1_byte_index, rx1_head and rx1_byte_index, #%11 'now 0 to 3 mov rx1_address, rx1_head 'adjust to buffer start shr rx1_address, #2 add rx1_address, rx1_lut_buff 'by adding rx1_lut_buff xor rx1_byte_index,#3 'altsb rx1_byte_index, rx1_address 'setbyte 0, rx1_char, #0 rdlut rx1_lut_value, rx1_address altsb rx1_byte_index, #rx1_lut_value setbyte 0, rx1_char, #0 wrlut rx1_lut_value, rx1_address 'write byte to circular buffer in lut incmod rx1_head, rx1_lut_btop 'increment buffer head cmp rx1_head, rx1_tail wz 'hitting tail is bad if_z incmod rx1_tail, rx1_lut_btop 'increment tail - I am losing received chars at the end of the buffer because the buffer is full reti1 'exit '======================================================================= ' ' INT 2 - rx2 read interrupt writes byte as long in lut buffer, runs if pin receives a char ' '======================================================================= rx2_isr rdpin rx2_char, rx2_pin 'get received chr shr rx2_char, #32-8 'shift to lsb justify mov rx2_byte_index, rx2_head and rx2_byte_index, #%11 mov rx2_address, rx2_head 'adjust to buffer start shr rx2_address, #2 add rx2_address, rx2_lut_buff 'by adding rx1_lut_buff xor rx2_byte_index,#3 rdlut rx2_lut_value, rx2_address altsb rx2_byte_index, #rx2_lut_value setbyte 0, rx2_char, #0 ' cmp rx2_byte_index, #0 wz ' if_z setbyte rx2_lut_value, rx2_char, #3 ' cmp rx2_byte_index, #1 wz ' if_z setbyte rx2_lut_value, rx2_char, #2 ' cmp rx2_byte_index, #2 wz ' if_z setbyte rx2_lut_value, rx2_char, #1 ' cmp rx2_byte_index, #3 wz ' if_z setbyte rx2_lut_value, rx2_char, #0 wrlut rx2_lut_value, rx2_address 'write byte to circular buffer in lut incmod rx2_head, rx2_lut_btop 'increment buffer head cmp rx2_head, rx2_tail wz 'hitting tail is bad if_z incmod rx2_tail, rx2_lut_btop 'increment tail - I am losing received chars at the end of the buffer because the buffer is full reti2 'exit '======================================================================= ' ' INT 3 - tx write interrupt, reads bytes from longs in lut buffer , runs once every tx_ct1wait clocks ' '======================================================================= tx_isr cmp tx1_head, tx1_tail wz 'tx1 byte to send? if_z jmp #.tx2_send 'no wait for next time ' rdpin tx1_char, tx1_pin wc 'wait for pin ready? if_c jmp #.tx2_send 'no wait for next time ' mov tx_tail, tx1_tail 'adjust to buffer start mov tx_lutbuf, tx1_lut_buff 'by adding tx1_lut_buff call #.txgetlutchar incmod tx1_tail, tx1_lut_btop 'increment buffer tail wypin txx_char, tx1_pin 'send byte ' .tx2_send cmp tx2_head, tx2_tail wz 'tx2 byte to send? if_z jmp #.end_isr 'no wait for next time ' rdpin tx2_char, tx2_pin wc 'wait for pin ready? if_c jmp #.end_isr 'no wait for next time ' mov tx_tail, tx2_tail 'adjust to buffer start mov tx_lutbuf, tx2_lut_buff 'by adding tx2_lut_buff call #.txgetlutchar incmod tx2_tail, tx2_lut_btop 'increment buffer tail wypin txx_char, tx2_pin 'send byte .end_isr addct1 tx_ct1, tx_ct1wait 'update txct1 target reti3 'return to main program '----------------------------------------------------------------------- .txgetlutchar mov tx_byteindex, tx_tail and tx_byteindex, #%11 mov txx_address, tx_tail 'adjust to buffer start shr txx_address, #2 add txx_address, tx_lutbuf 'by adding txX_lut_buff 'rdlut txx_char, txx_address 'get byte from circular buffer in lut 'ret rdlut tx_lutvalue, txx_address 'get byte from circular buffer in lut cmp tx_byteindex, #0 wz if_z getbyte txx_char, tx_lutvalue, #3 cmp tx_byteindex, #1 wz if_z getbyte txx_char, tx_lutvalue, #2 cmp tx_byteindex, #2 wz if_z getbyte txx_char, tx_lutvalue, #1 cmp tx_byteindex, #3 wz if_z getbyte txx_char, tx_lutvalue, #0 ret '======================================================================= ' ' handle rx1 mailbox ' '======================================================================= rx1_do_cmd mov rxdonewritepar, #rx1_donewritepar mov rxdone, #rx1_done mov rxlutbtop, rx1_lut_btop mov rxhead, rx1_head mov rxtail, rx1_tail mov rxcmd, rx1cmd 'preset rxcmd neg rxcmd mov rxcmdparam, rxcmd shr rxcmdparam, #8 and rxcmd, #$FF cmps rx1cmd, #0 wcz '#rx1_block if_ge jmp #rx1blockread cmp rxcmd, #2 wz '#rx1_check if_nz jmp #rxdocmd 'common rx commands mov rx_char, minusOne '#rx1check cmp rx1_head, rx1_tail wz 'byte received? if_nz call #rx1_get_rx_char rx1_donewritepar wrlong rx_char, rx1_param_ptr 'write rx1 parameter back in HUB rx1_done mov rx1cmd, minusOne _ret_ wrlong rx1cmd, rx1_mailbox_ptr 'rx1 command finished '----------------------------------------------------------------------- rx1_get_rx_char mov rxbyteindex, rx1_tail and rxbyteindex, #%11 mov rx_address, rx1_tail 'adjust to buffer start shr rx_address, #2 add rx_address, rx1_lut_buff 'by adding rx1_lut_buff call #rxgetlutchar _ret_ incmod rx1_tail, rx1_lut_btop 'increment buffer tail '----------------------------------------------------------------------- rx1blockread cmp rx1cmd, #0 wz 'need more bytes? if_z jmp rxdone 'no - done cmp rx1_head, rx1_tail wz 'byte received? if_z ret 'no - try again don't block the rest call #rx1_get_rx_char wrbyte rx_char, rx1param 'write byte to Block add rx1param, #1 'adjust Block address _ret_ sub rx1cmd, #1 'adjust count - try again don't block the rest '----------------------------------------------------------------------- rxgetlutchar rdlut rxlutvalue, rx_address 'get byte from circular buffer in lut ' xor rxbyteindex, #3 ' altgb rxbyteindex, #rxlutvalue ' getbyte 0, rx_char, #0 cmp rxbyteindex, #0 wz if_z getbyte rx_char, rxlutvalue, #3 cmp rxbyteindex, #1 wz if_z getbyte rx_char, rxlutvalue, #2 cmp rxbyteindex, #2 wz if_z getbyte rx_char, rxlutvalue, #1 cmp rxbyteindex, #3 wz if_z getbyte rx_char, rxlutvalue, #0 ret '======================================================================= ' ' handle rx2 mailbox ' '======================================================================= rx2_do_cmd mov rxdonewritepar, #rx2_donewritepar mov rxdone, #rx2_done mov rxlutbtop, rx2_lut_btop mov rxhead, rx2_head mov rxtail, rx2_tail mov rxcmd, rx2cmd 'preset rxcmd neg rxcmd mov rxcmdparam, rxcmd shr rxcmdparam, #8 and rxcmd, #$FF cmps rx2cmd, #0 wcz '#rx2_blck if_ge jmp #rx2blockread cmp rxcmd, #2 wz '#rx2_check if_nz jmp #rxdocmd mov rx_char, minusOne '#rx2check cmp rx2_head, rx2_tail wz 'byte received? if_nz call #rx2_get_rx_char rx2_donewritepar wrlong rx_char, rx2_param_ptr 'rx2 parameter back in HUB rx2_done mov rx2cmd, minusOne _ret_ wrlong rx2cmd, rx2_mailbox_ptr 'rx2 command finished '----------------------------------------------------------------------- rx2_get_rx_char mov rxbyteindex, rx2_tail and rxbyteindex, #%11 mov rx_address, rx2_tail 'adjust to buffer start shr rx_address, #2 add rx_address, rx2_lut_buff 'by adding rx2_lut_buff call #rxgetlutchar _ret_ incmod rx2_tail, rx2_lut_btop 'increment buffer tail '----------------------------------------------------------------------- rx2blockread cmp rx2cmd, #0 wz 'need more bytes? if_z jmp rxdone 'no - done cmp rx2_head, rx2_tail wz 'byte received? if_z ret 'no - try again don't block the rest call #rx2_get_rx_char wrbyte rx_char, rx2param 'write byte to Block add rx2param, #1 'adjust Block address _ret_ sub rx2cmd, #1 'adjust count - try again don't block the rest '======================================================================= ' ' handle tx mailbox ' '======================================================================= tx1_do_cmd mov txdonewritepar, #tx1_donewritepar mov txblock, #tx1_block mov txdone, #tx1_done mov txdec, tx1param 'preset txdec mov txnumptr, #tx1_write_num_wait 'preset txnumptr mov txlutbtop, tx1_lut_btop mov txhead, tx1_head mov txtail, tx1_tail mov txcmd, tx1cmd 'preset txcmd jmp #txdocmd '----------------------------------------------------------------------- tx2_do_cmd mov txdonewritepar, #tx2_donewritepar mov txblock, #tx2_block mov txdone, #tx2_done mov txdec, tx2param 'preset txdec mov txnumptr, #tx2_write_num_wait 'preset txnumptr mov txlutbtop, tx2_lut_btop mov txhead, tx2_head mov txtail, tx2_tail mov txcmd, tx2cmd 'preset txcmd jmp #txdocmd '----------------------------------------------------------------------- tx1_donewritepar wrlong tx_char, tx1_param_ptr 'return tx1 result tx1_done mov tx1cmd, minusOne _ret_ wrlong tx1cmd, tx1_mailbox_ptr 'clear tx1_mailbox - tx1_cmd finished '----------------------------------------------------------------------- tx2_donewritepar wrlong tx_char, tx2_param_ptr 'return tx2 result tx2_done mov tx2cmd, minusOne _ret_ wrlong tx2cmd, tx2_mailbox_ptr 'clear tx2_mailbox - tx2_cmd finished '----------------------------------------------------------------------- tx1_block cmps tx1cmd, #0 wz wc 'more bytes? if_z jmp txdone 'no - clear tx1_mailbox - tx1block finished mov tx_address, tx1_head 'returns tx1_head+1 incmod tx_address, tx1_lut_btop 'in tx_address cmp tx_address, tx1_tail wz 'no - buffer full if_z ret 'no - try again don't block the rest mov tx_char, #0 rdbyte tx_char, tx1param 'get next char cmp tx1cmd, minusFive wz 'string output? if_nz sub tx1cmd, #1 'no - adjust count of bytes to send if_z cmp tx_char, #0 wz 'yes - more bytes? if_z jmp txdone 'no - clear tx1_mailbox - tx1_block (string) finished mov txhead, tx1_head mov txlutbuf, tx1_lut_buff call #txputlutchar incmod tx1_head, tx1_lut_btop 'increment buffer head _ret_ add tx1param, #1 'adjust Block address '----------------------------------------------------------------------- tx2_block cmps tx2cmd, #0 wz wc 'more bytes? if_z jmp txdone 'no - clear tx2_mailbox - tx2block finished mov tx_address, tx2_head 'returns tx2_head+1 incmod tx_address, tx2_lut_btop 'in tx_address cmp tx_address, tx2_tail wz 'no - buffer full if_z ret 'no - try again don't block the rest mov tx_char, #0 rdbyte tx_char, tx2param 'get next char cmp tx2cmd, minusFive wz 'string output? if_nz sub tx2cmd, #1 'no - adjust count of bytes to send if_z cmp tx_char, #0 wz 'yes - more bytes? if_z jmp txdone 'no - clear tx2_mailbox - tx2block (string) finished mov txhead, tx2_head mov txlutbuf, tx2_lut_buff call #txputlutchar incmod tx2_head, tx2_lut_btop 'increment buffer head _ret_ add tx2param, #1 'adjust Block address '----------------------------------------------------------------------- txputlutchar mov txbyteindex, txhead and txbyteindex, #%11 mov tx_address, txhead 'adjust to buffer start shr tx_address, #2 add tx_address, txlutbuf 'by adding txX_lut_buff 'wrlut tx_char, tx_address 'write byte to circular buffer in lut 'ret xor txbyteindex, #3 rdlut txlutvalue, tx_address altsb txbyteindex, #txlutvalue setbyte 0, tx_char, #0 _ret_ wrlut txlutvalue, tx_address 'write byte to circular buffer in lut '----------------------------------------------------------------------- tx1_write_num_wait 'writes ascii digit to tx1 buffer and waits if buffer full add tx_char, #48 'make ascii out of digit tx1_write_byte_wait 'writes byte to tx2 buffer and waits if buffer full mov tx_address, tx1_head 'returns tx2_head+1 incmod tx_address, tx1_lut_btop 'in tx_address cmp tx_address, tx1_tail wz 'hitting tail is bad if_z jmp #tx1_write_byte_wait 'buffer full - wait mov txhead, tx1_head mov txlutbuf, tx1_lut_buff call #txputlutchar _ret_ incmod tx1_head, tx1_lut_btop 'increment buffer head '----------------------------------------------------------------------- tx2_write_num_wait 'writes ascii digit to tx2 buffer and waits if buffer full add tx_char, #48 'make ascii out of digit tx2_write_byte_wait 'writes byte to tx2 buffer and waits if buffer full mov tx_address, tx2_head 'returns tx2_head+1 incmod tx_address, tx2_lut_btop 'in tx_address cmp tx_address, tx2_tail wz 'hitting tail is bad if_z jmp #tx2_write_byte_wait 'buffer full - wait mov txhead, tx2_head mov txlutbuf, tx2_lut_buff call #txputlutchar _ret_ incmod tx2_head, tx2_lut_btop 'increment buffer head '----------------------------------------------------------------------- 'tx_write_num_wait 'writes ascii digit to tx2 buffer and waits if buffer full ' add tx_char, #48 'make ascii out of digit '.tx_write_byte_wait 'writes byte to tx2 buffer and waits if buffer full ' mov tx_address, txhead 'returns tx2_head+1 ' incmod tx_address, txlutbtop 'in tx_address ' cmp tx_address, txtail wz 'hitting tail is bad ' if_z jmp #.tx_write_byte_wait 'buffer full - wait ' jmp #txputlutchar '======================================================================= ' 'used by both RX ports ' '======================================================================= rxdocmd cmp rxcmd, #3 wz 'get count of bytes in rx buffer if_z jmp #rxcount cmp rxcmd, #4 wz 'get size of rx buffer if_z mov rx_char, rxlutbtop if_z jmp rxdonewritepar 'returns size of receive buffer jmp rxdone 'clear rx_mailbox - done '----------------------------------------------------------------------- rxcount mov rx_char, rxhead 'returns count of bytes in receive buffer RX2 in rx_char cmp rxhead, rxtail wcz if_b add rx_char, rxlutbtop sub rx_char, rxtail jmp rxdonewritepar 'returns count of bytes in receive buffer RX2 in rx_char '======================================================================= ' 'used by both TX ports ' '======================================================================= txdocmd cmps txcmd, #0 wc wz '#txX_block if_ge jmp txblock neg txcmd mov txcmdparam, txcmd shr txcmdparam, #8 and txcmd, #$FF cmp txcmd, #2 wz 'get count of free bytes in tx buffer or -1 if full if_z jmp #txcheck cmp txcmd, #3 wz 'get count of free bytes in tx buffer if_z jmp #txcount cmp txcmd, #4 wz 'get size of tx buffer if_z mov tx_char, txlutbtop if_z jmp txdonewritepar cmp txcmd, #5 wz 'output str on tx1 if_z jmp txblock cmp txcmd, #6 wz 'output dec without leading zero's on tx if_z jmp #decout cmp txcmd, #7 wz 'output dec with leading zero's on tx if_z jmp #decout cmp txcmd, #8 wz 'output hex without leading zero's on tx if_z jmp #hexout cmp txcmd, #9 wz 'output he with leading zero's on tx if_z jmp #hexout jmp txdone 'clear tx_mailbox - done '----------------------------------------------------------------------- txcheck mov tx_char, minusOne 'returns -1 or count of bytes in transmit buffer for tx1 mov tx_address, txhead 'returns tx2_head+1 incmod tx_address, txlutbtop 'in tx_address cmp tx_address, txtail wz if_z jmp txdonewritepar 'return buffer full else return tx1_count txcount mov tx_char, txhead 'returns count of bytes free in transmit buffer for tx in tx_char cmp txhead, txtail wc wz 'if head0) if_nz mov txcmd, #7 'force ouput of zeroes not spaces after first digit cmp txloopctr, #1 wz if_z mov decbuf, #1 'set Flag also for last digit if_z mov txcmd, #7 'force ouput of zeroes not spaces for last digit cmp decbuf, #0 wz 'now check Flag if we need to output if_z jmp #.done 'no - done cmp txcmdparam, #0 wz 'if no size if_z jmp #.out 'put out char cmp txcmd, #6 wz 'is cmd 6? if_z jmp #.replaceZero cmp txcmd, #8 wz 'is cmd 8? if_z jmp #.replaceZero jmp #.out 'no - put out char .replaceZero cmp tx_char, #0 wz 'if zero replace by space if_z mov tx_char, #16 '48 - 32 ... space instead of 0 if_z neg tx_char 'now -16 .out call txnumptr 'send char (+48) .done sub txcogptr, #1 'next char djnz txloopctr, #digitoutloop 'next digit jmp txdone 'clear tx_mailbox '----------------------------------------------------------------------- minusOne long -1 minusFive long -5 ' rx1cmd long -1 tx1cmd long -1 rx2cmd long -1 tx2cmd long -1 ' txx_char res 1 txx_address res 1 tx_byteindex res 1 '----------------------------------------------------------------------- 'fit 0'471 477 479 487 '-----------------------------------------------------------------------