
\ REGISTERS GPIO

FE000000 CONSTANT PERI_BASE
PERI_BASE 200000 + CONSTANT GPIO_BASE
PERI_BASE 804000 + CONSTANT I2C_BASE_REGISTER
GPIO_BASE 	CONSTANT GPFSEL0


: REGISTERS_I2C{ \ ( -- ADDR )
  I2C_BASE_REGISTER ;

: REGISTER ( ADDR -- ADDR )
  DUP 4 + SWAP CONSTANT ;

: }REGISTERS_I2C ( ADDR -- )
  DROP ;

REGISTERS_I2C{
  REGISTER I2C_CONTROL
  REGISTER I2C_STATUS
  REGISTER I2C_DLEN
  REGISTER I2C_SLAVE_REGISTER
  REGISTER I2C_FIFO
  REGISTER I2C_CLOCK_DIVIDER
  REGISTER I2C_DATA_DELAY
  REGISTER I2C_CLOCK_STRETCH_TIMEOUT
}REGISTERS_I2C

\ CONTROL_REGISTER


\ ENABLE/DISABLE I2C
: I2C ( FLAG -- )
  I2C_CONTROL F SET_BIT ;

\ START_TRANSFER
: ST ( -- )
  1 I2C_CONTROL 7 SET_BIT ;

\ CLEAR_FIFO
: CLEAR ( -- )
  1 I2C_CONTROL 4 SET_BIT ;

\ READ_TRANSFER
: R_BIT ( -- )
  1 I2C_CONTROL 0 SET_BIT ;

\ WRITE_TRANSFER
: W_BIT ( -- )
  0 I2C_CONTROL 0 SET_BIT ;

\ INTERRUPT_RX
: INTR ( FLAG -- )
  I2C_CONTROL A SET_BIT ; \ ENABLE/DISABLE INTERRUPTS ON RX

\ INTERRUPT_TX
: INTT ( FLAG -- )
  I2C_CONTROL 9 SET_BIT ; \ ENABLE/DISABLE INTERRUPTS ON TX

\ INTERRUPT_DONE
: INTD ( FLAG -- )
  I2C_CONTROL 8 SET_BIT ; \ ENABLE/DISABLE INTERRUPTS ON DONE



\ STATUS

\ USE GET_BIT FOR READING THE BIT'S VALUE

\ CLOCK_STRETCH_TIMEOUT
: CLKT ( -- REGISTER BIT_POSITION )
  I2C_STATUS 9 ;

\ ACK ERROR
: ERR ( -- REGISTER BIT_POSITION )
  I2C_STATUS 8 ;

\ FIFO FULL
: RXF ( -- REGISTER BIT_POSITION )
  I2C_STATUS 7 ;

\ FIFO EMPTY
: TXE ( -- REGISTER BIT_POSITION )
  I2C_STATUS 6 ;

\ FIFO CONTAINS DATA
: RXD ( -- REGISTER BIT_POSITION )
  I2C_STATUS 5 ;

\ FIFO CAN ACCEPT DATA
: TXD ( -- REGISTER BIT_POSITION )
  I2C_STATUS 4 ;

\ FIFO NEEDS READING
: RXR ( -- REGISTER BIT_POSITION )
  I2C_STATUS 3 ;

\ FIFO NEEDS WRITING
: TXW ( -- REGISTER BIT_POSITION )
  I2C_STATUS 2 ;

\ TRANSFER DONE
: DONE ( -- REGISTER BIT_POSITION )
  I2C_STATUS 1 ;

\ TRANSFER ACTIVE
: TA ( -- REGISTER BIT_POSITION )
  I2C_STATUS 0 ;

: RESET ( REGISTER BIT_POSITION -- )
  1 -ROT SET_BIT ;


\ FIFO
\ FOR SETTING ( VALUE DATA SET ) FOR GETTING ( DATA GET )
: DATA ( -- REGISTER BIT_POSITION_INITIAL BIT_POSITION_FINAL )
  I2C_FIFO 0 7 ;


\ SETTING ALTERNATE FUNCTIONS AND ENABLE I2C
: I2C_INIT
  GPFSEL0 DUP @ FC0 INVERT AND 900 OR SWAP !
  ENABLE I2C ;


\ I2C USAGE

\ CHECK IF THE TRANSFER IS DONE CORRECTLY ( DONE==1 TA==0 ERR==0)
: ?CHECK ( -- FLAG )
  DONE GET_BIT TA GET_BIT 0= ERR GET_BIT 0= AND AND ;


: I2C_WRITE ( VALUES SLAVE_ADDRESS #BYTES -- )
  DONE RESET \ RESET DONE
  CLEAR \ CLEAR FIFO
  DUP >R \ DUPLICATE #BYTES ONTO RETURN STACK
  I2C_DLEN ! \ SET #BYTES
  I2C_SLAVE_REGISTER ! \ SET SLAVE ADDRESS
  W_BIT \ SET WRITING
  R>
  BEGIN
    1- SWAP DATA SET DUP 0= \ SET FIFO
  UNTIL DROP
  ST \ START WRITING
  BEGIN
    ?CHECK \ WAIT UNTIL THE CORRECT WRITING
  UNTIL ;


: I2C_READ ( SLAVE_ADDRESS #BYTES -- VALUES )
  DONE RESET \ RESET DONE
  DUP >R \ DUPLICATE #BYTES ONTO THE RETURN STACK
  I2C_DLEN ! \ SET #BYTES
  I2C_SLAVE_REGISTER ! \ SET SLAVE ADDRESS
  R_BIT \ SET READING
  ST  \ START READING
  BEGIN
    ?CHECK \ WAIT UNTIL THE CORRECT READING
  UNTIL
  R>
  BEGIN
    1- DATA GET SWAP DUP 0= \ PUSH DATA ONTO THE STACK
  UNTIL DROP ;
