Carl Jacobs
01-10-2009, 05:48 AM
FullDuplexSerial has already been studied to death - why would anyone be interested in yet another variation?
Read On...
The object is in the OBEX at obex.parallax.com/objects/398/ (http://obex.parallax.com/objects/398/)
This variation uses the left-over memory in the COG to store the Transmit (Tx) and Receieve (Rx) buffers. There are just over 1300 bytes of spare space available, and the Rx and Tx buffers may be freely allocated (in multiples of 4 bytes) to use this available space. There are no power-of-two limitations, if you want 4 bytes for Tx and 1296 bytes for Rx then that is permitted.
The nett result of this is that the object only requires 6 longs of hub memory.
The buffers are fully automatic and accessed through 2 longs in hub memory, Rx1_Buf and Tx1_Buf. Their operation is as follows:
Transmitter:
If Tx1_Buf is in the range 0..255 then that byte is still waiting for space in the Tx buffer. Once space is available the byte is inserted and Tx1_Buf is set to -1, at which point it is free to be used again. This looks much simpler in code:
PUB tx(txbyte)
{ Wait for space in the Tx buffer }
repeat while tx1_buf => 0
{ Send a byte }
tx1_buf := txbyte
Receiver:
If Rx1_Buf equals -1 then the Rx buffer is empty. If Rx1_Buf is in the range 0..255 then a byte is available, it can be read out with Rx1_Buf being set it to -1 to indicate that you're done. The cog will automatically grab the next byte from the internal Rx buffer and place it into Rx1_Buf. This looks much simpler in code:
PUB rx : rxbyte
{ Wait for a byte in the Rx buffer }
repeat while (rxbyte := rx1_buf) < 0
{ Indicate that the byte has been read }
rx1_buf := -1
Both Tx1_Buf and Rx1_Buf are typically updated by the driver cog at 300-400 thousand times a second.
From the previous examples it becomes a simple matter to access the serial driver from assembly language as well as via pointers passed to sub objects.
I shall make no claim that this object uses simple assembly language or that it is a minimal variation on FullDuplexSerial! This code was written from the ground up. It is partially commented. It uses a completely different form of multi-tasking to FullDuplexSerial. It has particularly tricky operation around the management of the internal FIFO buffers. The biggest challenge was distributing the management of the FIFO buffers between the bit bashing operations.
This object was written for two main reasons:
1) To minimize the memory footprint required by the serial driver
2) To allow easy access from JDForth - and other assembly language COGs.
The driver has 2 limitations which will not be a problem for most users:
1) Only FullDuplexSerial mode 0 is supported.
2) Only baud rates up to 345600 are supported for a 80MHz clock - which is about the same as FullDuplexSerial.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Carl Jacobs
JDForth - Forth to Spin Compiler http://www.jacobsdesign.com.au/software/jdforth/jdforth.php
Includes: FAT16 support for SD cards. Bit-bash Serial at 2M baud. 32-bit floating point maths.·Fib(28) in 0.86 seconds. ~3x faster than spin, ~40% larger than spin.
Read On...
The object is in the OBEX at obex.parallax.com/objects/398/ (http://obex.parallax.com/objects/398/)
This variation uses the left-over memory in the COG to store the Transmit (Tx) and Receieve (Rx) buffers. There are just over 1300 bytes of spare space available, and the Rx and Tx buffers may be freely allocated (in multiples of 4 bytes) to use this available space. There are no power-of-two limitations, if you want 4 bytes for Tx and 1296 bytes for Rx then that is permitted.
The nett result of this is that the object only requires 6 longs of hub memory.
The buffers are fully automatic and accessed through 2 longs in hub memory, Rx1_Buf and Tx1_Buf. Their operation is as follows:
Transmitter:
If Tx1_Buf is in the range 0..255 then that byte is still waiting for space in the Tx buffer. Once space is available the byte is inserted and Tx1_Buf is set to -1, at which point it is free to be used again. This looks much simpler in code:
PUB tx(txbyte)
{ Wait for space in the Tx buffer }
repeat while tx1_buf => 0
{ Send a byte }
tx1_buf := txbyte
Receiver:
If Rx1_Buf equals -1 then the Rx buffer is empty. If Rx1_Buf is in the range 0..255 then a byte is available, it can be read out with Rx1_Buf being set it to -1 to indicate that you're done. The cog will automatically grab the next byte from the internal Rx buffer and place it into Rx1_Buf. This looks much simpler in code:
PUB rx : rxbyte
{ Wait for a byte in the Rx buffer }
repeat while (rxbyte := rx1_buf) < 0
{ Indicate that the byte has been read }
rx1_buf := -1
Both Tx1_Buf and Rx1_Buf are typically updated by the driver cog at 300-400 thousand times a second.
From the previous examples it becomes a simple matter to access the serial driver from assembly language as well as via pointers passed to sub objects.
I shall make no claim that this object uses simple assembly language or that it is a minimal variation on FullDuplexSerial! This code was written from the ground up. It is partially commented. It uses a completely different form of multi-tasking to FullDuplexSerial. It has particularly tricky operation around the management of the internal FIFO buffers. The biggest challenge was distributing the management of the FIFO buffers between the bit bashing operations.
This object was written for two main reasons:
1) To minimize the memory footprint required by the serial driver
2) To allow easy access from JDForth - and other assembly language COGs.
The driver has 2 limitations which will not be a problem for most users:
1) Only FullDuplexSerial mode 0 is supported.
2) Only baud rates up to 345600 are supported for a 80MHz clock - which is about the same as FullDuplexSerial.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Carl Jacobs
JDForth - Forth to Spin Compiler http://www.jacobsdesign.com.au/software/jdforth/jdforth.php
Includes: FAT16 support for SD cards. Bit-bash Serial at 2M baud. 32-bit floating point maths.·Fib(28) in 0.86 seconds. ~3x faster than spin, ~40% larger than spin.