@ersmith Hi Eric: I have attached a spin2 program which "simple smart pin serial object for P2 Eval board" I wish to setup smart pins for SPI to complete this code:
I wish to avoid P58, P59, P60 and P61.
In the code for "simple smart pin serial object for P2 Eval board" it uses:
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
Can I use similar code to setup smart pins for SPI for nRESET, RS, nCS, MOSI, SCLK, MISO? What smart pin mode configuration lines would I need?
Thanks,
Kevin.
I'm definitely not an expert on smart pins. I think there's a great deal of interest in SPI and smartpins, so I suggest you start a new thread to ask for help on that. A good starting place for SPI code is the board/P2ES_flashloader.spin2 file, written by @ozpropdev and @evanh , which uses smartpins to implement reading from SPI flash.
I would be willing to help with SPI smartpin code since I've implemented a couple versions already. The SPI_Smartpin code I posted would be a great starting point, although I'd have to check which version I posted (and make sure everything works properly.) I believe I have a copy of the OBEX code stashed somewhere, when I get some time I will look to see how easy or hard this would be. The most complicated part will probably be getting the timing tuned properly. I remember having a bear of a time getting things right when working on my copy of FSRW.
I'm hoping to get my P2D2 soon so I can update all the smartpin code I've currently accumulated. The smartpin modes have changed but that should be a simple replace of the config.
@cheezus Thank you for your reply. I am thrilled to receive such a generous offer. I am retired and my interest is purely a hobby. I am new to Propeller 2 and have no technical experience. My end goal is to mirror the layout of Adafruit ILI9341 & GFX Libraries and if possibly utilize https://impulseadventure.com/ system called GUI Slice. This is all to build a robot control unit utilizing the Propeller 2 ES Eval Board Rev B. Very much a long term plan, hence no hurry at all. My intent is to document my progress on this forum in a style helpful to newcomers as well as writing a comprehensive blog on my own website. I definitely prefer "C" Programming but will work through SPIN & PASM in order to make some progress with Propeller 2. Initially I hope to make minimal changes to Mark_T's object, document those changes, get it working and then hope other newcomers can use the approach on other objects. Perhaps some will say impossible, yet it may be interesting to try.
Many thanks,
Kevin.
"C:/FlexGUI/bin/fastspin" -2 -l -O1 -I "C:/FlexGUI/include" "C:/FlexGUI/kgsamples/ILI9341A/ILI9341-spi-p2.spin"
Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2019 Total Spectrum Software Inc.
Version 4.0.6 Compiled on: Dec 30 2019
ILI9341-spi-p2.spin
ILI9341-spi-p2.p2asm
Done.
Program size is 1184 bytes
Finished at Mon Jan 20 06:25:13 2020
@Mark_T Thank you for your original files (ex obex). Your comments would be welcome.
Many thanks,
Kevin.
I've taken a quick look and it might help to start with my SDSPI.spin2 instead. I think it's a little better documented and the XPT2046 driver is actually kind of an oddball. About the ???s
wxpin b, #_CLK ' set base period (*2) see SPI_Smartpin.spin2 see Page 66 ????
'' b is clks per 1/2 bit. Passed from spin method GetBitTime
PRI GetBitTime(max_clkfreq) : bt
bt :=((clkfreq / max_clkfreq) /2 )+1 ' SPI bit time
if bt < 2 ' make sure at least sysclock /2 ''REVB change to 4
bt := 2 '' REVB change to 4
NOTE: This is for REVA, since I don't have a REVB board yet I can't verify but I believe this needs to be sysclock /4. I could be wrong...
re: del_millis - I'd create a coglong "millis" and pass this value from spin at startup.
The CON section ;
'' smart pin modes
sp_stx = %01_11100_0 '+ (%1111 << 24) ' -1 Mode 28 sync serial transmit (A-data, B-clock)
' sp_srx = %00_11101_0 + (%0001 << 24) ' +1 Mode 29 sync serial receive (A-data, B-clock)
sp_clk = %01_00101_0 '+ sp_inv_pin _ transition output _ output enabled, regardless of DIR
'sp configs
stx_c = (%1 << 5) + (numBits - 1) ' 8 bit default
stx_c16 = (%1 << 5) + (16 - 1) ' 16-bit transfer
' srx_c = (%0 << 5) + (numBits - 1) ' rx not used
clks = numBits * 2
numBits = 8 ' 8 bit default
..
PRI getmask(clk, data) : t
t := clk - data
if ( || t ) <> t
t := ( || t ) + %0100
This is how I'd set the constants up (I think). You are only transmitting so safe to remove SRX entries. Also, removing the bpin from the config constant allows this to be computed at startup.
SDSPI.spin2 init and variables
CON
{{
SDSPI ASM for P2 v_0_1_0
by Cheezus Slice - Joe Heinz - 2019
cheezusslicedj@gmail.com
}}
spi_clk_max = 20_000_00 ' 20mhz safe, 26 seems to work though? 27 fail
spi_clk_inv = 1 ' 1 inverted, 0 non-inverted
{
VAR byte cog
}
DAT cog byte 0
PUB HOOK ' test compile
start_explicit( 3, 2, 1, 0 )
PUB Stop
if cog
cogstop(cog-1)
cog := 0
PUB GetCog
return cog
PUB release
PUB start_explicit( _DO, _CLK, _DI, _CS ) : card_type | domask, dimask
stop
long[@cmd] := "i" 'set flag to know if the started cog has read its parameters
long[@cmd][1] := _DO | (_CLK << 8) + (_DI << 16) + ( _CS << 24)' pins
long[@cmd][2] := getmask(_CLK, _DO) + (getmask(_CLK, _DI) << 4) ' clock masks
long[@cmd][2] += spi_clk_inv << 8 ' clock invert
long[@cmd][3] := GetBitTime(spi_clk_max) ' spi bit time
long[@cmd][4] := GetBitTime(400_000) '400k
cog := cognew(@_asm_start,@cmd) + 1
if cog
repeat until long[@cmd] <> "i" ' wait until cog is done reading parameter
card_type := long[@cmd][4] ' arg5 returns card type or returns with ptr to error from low level driver
PUB ReadBlock(n, b)
return DoCommand("r", n, b, 0)
PUB WriteBlock(n, b)
return DoCommand("w", n, b, 0)
PRI GetBitTime(max_clkfreq) : bt
bt :=((clkfreq / max_clkfreq) /2 )+1 ' SPI bit time
if bt < 2 ' make sure at least sysclock /2
bt := 2
PRI DoCommand(_cmd, _arg1, _arg2, _arg3)
repeat while cmd <> 0
arg1 := _arg1
arg2 := _arg2
arg3 := _arg3
cmd := _cmd
repeat until cmd <> _cmd
return err
PRI getmask(clk, data) : t
t := clk - data
if ( || t ) <> t
t := ( || t ) + %0100
DAT org
_asm_start mov ptr_to_mbox, ptra ' save mbox address for later
'' get parameters from spin
do_init mov ptra, ptr_to_mbox ' return ptra back to mbox
rdlong tmp, ptra++ ' command long 0
rdlong tmp, ptra++ ' pins long 1
getbyte pinDO, tmp, #0
getbyte pinCLK, tmp, #1
getbyte pinDI, tmp, #2
getbyte pinCS, tmp, #3
rdlong tmp, ptra++ 'mask long 2
getnib sp_doclk, tmp, #0
getnib sp_diclk, tmp, #1
shl sp_doclk, #24
shl sp_diclk, #24
rdlong sp_bt, ptra++ ' timing long 3
rdlong sp_init_bt, ptra ' 400k 4
rdlong delay1s, #$14 ' clkfreq from hub
'' setup pins
drvh pinCS
dirl pinCLK '' setup Clock pin
shr tmp, #8
cmp tmp, #1 wz
mov tmp, sp_clk
if_z add tmp, sp_inv_pin ' invert clock
wrpin tmp, pinCLK
wxpin sp_init_bt, pinCLK ' set base period (*2)
dirh pinCLK ' enable clk
dirl pinDI '' setup DI pin
mov tmp, sp_stx ' save mode, bpin might change
add tmp, sp_diclk ' setup bpin
wrpin tmp, pinDI ' sync tx
wxpin sp_stx_c, pinDI ' stop/start mode
dirh pinDI ' enable smartpin
wypin #$FF, pinDI ' prime shifter
dirl pinDO '' setup DO pin
mov tmp, sp_srx ' save mode, bpin might change
add tmp, sp_doclk ' setup bpin
wrpin tmp, pinDO ' sync rx
wxpin sp_stx_c, pinDO ' 8 bit, pre
dirh pinDO ' enable pin
'' card init
drvh pinCS ' set cs high
wypin sectorsize, pinCLK ' set init clocks
getct timeout ' setup 1s timeout
addct1 timeout, delay1s ' in case card does not respond
call #wait_clock ' wait for smartpins to finish
dirl pinCLK '' setup Clock pin
wxpin sp_bt, pinCLK ' set base period (*2)
dirh pinCLK ' enable clk
..
..
{=== Smart pin constants ===}
sp_clk long %01_00101_0
sp_stx long %01_11100_0
sp_srx long %00_11101_0
sp_stx_c long %1_00111
sp_srx_c long %0_00111
sp_inv_pin long %0000_001_000_000 << 8
byteclks long (2*8)
sectorsize long 512
{=== Pin Variables ===}
pinDO res 1 ' do
pinCLK res 1 ' clk
pinDI res 1 ' di
pinCS res 1 ' chip select
{===== Smartpin Clock Variables =====}'' smartpins stuffs
sp_doclk res 1
sp_diclk res 1
sp_bt res 1
sp_init_bt res 1
adrShift res 1 ' will be 0 for SDHC, 9 for MMC & SD
' loaded on init
{===== Command Mailbox =====}
ptr_to_mbox res 1
cmd_in res 1
arg1_in res 1
arg2_in res 1
arg3_in res 1
err_out res 1
{=== Timing Variables ===}
delay1s res 1 ' clkfreq = 1 s
timeout res 1
{=== Temp Variables ===}
tmp res 1 ' this may get used in all subroutines...don't use except in lowest
data_in res 1
data_out res 1
sd_cmd res 1
sd_parm res 1
FIT 496
You may also want to look at using the PTRA/PTRB for hub access. Hopefully this helps a bit. Sorry I don't have more time right now. I've been meaning to make a general SPI cog but waiting for REVB silicon so I can test properly
Comments
In the code for "simple smart pin serial object for P2 Eval board" it uses: Can I use similar code to setup smart pins for SPI for nRESET, RS, nCS, MOSI, SCLK, MISO? What smart pin mode configuration lines would I need?
Thanks,
Kevin.
Are you Mark Tillotson author of:
http://obex.parallax.com/object/723 ILI9341-test-bst-archive-131116-160819.zip ?
The same as:
https://forums.parallax.com/discussion/169846/smartpin-spi-bidirectional-sample-code
I am kg1 Kevin Gordon email address (see private message)
Could you please have a look at:
https://forums.parallax.com/discussion/comment/1456684/#Comment_1456684
P2 Touchscreen + Memory
cheezus 2018-09-30
Especially on 2019-11-22 open file P2Touch.zip see SmartSerial.spin and SPI_Smartpin.spin2
Could this work of Cheezus be used to upgrade the illi9341 driver for use on the Propeller 2 ES Eval Board Rev B?
Thanks,
Kevin.
I would be willing to help with SPI smartpin code since I've implemented a couple versions already. The SPI_Smartpin code I posted would be a great starting point, although I'd have to check which version I posted (and make sure everything works properly.) I believe I have a copy of the OBEX code stashed somewhere, when I get some time I will look to see how easy or hard this would be. The most complicated part will probably be getting the timing tuned properly. I remember having a bear of a time getting things right when working on my copy of FSRW.
I'm hoping to get my P2D2 soon so I can update all the smartpin code I've currently accumulated. The smartpin modes have changed but that should be a simple replace of the config.
''revA smartpin modes sp_stx = %01_11100_0 + (%1111 << 24) ' -1 sp_srx = %00_11101_0 + (%0001 << 24) ' +1 sp_clk = %01_00101_0 '+ sp_inv_pinOnce I take a look at what would be required of the SPI code, I might be able to find some ASM that fits the job better.
*edit -
It looks like all the SPI specific stuff is pretty well contained.
spi8 mov bitcount, #8 shl dval, #24 shl dval, #1 wc :loop muxc OUTA, MOSImask andn OUTA, SCLKmask shl dval, #1 wc or OUTA, SCLKmask djnz bitcount, #:loop andn OUTA, SCLKmask spi8_ret ret { ------------------------------------------------------ } spi16 mov bitcount, #16 shl dval, #16 shl dval, #1 wc :loop muxc OUTA, MOSImask andn OUTA, SCLKmask shl dval, #1 wc or OUTA, SCLKmask djnz bitcount, #:loop andn OUTA, SCLKmask spi16_ret retwould need to be replaced with something like this
spi8 mov t, dval ' type is conversion SHL t, #32-8 ' Set MSB First '' di - stx dirl #_DI wrpin #sp_stx, #_DI ' sync tx wxpin #stx_c, #_DI ' stop/start mode wypin #$FF, #_DI dirh #_DI mov clks, #8 call #send spi8_ret ret spi16 mov t, dval ' type is conversion SHL t, #32-16 ' Set MSB First '' di - stx dirl #_DI wrpin #sp_stx, #_DI ' sync tx wxpin #stx_c16, #_DI ' stop/start mode wypin #$FF, #_DI dirh #_DI mov clks, #16 call #send spi8_ret ret send REV t '' prepare to read wypin t, #_DI ' data !! '' start clock rdpin pa, #_CLK wypin clks, #_CLK ' start clock .busy testp #_CLK wc if_nc jmp #.busy send_ret retSwitching between 8 and 16 bits should be doable, just configure the DI smartpin. Note, smartpins use the actual pin number, not the mask.
The smartpin setup code is pretty simple and it looks like the pin setup in the ILI file is pretty simple
mov OUTA, IF_IDLE mov DIRA, IF_IDLE or DIRA, RSmask or DIRA, MOSImaskgets replaced with
dirl #_CLK outh #_CLK ' mode 1,1 - clock starts high wrpin #sp_clk, #_CLK wxpin b, #_CLK ' set base period (*2) dirh #_CLK '' di - stx dirl #_DI wrpin #sp_stx, #_DI ' sync tx wxpin #stx_c, #_DI ' stop/start mode wypin #$FF, #_DI dirh #_DIIt would take some work, but it's totally doable. I'd breadcrumb you more if I had more time
Many thanks,
Kevin.
forums.parallax.com/discussion/169722/simple-question-how-to-do-p1-par-to-get-address-of-first-variable-in-p2pasm-from-spin2
Please look through attached files.
@cheezus I have marked some lines with ??? where I am lost. Please scan the files. Your corrections would be much appreciated. @Mark_T Thank you for your original files (ex obex). Your comments would be welcome.
Many thanks,
Kevin.
wxpin b, #_CLK ' set base period (*2) see SPI_Smartpin.spin2 see Page 66 ???? '' b is clks per 1/2 bit. Passed from spin method GetBitTime PRI GetBitTime(max_clkfreq) : bt bt :=((clkfreq / max_clkfreq) /2 )+1 ' SPI bit time if bt < 2 ' make sure at least sysclock /2 ''REVB change to 4 bt := 2 '' REVB change to 4NOTE: This is for REVA, since I don't have a REVB board yet I can't verify but I believe this needs to be sysclock /4. I could be wrong...re: del_millis - I'd create a coglong "millis" and pass this value from spin at startup.
The CON section ;
'' smart pin modes sp_stx = %01_11100_0 '+ (%1111 << 24) ' -1 Mode 28 sync serial transmit (A-data, B-clock) ' sp_srx = %00_11101_0 + (%0001 << 24) ' +1 Mode 29 sync serial receive (A-data, B-clock) sp_clk = %01_00101_0 '+ sp_inv_pin _ transition output _ output enabled, regardless of DIR 'sp configs stx_c = (%1 << 5) + (numBits - 1) ' 8 bit default stx_c16 = (%1 << 5) + (16 - 1) ' 16-bit transfer ' srx_c = (%0 << 5) + (numBits - 1) ' rx not used clks = numBits * 2 numBits = 8 ' 8 bit default .. PRI getmask(clk, data) : t t := clk - data if ( || t ) <> t t := ( || t ) + %0100This is how I'd set the constants up (I think). You are only transmitting so safe to remove SRX entries. Also, removing the bpin from the config constant allows this to be computed at startup.
SDSPI.spin2 init and variables
CON {{ SDSPI ASM for P2 v_0_1_0 by Cheezus Slice - Joe Heinz - 2019 cheezusslicedj@gmail.com }} spi_clk_max = 20_000_00 ' 20mhz safe, 26 seems to work though? 27 fail spi_clk_inv = 1 ' 1 inverted, 0 non-inverted { VAR byte cog } DAT cog byte 0 PUB HOOK ' test compile start_explicit( 3, 2, 1, 0 ) PUB Stop if cog cogstop(cog-1) cog := 0 PUB GetCog return cog PUB release PUB start_explicit( _DO, _CLK, _DI, _CS ) : card_type | domask, dimask stop long[@cmd] := "i" 'set flag to know if the started cog has read its parameters long[@cmd][1] := _DO | (_CLK << 8) + (_DI << 16) + ( _CS << 24)' pins long[@cmd][2] := getmask(_CLK, _DO) + (getmask(_CLK, _DI) << 4) ' clock masks long[@cmd][2] += spi_clk_inv << 8 ' clock invert long[@cmd][3] := GetBitTime(spi_clk_max) ' spi bit time long[@cmd][4] := GetBitTime(400_000) '400k cog := cognew(@_asm_start,@cmd) + 1 if cog repeat until long[@cmd] <> "i" ' wait until cog is done reading parameter card_type := long[@cmd][4] ' arg5 returns card type or returns with ptr to error from low level driver PUB ReadBlock(n, b) return DoCommand("r", n, b, 0) PUB WriteBlock(n, b) return DoCommand("w", n, b, 0) PRI GetBitTime(max_clkfreq) : bt bt :=((clkfreq / max_clkfreq) /2 )+1 ' SPI bit time if bt < 2 ' make sure at least sysclock /2 bt := 2 PRI DoCommand(_cmd, _arg1, _arg2, _arg3) repeat while cmd <> 0 arg1 := _arg1 arg2 := _arg2 arg3 := _arg3 cmd := _cmd repeat until cmd <> _cmd return err PRI getmask(clk, data) : t t := clk - data if ( || t ) <> t t := ( || t ) + %0100 DAT org _asm_start mov ptr_to_mbox, ptra ' save mbox address for later '' get parameters from spin do_init mov ptra, ptr_to_mbox ' return ptra back to mbox rdlong tmp, ptra++ ' command long 0 rdlong tmp, ptra++ ' pins long 1 getbyte pinDO, tmp, #0 getbyte pinCLK, tmp, #1 getbyte pinDI, tmp, #2 getbyte pinCS, tmp, #3 rdlong tmp, ptra++ 'mask long 2 getnib sp_doclk, tmp, #0 getnib sp_diclk, tmp, #1 shl sp_doclk, #24 shl sp_diclk, #24 rdlong sp_bt, ptra++ ' timing long 3 rdlong sp_init_bt, ptra ' 400k 4 rdlong delay1s, #$14 ' clkfreq from hub '' setup pins drvh pinCS dirl pinCLK '' setup Clock pin shr tmp, #8 cmp tmp, #1 wz mov tmp, sp_clk if_z add tmp, sp_inv_pin ' invert clock wrpin tmp, pinCLK wxpin sp_init_bt, pinCLK ' set base period (*2) dirh pinCLK ' enable clk dirl pinDI '' setup DI pin mov tmp, sp_stx ' save mode, bpin might change add tmp, sp_diclk ' setup bpin wrpin tmp, pinDI ' sync tx wxpin sp_stx_c, pinDI ' stop/start mode dirh pinDI ' enable smartpin wypin #$FF, pinDI ' prime shifter dirl pinDO '' setup DO pin mov tmp, sp_srx ' save mode, bpin might change add tmp, sp_doclk ' setup bpin wrpin tmp, pinDO ' sync rx wxpin sp_stx_c, pinDO ' 8 bit, pre dirh pinDO ' enable pin '' card init drvh pinCS ' set cs high wypin sectorsize, pinCLK ' set init clocks getct timeout ' setup 1s timeout addct1 timeout, delay1s ' in case card does not respond call #wait_clock ' wait for smartpins to finish dirl pinCLK '' setup Clock pin wxpin sp_bt, pinCLK ' set base period (*2) dirh pinCLK ' enable clk .. .. {=== Smart pin constants ===} sp_clk long %01_00101_0 sp_stx long %01_11100_0 sp_srx long %00_11101_0 sp_stx_c long %1_00111 sp_srx_c long %0_00111 sp_inv_pin long %0000_001_000_000 << 8 byteclks long (2*8) sectorsize long 512 {=== Pin Variables ===} pinDO res 1 ' do pinCLK res 1 ' clk pinDI res 1 ' di pinCS res 1 ' chip select {===== Smartpin Clock Variables =====}'' smartpins stuffs sp_doclk res 1 sp_diclk res 1 sp_bt res 1 sp_init_bt res 1 adrShift res 1 ' will be 0 for SDHC, 9 for MMC & SD ' loaded on init {===== Command Mailbox =====} ptr_to_mbox res 1 cmd_in res 1 arg1_in res 1 arg2_in res 1 arg3_in res 1 err_out res 1 {=== Timing Variables ===} delay1s res 1 ' clkfreq = 1 s timeout res 1 {=== Temp Variables ===} tmp res 1 ' this may get used in all subroutines...don't use except in lowest data_in res 1 data_out res 1 sd_cmd res 1 sd_parm res 1 FIT 496You may also want to look at using the PTRA/PTRB for hub access. Hopefully this helps a bit. Sorry I don't have more time right now. I've been meaning to make a general SPI cog but waiting for REVB silicon so I can test properly
Kevin.
Glad I could help. I too am still learning but getting better at it.