SPI Slave implemented on prop
Just curious if there is any prior art for implementing an SPI Slave on a prop
In my continuing efforts to come up with a framework of marrying a prop to another MCU, i've implemented a simple yet effective SPI Slave mechanism running on one cog.
The protocol is very simple:
NSS on
1st byte: command (read or wright data)
2nd byte: register address to read/write into (i have a 0xff longs of hub ram allocated as SPI accessible registers)
next bytes: data in longs (has to be a multiple of 4 bytes of course)
NSS off
Currently it only runs at laughable "under 1Mbps", but i plan to optimize the heck out of it, to make it be able to run faster
I'll share this code soon if anyone is interested to use it or help with optimizations
Cheers
In my continuing efforts to come up with a framework of marrying a prop to another MCU, i've implemented a simple yet effective SPI Slave mechanism running on one cog.
The protocol is very simple:
NSS on
1st byte: command (read or wright data)
2nd byte: register address to read/write into (i have a 0xff longs of hub ram allocated as SPI accessible registers)
next bytes: data in longs (has to be a multiple of 4 bytes of course)
NSS off
Currently it only runs at laughable "under 1Mbps", but i plan to optimize the heck out of it, to make it be able to run faster
I'll share this code soon if anyone is interested to use it or help with optimizations
Cheers

Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Searider
things could be unrolled further (resulting in huge mess) but i think the bottleneck will still be the wrlong/rdlong. I thought of implementing some kind of caching, but that would complicate things.
EDIT: updated the code with jump table mechanism (for cases if more commands are needed)
org 0 'Command jump table. Addresses of these pointers must be equal to numbers representing a command wrcmdptr LONG 0 rdcmdptr LONG 0 entry or dira, misomask 'init pointers mov wrcmdptr, #wrdata mov rdcmdptr, #rddata waitnsstrans0 waitpne nssmask, nssmask nextcmd ' shift in the command mov t1, #8 '8bits in byte mov data, #0 shr jmpcmd, #8 'prepare jmpcmd for later shifting in of jump pointer address :nextbit :waitclktrans0 ' test nssmask, ina wz ' if_nz jmp #waitnsstrans0 ' abort and wait for next nss falling edge test clkmask, ina wz if_nz jmp #:waitclktrans0 ' wait for clk = 0 transition test mosimask, ina wc rcl jmpcmd, #1 ' shift in the jump pointer address. The shifting order is LSb first waitpeq clkmask, clkmask ' wait for clk = 1 transition djnz t1, #:nextbit jmpcmd jmp 0 'template for conditional jumping, according to the command received '-------------------------------------------------------------------------------------------- wrdata 'shift in the register address mov t1, #8 '8bits in byte 'or outa, gmask 'test :nextbit :waitclktrans0 ' test nssmask, ina wz ' if_nz jmp #waitnsstrans0 ' abort and wait for next nss falling edge test clkmask, ina wz if_nz jmp #:waitclktrans0 ' wait for clk = 0 transition test mosimask, ina wc rcr addr, #1 ' shift in new bit. The shifting order is LSb first waitpeq clkmask, clkmask ' wait for clk = 1 transition djnz t1, #:nextbit shr addr, #24 'shift right the byte received to the bits 0-7 position wrnextdata ' now shift in the data to write mov t1, #32 '32bits in long :nextbit :waitclktrans0 test nssmask, ina wz if_nz jmp #waitnsstrans0 ' abort and wait for next nss falling edge test clkmask, ina wz if_nz jmp #:waitclktrans0 ' wait for clk = 0 transition test mosimask, ina wc rcr data, #1 waitpeq clkmask, clkmask ' wait for clk = 1 transition djnz t1, #:nextbit wrlong data, addr 'write to hub ram at pre-specified location 'mov tempreg, data 'test add addr, #4 'next long jmp #wrnextdata 'write the next register '------------------------------------------------------------------------------- rddata ' shift in the register address mov t1, #8 '8bits in byte 'or outa, amask 'test :nextbit :waitclktrans0 ' test nssmask, ina wz ' if_nz jmp #waitnsstrans0 ' abort and wait for next nss falling edge test clkmask, ina wz if_nz jmp #:waitclktrans0 ' wait for clk = 0 transition test mosimask, ina wc rcr addr, #1 ' shift in new bit. The shifting order is LSb first waitpeq clkmask, clkmask ' wait for clk = 1 transition djnz t1, #:nextbit shr addr, #24 'shift right the byte received to the bits 0-7 position rdnextdata rdlong data, addr 'read from hub ram at pre-specified location 'mov data, tempreg 'test ' now shift out the data mov t1, #32 '32bits in long :nextbit rcr data, #1 wc ' shift out new bit. The shifting order is LSb first muxc outa, misomask ' shift out next out bit :waitclktrans0 test nssmask, ina wz if_nz jmp #waitnsstrans0 ' abort and wait for next nss falling edge test clkmask, ina wz if_nz jmp #:waitclktrans0 ' wait for clk = 0 transition waitpeq clkmask, clkmask ' wait for clk = 1 transition djnz t1, #:nextbit add addr, #4 'next long jmp #rdnextdata 'read the next register rmask LONG 1<<15 amask LONG 1<<14 gmask LONG 1<<13 nssmask LONG 1<<4 clkmask LONG 1<<5 misomask LONG 1<<6 mosimask LONG 1<<7 ' ' ' Uninitialized data ' t1 res 1 t2 res 1 t3 res 1 addr res 1 data res 1Post Edited (pems) : 11/9/2008 2:35:07 AM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Searider
@ Pems : You seem to be on the right track. If it's a dedicated SPI peripheral and you want even faster throughput you could use multiple Cogs - One simply catches transitions and throws them into a ring buffer, another Cog can assemble the bytes / packets and executes them. That will get the clock rate up high.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Searider