( SPI_Progs)

( set address and bit positions in SPI_CS etc - see page 153)
( NB bus address of 7E000000 corresponds to physical address of 20000000)
(   - use physical addresses)


HEX
( get address of CS Register - Master Controller & Status)
200 20204000 DECIMAL 13 SPI_reg BINARY
( ." SPI_reg addr= " DUP BINARY U.  )

CONSTANT SPI_CS
( ." SPI_CS constant= " SPI_CS U. CR )
      
HEX
SPI_CS 4 + CONSTANT SPI_FIFO    ( SPI Master TX & RX FIFOs Reg)
SPI_CS 8 + CONSTANT SPI_CLK     ( SPI Master Clock Divider Reg)

00800000 CONSTANT CS_CS2    ( CSPOL2)
00400000 CONSTANT CS_CS1    ( CSPOL1)
00200000 CONSTANT CS_CS0    ( CSPOL0)

00100000 CONSTANT CS_RXFIFOFULL  ( RXF)
00080000 CONSTANT CS_RXFIFO3_4   ( RXR)
00040000 CONSTANT CS_TXFIFOSPCE  ( TXD)
00020000 CONSTANT CS_RXFIFODATA  ( RXD)
00010000 CONSTANT CS_DONE        ( DONE)

00001000 CONSTANT CS_MOSI_INPUT  ( REN)
00000800 CONSTANT CS_DEASRT_CS   ( ADCS)
00000400 CONSTANT CS_RX_IRQ      ( INTR)
00000200 CONSTANT CS_DONE_IRQ    ( INTD)
00000100 CONSTANT CS_DMA_ENABLE  ( DMAEN)

00000080 CONSTANT CS_ACTIVATE    ( TA - Transfer Active)
00000040 CONSTANT CS_POLARITY    ( CSPOL)
00000020 CONSTANT CS_CLRTXFIFO   ( CLEAR)
00000010 CONSTANT CS_CLRRXFIFO   ( CLEAR)
00000030 CONSTANT CS_CLRFIFOS    ( CLEAR)

00000008 CONSTANT CS_CLK_IDLHI   ( CPOL)
00000004 CONSTANT CS_CLK_TRANS   ( CPHA)  ( use 0 - also can use 0 for middle of data bit)

00000000 CONSTANT CS_CHIPSEL     ( CS)    ( only 0 or 1 - 0 for channel A)

: CS_CLRALL CS_CLRFIFOS CS_DONE OR ;  ( bit pattern to clear FIFOS and DONE together)

 0 VARIABLE COUNTER 

DECIMAL

( Clock ..)
256 VARIABLE CDIV     ( Clock Divider value)
: set_clock  CDIV @ SPI_CLK  wr_SVCmode  ;  ( value,addr ...) ( in SVC mode)

( FIFOs ...)
( Polling requires DMAEN clear and TA set)
: read_FIFO  SPI_FIFO rd_SVCmode ;  ( ... value)   ( in SVC mode)
: write_FIFO  SPI_FIFO wr_SVCmode ;  ( value ...)  ( in SVC mode)

( Utilities)
: ?Esc -113 INKEY ;    ( ..... 0/FF) ( >1 if Esc pressed)

: short_wait 0 DO I I * DROP LOOP ;   ( n...)

: dsp_SPI_CS HEX SPI_CS rd_SVCmode . CR DECIMAL ;  ( in SVC mode)


( Activate SPI pins)
: ?set_SPIpins 
     ( set as inputs first - recommended)
      0 7  GPWrMode  0  8 GPWrMode  0 9 GPWrMode
      0 10 GPWrMode  0 11 GPWrMode
    GPExpMMC                      ( pins 7 to 11 set for SPI bus)
     ( pins 8 to 11 - 'alt0')
     4 8 GPWrMode  4 9 GPWrMode 4 10 GPWrMode 4 11 GPWrMode
      8 GPRdMode ( ." Mode=" . KEY DROP)
;

: set_SPIpins
   GPExpMMC 
   ( 8 GPRdMode) ( ." Mode= " . KEY DROP )  ( Returns 4 - OK)
;

: unset_SPIpins
    ( 12 7 DO 0 DUP I GPWrMode LOOP DROP ; )    ( back to GPIO pins - input)
     0 7 GPWrMode 0  8 GPWrMode 0  9 GPWrMode
     0 10 GPWrMode 0 11 GPWrMode ;    

( Setup SPI bus)  ( in SVC mode)
: setup_spi
   set_clock
   CS_CLRALL SPI_CS wr_SVCmode
   CS_DONE   SPI_CS wr_SVCmode 
;

: test_bitz   ( bit code, addr ..... flg)
  rd_SVCmode  ( bit code,reg value ...)  ( in SVC mode)
  AND         ( n ...)            ( n>0 if reg has a 1 in this bit position)
  0= 0=       ( flg...)           ( 0/1 flg - '1' if bit=1 in reg)
;

: clr_TA  SPI_CS rd_SVCmode CS_ACTIVATE XOR SPI_CS wr_SVCmode ;

: get_Rx    ( wait for SPI to be ready - about 16 microsec)
   ( 0  COUNTER !)
   BEGIN
     CS_DONE  SPI_CS test_bitz
     ( 1 COUNTER +!)
     ( COUNTER @ 1000000 > IF DROP 1 ENDIF)
   UNTIL
;

( Read ADC)
: read_adc
  500 short_wait   ( to ensure chip select is high for a short while)
   CS_CHIPSEL  CS_ACTIVATE OR SPI_CS wr_SVCmode  ( use CS0 and set activate bit)
   ( now write the command into the FIFO - 2 x 8-bit words)
   208 write_FIFO           ( = 0xD0 command byte)
   get_Rx read_FIFO
   0 write_FIFO             ( dummy)
   get_Rx read_FIFO         ( wait until ready - DONE bit)
   CS_DONE  SPI_CS  wr_SVCmode       ( clear DONE bit) ( Is this correct?  TA instead?)
   clr_TA    ( to clear TA)
   SWAP 8 <<
   OR 2/                     ( combine)
;

: adc_wait   ( n csec .... )  ( governs speed)
   0 TIME=
   BEGIN DUP TIME < UNTIL 
   DROP ; 

: ADCsetup_general 
  set_SPIpins   ( ." SPI_CS after setup_io = " dsp_SPI_CS)
  setup_spi     ( ." SPI_CS after setup_spi = " dsp_SPI_CS) ;

: ADC   ( ...)
  SP! CR
  ADCsetup_general 
  ( loop and display)
  50 0 DO
       read_adc
       ." ADC value= " . CR 
       50 adc_wait
       LOOP
  unset_SPIpins
  ( ." SP after ADC " SP@ . CR)
;
                                                              