XPT2046 SPI Smartpin driver

I wanted to share this bit of code I've been working on for reading X-Y from the touch panel ADC. It could be generalized into an SPI driver but I think I'm going the other route and creating a SPI cog for my platform. I have 3 spi devices +1 spare external, with muxed cs creating an object to handle all of it makes sense. I have some crazy ideas for later.. :D Maybe someone will find it useful as is, (and I need to check what the RPI display I have uses...)

I'm thinking of pre-encoding the x,y config registers since these don't change... I'm thinking about keeping the bit-time conversion though, since I could be changing the clock dynamically in the future. It might make sense to pre-compute as much of the bit-time calc as possible, but haven't really looked at that yet. I also am inverting the clock pin using the out register. This is a residual from testing, as is the removal of the GetMask and hard-coding of the b-pin.

It works for now and I hope to not have to revisit this until I'm writing a driver for the SPI flash. Two down (the important 2), one to go! Now I just need to refine the touch panel calibration program and it's almost demo time!
CON
{{  =============================================================
        Basic X-Y driver for XPT 2046 Touch Screen Controller 
        Inline Smartpin SPI v0.5       -       11-26-19
        Cheezus Slice - Cheezusslicedj@gmail.com        
        This driver uses hard-coded pins but should be easy to 
        make dynamic if you wish. Only reads X-Y
    =============================================================
}}    
    _CS     = 15 '+ 32      ' chip select
    _CLK    = 13 '+ 32      ' Pins A, uncomment +32 for Pins B
    _DI     = 14 '+ 32      ' MOSI
    _DO     = 12 '+ 32      ' MISO
    '' config register 
    ''         S A2__A1__A0 MODE  SER PD1__PDO
    y_cfg   = %1__1___0___1___0____0____0____0  ' X  DIFF
    x_cfg   = %1__0___0___1___0____0____0____0  ' Y  DIFF

{
    z1_cfg  = %1__0___1___1___0____0____0____0  ' Z1 DIFF
    z2_cfg  = %1__1___0___0___0____0____0____0  ' Z2 DIFF
    t_cfg   = %1__0___0___0___0____1____0____0  ' temperature 
    b_cfg   = %1__0___1___0___0____1____0____0  ' battery
    a_cfg   = %1__1___1___0___0____1____0____0  ' battery
}   
    '' spi stuff  
    spi_clk_max = 2_000_000 
    '%AAAA_BBBB_FFF_PPPP_PPP_PPP_PPP_TT_MMMMM_0
    'ppp        =___xxxx_CIO_HHH_LLL 
    sp_inv_pin  = %0000_001_000_000 << 8
    'smartpin modes  TT_MMMMM_0
    sp_stx      =   %01_11100_0 + (%1111 << 24)     ' -1    b pin - clk    
    sp_srx      =   %00_11101_0 + (%0001 << 24)     ' +1    b pin - clk
    sp_clk      =   %01_00101_0 '+ sp_inv_pin 
    'sp configs
    stx_c       =   (%1 << 5) + (numBits - 1)       '   start-stop mode   
    srx_c       =   (%0 << 5) + (numBits - 1)       '   pre-clock sample                                                             
    clks        =   numBits * 2                     
    numBits     =   24                              ' 24 bits conversion

    
PUB TouchXY| x, y, xo, yo, b        
    b := GetBitTime(spi_clk_max)   
    asm    
            '' prepare data out x  ?should pre-encode?
            mov     xo,         #x_cfg          ' type is conversion 
            SHL     xo,         #32-8           ' Set MSB First
            REV     xo                          ' Set MSB First
            '' prepare data out y
            mov     yo,         #y_cfg       
            SHL     yo,         #32-8          
            REV     yo                          
            '' clk - transition
            dirl    #_CLK
            outh    #_CLK                       ' mode 1,1 - clock starts high
            wrpin   #sp_clk,    #_CLK   
            wxpin   b,          #_CLK           ' set base period (*2) 
            dirh    #_CLK    
            '' do - srx
            dirl    #_DO
            wrpin   #sp_srx,    #_DO            ' sync rx
            wxpin   #srx_c,     #_DO            ' stop/start mode    
            dirh    #_DO
            '' di - stx
            dirl    #_DI
            wrpin   #sp_stx,    #_DI            ' sync tx
            wxpin   #stx_c,     #_DI            ' stop/start mode
            wypin   #$FF,       #_DI
            dirh    #_DI
            drvl    #_CS
            '' prepare to read                 
            rdpin   pa,         #_DO            ' clear RX buffer
            wypin   xo,         #_DI            ' data !!
            '' start clock        
            rdpin   pa,         #_CLK
            wypin   #clks,      #_CLK           ' start clock            
    .busy   testp   #_CLK               wc
    if_nc   jmp     #.busy
            rdpin   x,          #_DO            ' get data
            '' prepare to read            
            rdpin   pa,         #_DO            ' clear RX buffer   
            wypin   yo,         #_DI            ' data !!
            '' start clock        
            rdpin   pa,         #_CLK
            wypin   #clks,      #_CLK           ' start clock            
    .busy2  testp   #_CLK               wc
    if_nc   jmp     #.busy2
            rdpin   y,          #_DO            ' get data
            drvh    #_CS                        ' drive CS high

            ' now handle data  
            shl     x,          #3              ' throw away msb             
            rev     x            
            and     x,          #$ffff          ' isolate 12b    
            ' now handle data  
            shl     y,          #3              ' throw away msb             
            rev     y            
            and     y,          #$ffff          ' isolate 12b 

            wypin   #0,         #_DI            ' clear buffer               
            wrpin   #0,         #_CLK
            wrpin   #0,         #_DO
            wrpin   #0,         #_DI
            dirl    #_CLK
            dirl    #_DO
            dirl    #_DI                     
    endasm
    
    result :=  x + (y << 16)  
        
PRI getmask(clk, data) : t          ' get mask to add to smartpin mode
    t := clk - data
    if ( || t ) <> t        
      t := ( || t ) + %0100     
    

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
Sign In or Register to comment.