' ' buffered smart pin serial object for P2 Eval board, buffering rx/tx in the Cog ' CON _txmode = %0000_0000_000_0000000000000_01_11110_0 'async tx mode, output enabled for smart output _rxmode = %0000_0000_000_0000000000000_00_11111_0 'async rx mode, input enabled for smart input VAR long cog 'cog id of this instance long rx1_cmd 'mailbox of this instance (4 longs) long rx1_param long tx1_cmd long tx1_param PUB stop if cog cogstop(cog) cog := 0 PUB start(rxpin, txpin, mode, baudrate) 'return startExt(rxpin, txpin, baudrate, baudrate) return startExt(rxpin, txpin, baudrate, baudrate, _rxmode, _txmode, 0, $100, $FF, $FF) 'PUB startExt(rxpin, txpin, rxbaudrate, txbaudrate, rxmode=_rxmode, txmode=_txmode, rxlutstart=0, txlutstart=$100, rxlutsize=$FF, txlutsize=$FF) | startparams[11] PUB startExt(rxpin, txpin, rxbaudrate, txbaudrate, rxmode, txmode, rxlutstart, txlutstart, rxlutsize, txlutsize) | startparams[11] stop startparams[0] := @rx1_cmd 'hub address mailbox startparams[1] := rxpin 'pin rx startparams[2] := 7 + ((CLKFREQ / rxbaudrate) << 16) 'bitrate rx startparams[3] := rxmode 'mode rx startparams[4] := rxlutstart 'start lutbuffer rx startparams[5] := rxlutsize 'size lutbuffer rx startparams[6] := txpin 'pin tx startparams[7] := 7 + ((CLKFREQ / txbaudrate) << 16) 'bitrate tx startparams[8] := txmode 'mode tx startparams[9] := txlutstart 'start lutbuffer tx startparams[10] := txlutsize 'size lutbuffer tx rx1_cmd := 0 'set flag to know if the started cog has read its parameters cog := cognew(@cogserial_init,@startparams[0]) + 1 if cog repeat until rx1_cmd == -1 'wait until cog is done reading parameter RESULT := 1 ' ' check if byte received (never waits) ' returns -1 if no byte, otherwise byte ' PUB rxcheck : rxbyte RETURN rx_read(0, -2) ' ' receive a byte (waits until done) ' returns received byte ' PUB rx : rxbyte rx_read(@rxbyte, 1) ' ' receive a block from serial to memory of given size in bytes (waits until done) ' PUB rx_read(hubaddress, size) rx_read_async(hubaddress, size) repeat until rx1_cmd == -1 RESULT := rx1_param ' ' receive a block from serial to memory of given size in bytes (does not wait for completion - you may need to check rx1_cmd if done or not later in your code) ' PUB rx_read_async(hubaddress, size) repeat until rx1_cmd == -1 rx1_param := hubaddress rx1_cmd := size ' ' returns size of receive buffer in bytes ' PUB rx_size RETURN rx_read(0, -4) ' ' returns number of bytes waiting in receive buffer ' PUB rx_count RETURN rx_read(0, -3) ' ' check if byte can be send (never waits) ' returns -1 if no space in buffer otherwise number of free bytes in send buffer ' PUB txcheck RETURN tx_write(0, -2) ' ' sends a byte (waits until done) ' PUB tx(val) tx_write(@val,1) ' ' sends a byte (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) ' PUB tx_async(val) tx_write_async(@val,1) ' ' sends a block from memory to serial of given size in bytes (waits until done) ' PUB tx_write(hubaddress, size) tx_write_async(hubaddress, size) repeat until tx1_cmd == -1 RESULT := tx1_param ' ' sends a block from memory to serial of given size in bytes (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) ' PUB tx_write_async(hubaddress, size) repeat until tx1_cmd == -1 tx1_param := hubaddress tx1_cmd := size ' ' returns size of send buffer in bytes ' PUB tx_size RETURN tx_write(0, -4) ' ' returns number of free bytes in send buffer ' PUB tx_count RETURN tx_write(0, -3) ' ' transmit a string (waits until done) ' PUB str(s) | c tx_write(s, -5) ' ' transmit a string (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) ' PUB str_async(s) | c tx_write_async(s, -5) ' ' transmit a long as decimal ' PUB dec(value) | i, x '' Print a decimal number result := 0 x := value == NEGX 'Check for max negative if value < 0 value := ||(value+x) 'If negative, make positive; adjust for max negative tx_async("-") 'and output sign i := 1_000_000_000 'Initialize divisor repeat 10 'Loop for 10 digits if value => i tx_async(value / i + "0" + x*(i == 1)) 'If non-zero digit, output digit; adjust for max negative value //= i 'and digit from value result~~ 'flag non-zero found elseif result or i == 1 tx_async("0") 'If zero digit (or only digit) output it i /= 10 'Update divisor ' ' transmit a long as hex ' PUB hex(val, digits) | shft, x shft := (digits - 1) << 2 repeat digits x := (val >> shft) & $F shft -= 4 if (x => 10) x := (x - 10) + "A" else x := x + "0" tx_async(x) DAT org 0 cogserial_init rdlong rx1_mailbox_ptr,ptra++ rdlong rx1_pin, ptra++ rdlong rx1_bitperiod, ptra++ rdlong rx1_mode, ptra++ rdlong rx1_lut_buff, ptra++ rdlong rx1_lut_btop, ptra++ rdlong tx1_pin, ptra++ rdlong tx1_bitperiod, ptra++ rdlong tx1_mode, ptra++ rdlong tx1_lut_buff, ptra++ rdlong tx1_lut_btop, ptra++ ' ' calculate mailbox pointers ' mov rx1_param_ptr, rx1_mailbox_ptr add rx1_param_ptr, #4 mov tx1_mailbox_ptr,rx1_param_ptr add tx1_mailbox_ptr,#4 mov tx1_param_ptr, tx1_mailbox_ptr add tx1_param_ptr, #4 ' ' clear mailbox ' wrlong minusOne, tx1_param_ptr wrlong minusOne, tx1_mailbox_ptr wrlong minusOne, rx1_param_ptr wrlong minusOne, rx1_mailbox_ptr ' this tells calling cog we got the parameters ' ' init used smartpins ' rx1_init cmp rx1_pin, minusOne wz if_nz call #rx1_reset tx1_init cmp tx1_pin, minusOne wz if_nz call #tx1_reset ' 'command loop ' rx1_cmd_check rdlong cmd, rx1_mailbox_ptr 'cmd from rx1 mailbox? cmp cmd, minusOne wz if_nz call #rx1_do_cmd 'do it tx1_cmd_check rdlong cmd, tx1_mailbox_ptr 'cmd from tx1 mailbox? cmp cmd, minusOne wz if_nz call #tx1_do_cmd 'do it call #tx1_count cmp tx_char, #0 wz 'bytes to send? if_z jmp #rx1_cmd_check 'no - loop mov tx_loopcount, tx_char 'else send quarter of the buffer, waiting for it - might need some tuning, a eights perhaps? shr tx_loopcount, #2 add tx_loopcount, #1 .tx1send rdpin tx1_char, tx1_pin wc 'wait for transmit done if_c jmp #.tx1send 'rx1_cmd_test call #tx1_send djnz tx_loopcount, #.tx1send jmp #rx1_cmd_check ' ' tx1 try to send, reads long in lut buffer ' tx1_send cmp tx1_head, tx1_tail wz 'byte to send? if_z ret 'no wait for next time rdpin tx1_char, tx1_pin wc 'wait for transmit done if_c ret mov tx1_address, tx1_tail 'adjust to buffer start add tx1_address, tx1_lut_buff 'by adding rx1_lut_buff rdlut tx1_char, tx1_address 'get byte from circular buffer in lut incmod tx1_tail, tx1_lut_btop 'increment buffer tail _ret_ wypin tx1_char, tx1_pin 'send byte ' ' rx1 read interrupt writes byte in lut buffer ' rx1_isr rdpin rx1_char, rx1_pin '2 get received chr shr rx1_char, #32-8 '2 shift to lsb justify mov rx1_address, rx1_head '2 adjust to buffer start add rx1_address, rx1_lut_buff '2 by adding rx1_lut_buff wrlut rx1_char, rx1_address '2 write byte to circular buffer in lut incmod rx1_head, rx1_lut_btop '2 ..increment buffer head call #tx1_send ' hitchhiking here every receive interrupt allows fo a send reti1 '2/4 ..exit ' ' Reset rx1 clear buffer pointers enable pin and int1 ' rx1_reset setint1 #0 'disable int1 dirl rx1_pin 'disable receiver mov rx1_head, #0 'reset serial buffer pointers mov rx1_tail, #0 mov rx1_char, #%110<<6 add rx1_char, rx1_pin wrpin rx1_mode, rx1_pin 'configure rx_pin for asynchronous receive, always input wxpin rx1_bitperiod, rx1_pin setse1 rx1_char 'set se1 to trigger on rx1_pin (rx1_pin high) mov ijmp1, #rx1_isr 'set int1 jump vector to rx1 ISR setint1 #4 'set int1 to trigger on se1 _ret_ dirh rx1_pin 'enable receiver ' ' handle rx1 mailbox ' rx1_do_cmd cmps cmd, #0 wcz '#rx1_blck if_ge jmp #.rx1block cmp cmd, minusTwo wz '#rx1_check if_z jmp #.rx1check cmp cmd, minusThree wz '#rx1_count if_z jmp #.rx1count cmp cmd, minusFour wz '#rx1_size if_z jmp #.rx1size jmp #.done .rx1block rdlong blockaddress, rx1_param_ptr 'cmd is current count .rx1BlockLoop cmp cmd, #0 wz if_z jmp #.done cmp rx1_head, rx1_tail wz 'byte received? if_z wrlong blockaddress, rx1_param_ptr 'no - save back current Block address if_z wrlong cmd, rx1_mailbox_ptr 'no - save back current count if_z ret 'noting there try again next round mov rx_address, rx1_tail 'adjust to buffer start add rx_address, rx1_lut_buff 'by adding rx1_lut_buff rdlut rx_char, rx_address 'get byte from circular buffer in lut incmod rx1_tail, rx1_lut_btop 'increment buffer tail wrbyte rx_char, blockaddress 'write byte to Block add blockaddress, #1 'adjust Block address sub cmd, #1 'adjust count jmp #.rx1BlockLoop 'and get next byte .rx1check mov rx_char, minusOne cmp rx1_head, rx1_tail wz 'byte received? if_z jmp #.donewritepar .rx1get cmp rx1_head, rx1_tail wz 'byte received? if_z jmp #.rx1get rdlut rx_char, rx1_tail 'get byte from circular buffer in lut incmod rx1_tail, rx1_lut_btop 'increment buffer tail jmp #.donewritepar .rx1count call #rx1_count jmp #.donewritepar .rx1size mov rx_char, rx1_lut_btop .donewritepar wrlong rx_char, rx1_param_ptr .done _ret_ wrlong minusOne, rx1_mailbox_ptr rx1_count mov rx_char, rx1_head 'returns count of bytes in receive buffer in rx_char cmp rx1_head, rx1_tail wcz if_b add rx_char, rx1_lut_btop _ret_ sub rx_char, rx1_tail ' ' Reset tx1 set tx1_mode and tx1_bitperiod, enable pin ' tx1_reset 'setint2 #0 'disable int2 dirl tx1_pin 'disable transmitter mov tx1_head, #0 'reset serial buffer pointers mov tx1_tail, #0 'mov tx1_char, #%110<<6 'add tx1_char, tx1_pin wrpin tx1_mode, tx1_pin 'configure tx1_pin for asynchronous transmit, always output wxpin tx1_bitperiod, tx1_pin 'setse2 tx1_char 'set se2 to trigger on tx1_pin (tx1_pin high) 'mov ijmp2, #tx1_isr 'set int2 jump vector to tx1 ISR 'setint2 #4 'set int2 to trigger on se2 _ret_ dirh tx1_pin 'enable transmitter ' ' handle tx1 mailbox ' tx1_do_cmd cmps cmd, #0 wcz '#tx1_block if_ge jmp #.tx1block cmp cmd, minusTwo wz '#tx1_check if_z jmp #.tx1check cmp cmd, minusThree wz '#tx1_count if_z jmp #.tx1count cmp cmd, minusFour wz '#tx1_size if_z jmp #.tx1size cmp cmd, minusFive wz '#tx1_str if_z jmp #.tx1block jmp #.done .tx1block rdlong blockaddress, tx1_param_ptr 'cmd is current count .tx1BlockLoop cmp cmd, #0 wz if_z jmp #.done mov tx_address, tx1_head incmod tx_address, tx1_lut_btop cmp tx_address, tx1_tail wz if_z wrlong blockaddress, tx1_param_ptr 'no - save back current Block address if_z wrlong cmd, tx1_mailbox_ptr 'no - save back current count if_z ret 'no space there try again next round mov tx_char, #0 rdbyte tx_char, blockaddress cmp cmd, minusFive wz if_nz sub cmd, #1 'adjust count if_z cmp tx_char, #0 wz if_z jmp #.done mov tx_address, tx1_head 'adjust to buffer start add tx_address, tx1_lut_buff 'by adding tx1_lut_buff wrlut tx_char, tx_address 'write byte to circular buffer in lut incmod tx1_head, tx1_lut_btop '..increment buffer head add blockaddress, #1 'adjust Block address jmp #.tx1BlockLoop 'and put next byte .tx1check mov tx_char, minusOne mov tx_address, tx1_head incmod tx_address, tx1_lut_btop cmp tx_address, tx1_tail wz if_z jmp #.donewritepar .tx1count call #tx1_count jmp #.donewritepar .tx1size mov tx_char, tx1_lut_btop .donewritepar wrlong tx_char, tx1_param_ptr .done _ret_ wrlong minusOne, tx1_mailbox_ptr tx1_count mov tx_char, tx1_head 'returns count of bytes in transmit buffer in tx_char cmp tx1_head, tx1_tail wcz if_b add tx_char, tx1_lut_btop _ret_ sub tx_char, tx1_tail ' ' data ' minusOne long -1 'usable ngative constants minusTwo long -2 minusThree long -3 minusFour long -4 minusFive long -5 ' rx1_mailbox_ptr res 1 rx1_param_ptr res 1 rx1_pin res 1 'serial1 rxpin rx1_bitperiod res 1 'bitperiod := 7 + ((CLKFREQ / baudrate) << 16) rx1_mode res 1 'configure rx1_pin for asynchronous receive, always input rx1_lut_buff res 1 'lut rx1 receive buffer address in lut rx1_lut_btop res 1 'lut rx1 receive buffer top address in lut (size for rx1) ' tx1_mailbox_ptr res 1 tx1_param_ptr res 1 tx1_pin res 1 'serial1 txpin tx1_bitperiod res 1 'bitperiod := 7 + ((CLKFREQ / baudrate) << 16) tx1_mode res 1 'configure tx1_pin for asynchronous transmit, always output tx1_lut_buff res 1 'lut tx1 send buffer address in lut tx1_lut_btop res 1 'lut tx1 send buffer top address in lut (size for tx1) ' rx1_head res 1 'serial1 rxhead address rx1_tail res 1 'serial1 rxtail address tx1_head res 1 'serial1 txhead address tx1_tail res 1 'serial1 txtail address ' blockaddress res 1 cmd res 1 rx_char res 1 rx_address res 1 tx_char res 1 tx_address res 1 tx_loopcount res 1 ' tx1_char res 1 'tmp char for tx1_send tx1_address res 1 'tmp address for tx1_send ' rx1_char res 1 'tmp char for rx1_isr rx1_address res 1 'tmp address for rx1_isr