Shop OBEX P1 Docs P2 Docs Learn Events
Use of spin2cpp - Page 3 — Parallax Forums

Use of spin2cpp

13»

Comments

  • @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:
    CON
    #ifdef __P2__
      _CLKMODE = $010007f8
      _XINFREQ = 160_000_000
      baudrate = 230_400
      propRX = 63
      propTX = 62
      nRESET= 8
      RS    = 9
      nCS   = 7
      MOSI  = 10
      SCLK  = 11
      MISO  = 12
    #else
      _CLKMODE = xtal1 + pll16x
      _XINFREQ = 80_000_000
      baudrate = 115_200
      propRX = 31
      propTX = 30
      nRESET= 8
      RS    = 9
      nCS   = 7
      MOSI  = 10
      SCLK  = 11
      MISO  = 12
    #endif
    
    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.
  • kg1kg1 Posts: 164
    edited 2020-01-14 20:33
    Hello @Mark_T
    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.
  • cheezuscheezus Posts: 295
    edited 2020-01-15 01:33
    kg1 wrote: »
    Hello @Mark_T
    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. :smirk:

    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_pin 
    

    Once 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      ret
    
    

    would 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   ret
    

    Switching 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, MOSImask
    

    gets 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    #_DI
    

    It would take some work, but it's totally doable. I'd breadcrumb you more if I had more time :smile:
  • @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.
  • @pilot0315 Thank you for your tutorial: great help understanding PAR:
    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.
    "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 :wink:
  • @cheezus Thank you for looking through my files. I will study your reply and sdspi_asm.spin2.
    Kevin.
  • @kg1

    Glad I could help. I too am still learning but getting better at it.
Sign In or Register to comment.