CON ''******************************************** ''* Ringnet Driver v2.0 * ''* Author: Michael Sommer (MSrobots) * ''******************************************** {-----------------REVISION HISTORY----------------- v2.0 - 6/29/2019 first official release. } '======================================================================= ' ' This driver is used to dasy-chain multiple P2's in form of a ring. ' ' All chained P2's share a common HUB buffer, each Member can lock the ' buffer, do changes and release it again. ' Think of mailboxes between P2's. ' ' The dasy chain ring can have 1-2-4-8-16-32 bit for data and needs ' one control line. Transfer is done with the streamer from HUB to pins ' and back to HUB on the next P2. ' '======================================================================= ' VAR LONG ringnetAddress LONG ringnetSize LONG outPinClock LONG outPinData LONG outPinMode LONG outPinBitclocks LONG inPinClock LONG inPinData LONG inPinMode LONG inPinBitclocks LONG inPinlockNumber '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LONG lockId LONG cogId '----------------------------------------------------------------------- PUB Stop if cogId cogstop(cogId-1) Release '----------------------------------------------------------------------- PUB Start(ringBufferHubAddress, ringBufferSizeInLongs, outPin_clock, outPin_data, outPin_mode, outPin_bitclocks, inPin_clock, inPin_data, inPin_mode, inPin_bitclocks, lockToUse) Stop ringnetAddress := ringBufferHubAddress ringnetSize := ringBufferSizeInLongs outPinClock := outPin_clock outPinData := outPin_data outPinMode := outPin_mode outPinBitclocks := outPin_bitclocks inPinClock := inPin_clock inPinData := inPin_data inPinMode := inPin_mode inPinBitclocks := inPin_bitclocks inPinLockNumber := lockToUse '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lockId := lockToUse cogId := cognew(@ringnet_ptr, @ringnetAddress)+1 '----------------------------------------------------------------------- PUB Lock | locknumber1 locknumber1 := lockId ASM .try locktry locknumber1 wc 'Keep trying to capture LOCK until successful if_nc jmp #.try ENDASM RETURN '----------------------------------------------------------------------- PUB Release | locknumber2 locknumber2 := lockId ASM lockrel locknumber2 wc 'release lock ENDASM RETURN '----------------------------------------------------------------------- PUB Poke_With_a_Stick | AtnMask AtnMask := 1<<(cogId-1) ASM cogatn AtnMask ENDASM RETURN '----------------------------------------------------------------------- DAT '======================================================================= ' ' ringnet COG ' '======================================================================= org 0 ringnet_ptr rdlong ringnet_ptr, ptra++ 'HUB address of Buffer to receive ringnet_size rdlong ringnet_size, ptra++ 'size of Ring Buffer to send (in longs) txPin_clock rdlong txPin_clock, ptra++ 'Pin to use for clock txPin_data rdlong txPin_data, ptra++ 'Pin to use for data tx_mode rdlong tx_mode, ptra++ '0-5 for 1 to 32 bit databus tx_bitclocks rdlong tx_bitclocks, ptra++ 'Xfrq for streamer rxPin_clock rdlong rxPin_clock, ptra++ 'Pin to use for clock rxPin_data rdlong rxPin_data, ptra++ 'Xinit for streamer rx_mode rdlong rx_mode, ptra++ '0-5 for 1 to 32 bit databus rx_bitclocks rdlong rx_bitclocks, ptra++ 'Xfrq for streamer rx_lock rdlong rx_lock, ptra++ 'Lock to use for writing Buffer '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'set up transmitter '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - txRingnet_size wrpin ##$1_0000, txPin_clock 'clock pin enable pin-registers (in and out) tx_xinit outl txPin_clock 'clock pin low tx_tmp dirh txPin_clock 'clock pin output tx_out mov tx_out, txPin_data 'first data pin tx_lines mov tx_lines, #1 tx_xfrq shl tx_lines, tx_mode 'now count of data pins tx_loopcnt rep #5, tx_lines 'for each data pin wrap wrpin ##$1_0000, tx_out ' data pin enable pin-registers (in and out) outl tx_out ' data pin low dirh tx_out ' data pin output add tx_out, #1 ' next data pin mov tx_xfrq, ##$8000_0000 'set for max freq (1/1) cmps tx_bitclocks, #1 wcz 'if more then one clock per bit if_a qdiv tx_xfrq, tx_bitclocks 'divide freq by clocks per bit if_a getqx tx_xfrq mov wrap, ringnet_size 'ring buffer size in longs shr wrap, #4 'now 64 byte count mov txRingnet_size, ringnet_size 'ring buffer size in longs shl txRingnet_size, #5 'size now bits not longs shr txRingnet_size, tx_mode 'size now bits divided by number of data lines mov tx_xinit, txPin_data 'set base pin for streamer (needs to be aligned) shl tx_xinit, #1 cmp tx_mode, #5 wz 'if 32 bit if_z add tx_xinit, ##%0011_0000_1000_0000 'set mode if_z mov tx_mode, #0 'clear submode if_z jmp #tx_shift 'now shift and ready to go cmp tx_mode, #4 wz 'if 16 bit if_z add tx_xinit, ##%0010_0000_1000_0000 'set mode if_z mov tx_mode, #0 'clear submode if_z jmp #tx_shift 'now shift and ready to go add tx_xinit, ##%0001_0000_1000_0000 'set mode keeop submode tx_shift shl tx_xinit, #16 'now shift and ready to go add tx_xinit, txRingnet_size 'add loop count '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'set up receiver '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - rx_xfrq wrpin ##$1_0000, rxPin_clock 'clock pin enable pin-registers (in and out) rxPin_clock_EV dirl rxPin_clock 'clock pin input rx_xinit drvl rxPin_clock 'clock pin driven low rx_out mov rx_out, rxPin_data 'first data pin rx_lines mov rx_lines, #1 rx_waitx shl rx_lines, rx_mode 'now count of data pins rxRingnet_size rep #5, rx_lines 'for each data pin wrpin ##$1_0000, rx_out ' data pin enable pin-registers (in and out) dirl rx_out ' data pin input drvl rx_out ' data pin drive low add rx_out, #1 ' next data pin mov rx_xfrq, ##$8000_0000 'set for max freq (1/1) cmps rx_bitclocks, #1 wcz 'if more then one clock per bit if_a qdiv rx_xfrq, rx_bitclocks 'divide freq by clocks per bit if_a getqx rx_xfrq mov rxRingnet_size, ringnet_size 'ring buffer size in longs shl rxRingnet_size, #5 'size now bits not longs shr rxRingnet_size, rx_mode 'size now bits divided by number of data lines mov rx_xinit, rxPin_data 'set base pin for streamer (needs to be aligned) shl rx_xinit, #1 cmp rx_mode, #5 wz 'if 32 bit if_z add rx_xinit, ##%1111_0000_0000_0000 'set mode if_z mov rx_mode, #0 'clear submode if_z jmp #rx_shift 'now shift and ready to go cmp rx_mode, #4 wz 'if 16 bit if_z add rx_xinit, ##%1110_0000_0000_0000 'set mode if_z mov rx_mode, #0 'clear submode if_z jmp #rx_shift 'now shift and ready to go add rx_xinit, ##%1101_0000_0000_0000 'set mode keep submode rx_shift shl rx_xinit, #16 'now shift and ready to go add rx_xinit, rxRingnet_size 'add loop count mov rx_waitx, rx_bitclocks shr rx_waitx, #1 'waitx now half bitclocks to start reading in the center 0 for /1, 1 for /2 and /3, 2 for /4 and /5, ... mov rxPin_clock_EV, rxPin_clock add rxPin_clock_EV, ##%011_000000 'now event source for setse1 for pin change setse1 rxPin_clock_EV 'wait for clock pin toggle '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .try1 locktry rx_lock wc 'Keep trying to capture LOCK until successful if_nc jmp #.try1 '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'set up watchdog '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'watchdog_flag mov watchdog_flag, #0 'clear watchdog_flag 'watchdog_frq mov watchdog_frq, #500 'ceck every 500 clocks 'watchdog_ctl getct watchdog_ctl 'set initial watchdog_ctl target ' addct1 watchdog_ctl, watchdog_frq ' mov ijmp3, #watchdog_isr3 'set int3 vector to watchdog_isr3 ' setint3 #1 'set int3 for ct-passed-ct1 event '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cmp rx_lock, #0 wz 'poke COG wih Lock 0 TODO - replace by watchdog or COGATN if_z call #transmit '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ' loop forever '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - loop call #receive 'wait for receive call #transmit 'do transmit 'mov watchdog_flag, #0 'clear watchdog_flag jmp #loop 'forever '----------------------------------------------------------------------- transmit xstop 'stop streamer setxfrq tx_xfrq 'set transfer freq for transmit rdfast wrap, Ringnet_ptr 'set address and wrap outnot txPin_clock 'signal start transmission waitx #3 'compensation xcont tx_xinit, tx_mode 'start sending waitxfi 'wait for finish ret 'done '----------------------------------------------------------------------- receive xstop 'stop streamer setxfrq rx_xfrq 'set transfer freq for receive wrfast wrap, Ringnet_ptr 'set address and wrap waitse1 'wait for clock pin toggle waitx rx_waitx 'wait for bitclock compensation xcont rx_xinit, rx_mode 'start receiving waitxfi 'wait for finish lockrel rx_lock 'release lock waitx #500 'give other cogs a chance to get a lock and change the buffer .try2 locktry rx_lock wc 'Keep trying to capture LOCK until successful if_nc jmp #.try2 ret 'done '----------------------------------------------------------------------- 'watchdog_isr3 add watchdog_flag, #1 'adjust dead counter ' ' addct1 watchdog_ctl, watchdog_frq 'update watchdog_ctl target ' reti3 'return to main program '-----------------------------------------------------------------------