@evanh said:
Jon,
Where is all your objects stored? I had a look in Obex for your bit-bashed SPI but couldn't find it.
As Terry pointed out, some of my early objects got folded into the Propeller Tool distribution. Please note that those files are on the oldish side, and I'm not as clever at PASM programming as you are. If you find issues (possible) or have suggestions for improvements (likely), please let me know. I wrote jm_spi.spin2 before I got a handle on smart pins. That file might still be useful, yet, again, I am open to skilled programmers improving it.
I wanted to capture the differences I have found between the W6100 and W6300. So far, the only issues I have found is the value difference of the SPI block selection. The parallel block select is the same between the chips, with reserved bits. Below are from the W6300 datasheet.
SPI Block Selection
Parallel Block Selection
I had the extra 0:2 reserved bits in my constants and that was the issue that caught me here. I might be able to combine these drivers into a single WS6x00 driver. Not sure of the best way to go about it.
Looks like the main difference between 6300 and 6100 is that with 6300 you can use a QPI interface and get similar or faster bandwidth as 6100 in 8-bit parallel mode?
@Rayman said:
Looks like the main difference between 6300 and 6100 is that with 6300 you can use a QPI interface and get similar or faster bandwidth as 6100 in 8-bit parallel mode?
Yes. Also the W6300 is clocked at 150Mhz vs 100Mhz of the W6100. (Though it is not documented correctly in the datasheet of the W6300) I believe the W6300 was put out to correct some of the performance problems of the W6100. Otherwise, I don't see anything wrong with the W6100.
Once I get Quad SPI going, I will make it drink from the UDP firehose and see how it does.
@evanh said:
Jon,
Where is all your objects stored? I had a look in Obex for your bit-bashed SPI but couldn't find it.
As Terry pointed out, some of my early objects got folded into the Propeller Tool distribution. Please note that those files are on the oldish side, and I'm not as clever at PASM programming as you are. If you find issues (possible) or have suggestions for improvements (likely), please let me know. I wrote jm_spi.spin2 before I got a handle on smart pins. That file might still be useful, yet, again, I am open to skilled programmers improving it.
Found it, thank you both for the direction. Bit-bashed has its simplicity and versatility.
I'm hacking up something and rough plan is to use the same API to make it easier integration for what Terry has already written.
@ke4pjw said:
Yes. Also the W6300 is clocked at 150Mhz vs 100Mhz of the W6100. (Though it is not documented correctly in the datasheet of the W6300) ...
I also noted an error on page 73 of v1.0.1 (4 Dec 2025) datasheet at https://docs.wiznet.io/Product/Chip/Ethernet/W6300 - where it draws a diagram of SPI mode 3 but with the labels "sampling" and "toggling" in wrong order.
Quick update. I did some optimization using the maximum segment size register and the web server. I was using a static size of 1K bytes for the amount of data to go into the packets being sent by the webserver. I noticed this was not optimal. It was a conservative number that would work in almost all real world cases, without causing fragmentation. I found that the Sn_MSSR register contains the maximum segment size after the 3way handshake is negotiated. This allows you to completely fill the packet with data you are sending. I validated that the MSS changed to 1452 (from 1460 with the normal MTU of 1500) if the client has an MTU of 1492, such as would happen with clients running PPPoE. Don't know if this is much better, but I don't think it hurts.
I will fold these changes into both W6100 and W6300 drivers. Still debating combining these to a single file. I probably should.
Now to work up the courage start messing with quadspi. Still a few days till I go back to work.
@rogloh said:
Well done. I take it that was with the streamer, not bit-banged?
Thanks! It is bit banged and conforms to Jon's driver nomenclature. I added readq and writeq methods. It works just like the regular read and write, but shifts whole nibbles each clock transition. I want to extend his driver to have methods to use the FIFO for larger byte transfers.
Not sure if these work in all use cases. Mode 0 with MSB first works.
pub writeQ(order, outval, bits) | x, di, do, clk, mode, tix, reps, ovset
'' Write bits from outval using defined SPI pins
'' -- order is LSBFIRST or MSBFIRST
longmove(@di, @sdipin, 5) ' copy configuration
org
rep #2, #4
drvl do
add do, #1 ' force to do pins to output
sub do,#4
shr do,#2 ' Set nibble pin group
testb order, #0 wc ' check for lsb mode
if_nc rev outval ' lsbfirst -- reverse the bits
mov ovset, bits 'Setup output value MSN first place number of bits into ovset
sub ovset, #4 'Remove a nibble of bits from the ovset
ROR outval, ovset 'Rotate right number of bits minus a nibble. This places the most signifigant nibble read for output
mov reps, bits ' Determine how many nibbles are in outval
shr reps, #2 ' Set the number of repitions on number of nibbles
testb mode, #0 wz ' check clock phase (z = phase)
rep @.endloop, reps ' shift out the nibbles reps times (Next nine instructions)
if_x0 altsn do, #outa
if_x0 setnib outval ' Set nibble (CPHS0)
waitx tix ' let sdo settle
drvnot clk ' toggle sclk
waitx tix
if_x1 altsn do, #outa
if_x1 setnib outval ' Set nibble (CPHS1)
waitx tix
drvnot clk
waitx tix
ROL outval, #4
.endloop
'debug(uhex(outval))
rep #2, #4 ' leave sdo low
drvl do
add do, #1 ' force to do pins to output
end
pub readQ(order, bits) : inval | x, di, do, clk, mode, tix, reps, tmpval
'' Read bits to inval using defined SPI pins
'' -- order is LSBFIRST or MSBFIRST
longmove(@di, @sdipin, 5) ' copy configuration
org
mov inval, #0 ' Initialize inval
mov di, do
rep #2, #4
fltl di
add di, #1 ' force to input (if shared with do)
sub di,#4
shr di,#2
mov reps, bits ' Determine how many nibbles are in outval
shr reps, #2 ' Set the number of repitions on number of nibbles
testb mode, #0 wz ' check clock phase (z = phase)
rep @.endloop, reps ' shift in the nibbles
waitx tix ' let sdi settle
shl inval, #4
if_x0 altgn di, #ina
if_x0 getnib tmpval ' if CPHS0 get nibble 1 from di pingroup
drvnot clk ' toggle sclk
waitx tix
waitx tix
drvnot clk
if_x1 altgn di, #ina
if_x1 getnib tmpval ' if CPHS1 get nibble 1 from di pingroup
waitx tix
add inval, tmpval
.endloop
testb order, #0 wc ' check for lsb mode
if_nc rev inval ' flip to lsbfirst
if_nc rol inval, bits
end
@evanh I updated it with my current code, but I still have some improvements to do, such as implementing the FIFO, ripping out all of the parallel interface code cruft from the 6100 code. I suppose I should start tracking that stuff in PBIs
It can, but since most of the people that received that last board were annoyed by the pin count of the parallel interface, and this chip claims 90Mbits/sec using SPI timings that we should be able to achieve, I only have the QSPI interface on the hardware. I don't have a way to test and none of the boards that Wiznet released have parallel either.
I implemented the FIFO with new SPI methods named WriteBytesQ and ReadBytesQ. You pass it the hub address you want data read or written from and the number of bytes. It reads or writes that data to the W6300 using QSPI. It appears that I am now bouncing off what the SDcard driver can do.
Update: Added to the Repo, but it isn't "cleaned up".
Comments
So far only changes in block selection. Web server works!
Congrats, Terry!
Jon,
Where is all your objects stored? I had a look in Obex for your bit-bashed SPI but couldn't find it.
The one I am using is in the Library folder that comes with PropTool.
Thanks Jon! Couldn't have got this far without your code. THANK YOU!
As Terry pointed out, some of my early objects got folded into the Propeller Tool distribution. Please note that those files are on the oldish side, and I'm not as clever at PASM programming as you are. If you find issues (possible) or have suggestions for improvements (likely), please let me know. I wrote jm_spi.spin2 before I got a handle on smart pins. That file might still be useful, yet, again, I am open to skilled programmers improving it.
You're welcome. At some point I need to study your driver so that I can connect my Propellers to my home network.
I wanted to capture the differences I have found between the W6100 and W6300. So far, the only issues I have found is the value difference of the SPI block selection. The parallel block select is the same between the chips, with reserved bits. Below are from the W6300 datasheet.


SPI Block Selection
Parallel Block Selection
I had the extra 0:2 reserved bits in my constants and that was the issue that caught me here. I might be able to combine these drivers into a single WS6x00 driver. Not sure of the best way to go about it.
Looks like the main difference between 6300 and 6100 is that with 6300 you can use a QPI interface and get similar or faster bandwidth as 6100 in 8-bit parallel mode?
Yes. Also the W6300 is clocked at 150Mhz vs 100Mhz of the W6100. (Though it is not documented correctly in the datasheet of the W6300) I believe the W6300 was put out to correct some of the performance problems of the W6100. Otherwise, I don't see anything wrong with the W6100.
Once I get Quad SPI going, I will make it drink from the UDP firehose and see how it does.
Found it, thank you both for the direction. Bit-bashed has its simplicity and versatility.
I'm hacking up something and rough plan is to use the same API to make it easier integration for what Terry has already written.
I also noted an error on page 73 of v1.0.1 (4 Dec 2025) datasheet at https://docs.wiznet.io/Product/Chip/Ethernet/W6300 - where it draws a diagram of SPI mode 3 but with the labels "sampling" and "toggling" in wrong order.
I added a repo link at the top of the page.
That's a lot of code! I've done very little ...
Quick update. I did some optimization using the maximum segment size register and the web server. I was using a static size of 1K bytes for the amount of data to go into the packets being sent by the webserver. I noticed this was not optimal. It was a conservative number that would work in almost all real world cases, without causing fragmentation. I found that the Sn_MSSR register contains the maximum segment size after the 3way handshake is negotiated. This allows you to completely fill the packet with data you are sending. I validated that the MSS changed to 1452 (from 1460 with the normal MTU of 1500) if the client has an MTU of 1492, such as would happen with clients running PPPoE. Don't know if this is much better, but I don't think it hurts.
I will fold these changes into both W6100 and W6300 drivers. Still debating combining these to a single file. I probably should.
Now to work up the courage start messing with quadspi. Still a few days till I go back to work.
I got quad spi working. I need to do some code cleanup and other optimizations before I release.
Well done. I take it that was with the streamer, not bit-banged?
Thanks! It is bit banged and conforms to Jon's driver nomenclature. I added readq and writeq methods. It works just like the regular read and write, but shifts whole nibbles each clock transition. I want to extend his driver to have methods to use the FIFO for larger byte transfers.
Not sure if these work in all use cases. Mode 0 with MSB first works.
pub writeQ(order, outval, bits) | x, di, do, clk, mode, tix, reps, ovset '' Write bits from outval using defined SPI pins '' -- order is LSBFIRST or MSBFIRST longmove(@di, @sdipin, 5) ' copy configuration org rep #2, #4 drvl do add do, #1 ' force to do pins to output sub do,#4 shr do,#2 ' Set nibble pin group testb order, #0 wc ' check for lsb mode if_nc rev outval ' lsbfirst -- reverse the bits mov ovset, bits 'Setup output value MSN first place number of bits into ovset sub ovset, #4 'Remove a nibble of bits from the ovset ROR outval, ovset 'Rotate right number of bits minus a nibble. This places the most signifigant nibble read for output mov reps, bits ' Determine how many nibbles are in outval shr reps, #2 ' Set the number of repitions on number of nibbles testb mode, #0 wz ' check clock phase (z = phase) rep @.endloop, reps ' shift out the nibbles reps times (Next nine instructions) if_x0 altsn do, #outa if_x0 setnib outval ' Set nibble (CPHS0) waitx tix ' let sdo settle drvnot clk ' toggle sclk waitx tix if_x1 altsn do, #outa if_x1 setnib outval ' Set nibble (CPHS1) waitx tix drvnot clk waitx tix ROL outval, #4 .endloop 'debug(uhex(outval)) rep #2, #4 ' leave sdo low drvl do add do, #1 ' force to do pins to output end pub readQ(order, bits) : inval | x, di, do, clk, mode, tix, reps, tmpval '' Read bits to inval using defined SPI pins '' -- order is LSBFIRST or MSBFIRST longmove(@di, @sdipin, 5) ' copy configuration org mov inval, #0 ' Initialize inval mov di, do rep #2, #4 fltl di add di, #1 ' force to input (if shared with do) sub di,#4 shr di,#2 mov reps, bits ' Determine how many nibbles are in outval shr reps, #2 ' Set the number of repitions on number of nibbles testb mode, #0 wz ' check clock phase (z = phase) rep @.endloop, reps ' shift in the nibbles waitx tix ' let sdi settle shl inval, #4 if_x0 altgn di, #ina if_x0 getnib tmpval ' if CPHS0 get nibble 1 from di pingroup drvnot clk ' toggle sclk waitx tix waitx tix drvnot clk if_x1 altgn di, #ina if_x1 getnib tmpval ' if CPHS1 get nibble 1 from di pingroup waitx tix add inval, tmpval .endloop testb order, #0 wc ' check for lsb mode if_nc rev inval ' flip to lsbfirst if_nc rol inval, bits endGood work.
Sorry I haven't put any time into the streamer code so far. I will get there eventually.
The first post link is all dated 20 Dec. I'm guessing you've got newer files local?
Correct, I haven't updated it in the repo yet. Hopefully I will this evening.
@evanh I updated it with my current code, but I still have some improvements to do, such as implementing the FIFO, ripping out all of the parallel interface code cruft from the 6100 code. I suppose I should start tracking that stuff in PBIs
Can’t the w6300 do parallel too?
It can, but since most of the people that received that last board were annoyed by the pin count of the parallel interface, and this chip claims 90Mbits/sec using SPI timings that we should be able to achieve, I only have the QSPI interface on the hardware. I don't have a way to test and none of the boards that Wiznet released have parallel either.
Got a new P1 board here with P2 style headers... Any reason this won't work with a P1?
It should work, obviously the software is written in Spin 2/PASM 2, but with a P1 driver, it would work.
I implemented the FIFO with new SPI methods named WriteBytesQ and ReadBytesQ. You pass it the hub address you want data read or written from and the number of bytes. It reads or writes that data to the W6300 using QSPI. It appears that I am now bouncing off what the SDcard driver can do.
Update: Added to the Repo, but it isn't "cleaned up".