( SPI_Progs)
( R.J.Wilks   March 2014)
( Using ADC channel 0 on Gertboard with SPI bus transfer)
( set address and bit positions in SPI_CS etc)

HEX
( get address of CS Register - Master Controller & Status)
200 20204000 DECIMAL 13 SPI_reg BINARY
CONSTANT SPI_CS
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)

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)

DECIMAL
1000 VARIABLE Twait

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

: dsp_SPI_CS HEX SPI_CS rd_SVCmode . CR DECIMAL ;  ( ...)

( Activate SPI pins 7 to 11 - call to GPIO module)
: set_SPIpins GPExpMMC ;   ( ...)

: unset_SPIpins   ( ...)  ( back to GPIO pins - input)
     0 7 GPWrMode 0  8 GPWrMode 0  9 GPWrMode
     0 10 GPWrMode 0 11 GPWrMode ;    

( Clock ..)
256 VARIABLE CDIV     ( Clock Divider value)
: set_clock  CDIV @ SPI_CLK  wr_SVCmode ;

( FIFOs ...)
: read_FIFO   SPI_FIFO rd_SVCmode 255 AND ;  ( ... value)
: write_FIFO  255 AND SPI_FIFO wr_SVCmode ;  ( value ...)

( Setup SPI bus - FIFOs cleared and 'DONE' to zero)
: setup_spi   ( ...)
   set_clock
   CS_CLRALL SPI_CS wr_SVCmode
   CS_DONE   SPI_CS wr_SVCmode ;

: clr_TA  SPI_CS rd_SVCmode CS_ACTIVATE XOR 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)
;

: wait_done   ( ...)   ( wait for SPI to be ready - about 16 microsec)
   BEGIN
     CS_DONE SPI_CS  test_bitz  ( rd_SVCmode AND)
   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 SWAP 5 << OR write_FIFO   ( = &D0 ch<<5 command byte)
   0 write_FIFO             ( dummy)
   read_FIFO read_FIFO      ( read 2 bytes from ADC and put on stack)
   wait_done                ( wait until ready - DONE bit)
   clr_TA                   ( TA=0 to stop transfers)
   SWAP 7 AND 8 <<
   OR 2/                    ( combine to 10-bit value)
;

: ADCsetup_general   ( ...)
  set_SPIpins setup_spi ;

: ADC   ( ch no...)
  0 1 confine        ( channel 0 or 1 only)
  ADCsetup_general
  ( loop and display)
  CR ." ADC Values:" CR
  DUP read_adc DROP  ( discard first reading)
   0 TIME=
  1000 0 DO
       DUP read_adc  .
       ( Twait @ short_wait)
       LOOP DROP
  unset_SPIpins
   TIME ." csec= " .
;
                                                              