User Tools

Site Tools


en:pfw:i2c_gd32vf_noforth_gd32vf103_bb-i2c.f

(* GD32VF103 bitbang I2C driver

Values for CRL/CRH-Registers:
 0:  Analog Input
 1:  Output Push/Pull, 10 MHz
 2:  Output Push/Pull,  2 MHz
 3:  Output Push/Pull, 50 MHz
 4:  Floating Input (Reset state)
 5:  Open-Drain Output, 10 MHz
 6:  Open-Drain Output,  2 MHz
 7:  Open-Drain Output, 50 MHz
 8:  Input with pull-up / pull-down
 9:  Alternate Function, Push/Pull, 10 MHz
 A:  Alternate Function, Push/Pull,  2 MHz
 B:  Alternate Function, Push/Pull, 50 MHz
 C:  Reserved
 D:  Alternate Function, Open-Drain, 10 MHz
 E:  Alternate Function, Open-Drain,  2 MHz
 F:  Alternate Function, Open-Drain, 50 MHz

PB6 = SCL
PB7 = SDA

  User words:  I2C-ON  {I2C-WRITE  {I2C-READ   I2C}
               BUS@  BUS!  DEVICE!  {DEVICE-OK?}
  Additional:  {I2C-OUT  {I2C-IN  {POLL}  BUS!}  BUS@}  BUS-MOVE
 
  An example, first execute I2C-ON  After that the I2C is setup as
  a master. Sent byte 'b' to an I2C device with address 'a'.
    : >SLAVE    ( b a -- )  {i2c-write  bus!  i2c} ;
    : >PCF8574  ( b -- )    40 >slave ;

*)

hex  
v: inside also definitions
40010C00 constant PB-CRL    \ Port-B control Register for pins 0 to 7
40010C08 constant PB-IDR    \ Port-B Input Data Register
40010C0C constant PB-ODR    \ Port-B Output Data Register

40 constant SCL             \ I2C clock line 
80 constant SDA             \ I2C data line
SCL SDA or constant BUS     \ I2C bus lines

value DEV  value SUM  value NACK?
\ : WAIT          ( -- )      10 for next ;         \ About 100 KHz with 104 MHz clock
  : WAIT          ( -- )      02 for next ;         \ About 200 KHz with 104 MHz clock
\ : WAIT          ( -- )      ;                     \ About 300 KHz with 104 MHz clock
\ : WAIT          ( -- )      ; immediate           \ About 380 KHz with 104 MHz clock

: I2START       ( -- )
    scl pb-odr *bis  wait
    sda pb-odr *bic  wait ;
 
: I2ACK         ( -- )
    scl pb-odr *bic  sda pb-odr *bic  wait
    scl pb-odr *bis  wait ;

: I2NACK        ( -- )
    scl pb-odr *bic  sda pb-odr *bis  wait
    scl pb-odr *bis  wait ;

: I2ACK@        ( -- )
    scl pb-odr *bic  sda pb-odr *bis  wait
    scl pb-odr *bis  wait
    sda pb-idr bit* to nack? ;

v: extra definitions
: BUS!          ( b -- )
    8 for
        scl pb-odr *bic 
        dup 80 and if   sda pb-odr *bis
        else            sda pb-odr *bic
        then            wait  2*
        scl pb-odr *bis  wait
    next  drop  i2ack@ ;

v: inside definitions
: {I2C-ADDR     ( +n -- )       drop  i2start  dev bus! ; \ Start I2C write with address from DEV


\ Higher level I2C access, hides internal details!
v: extra definitions
: I2C-ON        ( -- )
    6644,4444 pb-crl !  \ Set PB5 & PB6 as I2C output (Reset $44444444)
    bus pb-odr *bis ;   \ I2C floating at startup

: BUS@          ( -- b )
    0  8 for
        2*  scl pb-odr *bic  sda pb-odr *bis  wait
        sda pb-idr bit*  0<> 1 and  or
        scl pb-odr *bis wait
    next 
    -1 +to sum
    sum if  i2ack  else  i2nack  then ;

: I2C}          ( -- )
    scl pb-odr *bic  sda pb-odr *bic  wait
    scl pb-odr *bis  wait
    sda pb-odr *bis ;

: DEVICE!       ( ia -- )   2* FE and  to dev ;
: {DEVICE-OK?}  ( -- f )    0 {i2c-addr  i2c}  nack? 0= ; \ 'f' is true when an ACK was received 
: {I2C-WRITE    ( +n -- )   {i2c-addr  nack? ?abort ; \ Start I2C write to device in DEV

: {I2C-READ     ( +n -- )     \ Start read from device in DEV
    to sum  i2start  dev 1+ bus!  nack? ?abort ; 


\ Waiting for an EEPROM write to succeed is named acknowledge polling.
: {POLL}    ( -- )          begin  {device-ok?} until ; \ Wait until ACK received
: {I2C-OUT  ( dev +n -- )   swap  device!  {i2c-write ;
: {I2C-IN   ( dev +n -- )   swap  device!  {i2c-read ;
: BUS!}     ( b -- )        bus!  i2c} ;
: BUS@}     ( -- b )        bus@  i2c} ;
: BUS-MOVE  ( a u -- )      bounds ?do i c@ bus! loop ; \ Send string of bytes from 'a' with length 'u

v: fresh
shield BB-I2C\  freeze

\ End ;;;
en/pfw/i2c_gd32vf_noforth_gd32vf103_bb-i2c.f.txt · Last modified: 2023-09-04 18:15 by uho