To use this file copy and paste this:    // #URL-lib "http://pin1.org/forthlib/flb/I2C/i2c.flb"   into BV Terminal 3 or here to download.

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // I2C interface // Uses the built in I2C functionality of the LPC2xxx // This is the generic I2C driver with ARM as the master // To drive individual devices // NOTE: This file only makes use of I2C channel 0, there is // another channel but it is not implemented here // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

// HISTORY: // Aug 2007 *updated by adding a few extra words // *added a section at the back // Oct 2007 *error with P, should not use i2-valid (corrected) // *added libaraies // Dec 2007 *loader added // *sid used in loader-1 // Feb 2008 *this file is now a library with // *only the public words exposed // Nov 2008 *Renamed the AA,SI,STO & STA constants to prevent // clashes when using with sid=0 // *Increased number of re-tries on i2-start to cater for // slow devices

// REQUIRES: // #URL-lib "http://pin1.org/forthlib/flb/General/soft1.flb" sid=0 // #URL-lib "http://pin1.org/forthlib/flb/General/pinsel.flb" sid=101

// Register CONSTANTS: // channel 0 - only channel 0 used, there is a channel 1, extend // this file as required. &E001C000 constant I2CONSET &E001C004 constant I2STAT &E001C008 constant I2DAT &E001C00C constant I2ADR // not used &E001C010 constant I2SCLH &E001C014 constant I2SCLL &E001C018 constant I2CONCLR // easier to understand 4 constant I2_AA 8 constant I2_SI 16 constant I2_STO 32 constant I2_STA


Full Contents of File

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// I2C interface
// Uses the built in I2C functionality of the LPC2xxx
// This is the generic I2C driver with ARM as the master
// To drive individual devices
// NOTE: This file only makes use of I2C channel 0, there is
// another channel but it is not implemented here
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

// HISTORY:
// Aug 2007 *updated by adding a few extra words
// *added a section at the back
// Oct 2007 *error with P, should not use i2-valid (corrected)
// *added libaraies
// Dec 2007 *loader added
// *sid used in loader-1
// Feb 2008 *this file is now a library with
// *only the public words exposed
// Nov 2008 *Renamed the AA,SI,STO & STA constants to prevent
// clashes when using with sid=0
// *Increased number of re-tries on i2-start to cater for
// slow devices


// REQUIRES:
// #URL-lib "http://pin1.org/forthlib/flb/General/soft1.flb" sid=0
// #URL-lib "http://pin1.org/forthlib/flb/General/pinsel.flb" sid=101

// Register CONSTANTS:
// channel 0 - only channel 0 used, there is a channel 1, extend
// this file as required.
&E001C000  constant  I2CONSET
&E001C004  constant  I2STAT
&E001C008  constant  I2DAT
&E001C00C  constant  I2ADR        // not used
&E001C010  constant  I2SCLH
&E001C014  constant  I2SCLL
&E001C018  constant  I2CONCLR
// easier to understand
4    constant  I2_AA
8    constant  I2_SI
16  constant  I2_STO
32  constant  I2_STA

// Set I2C frequency in Hz, this is for starters and can be changed
// by the public word at the end of the file
50000  constant  i2cBusSpeed  // conservative

// run this first to set up hardware
// (---)
: i2c-init
        2  1  pinselect      // set i2c functions
        3  1  pinselect      // on pins p0.2 and p0.3
        pclk  i2cBusSpeed  / // I2C speed
        dup  I2SCLH  !  I2SCLL  !      // 75khz @ plck = 60Mhz
        &40  I2CONSET  !    // enable i2c
;

// enables speed to be set after initialisation
// set speed in Hz, i.e 100000 = 100kHz
// ( speed ---)
: i2-speed
        pclk  swap  / dup
        I2SCLH  !  I2SCLL  !
;       

// send start condition return true if master can
// take charge of bus, otherwise returns 0
// ( --- -1|0)
: i2-start
        0
        10000  for
                I2_STA  I2CONSET  !  // start
                I2STAT  @  &08  =  if  drop  -1  leave  then
        next
;

// when a command is issued the status goes to &f8
// this can keep the command here until its finished
// the time out of 100000 should be long enough for the slowest of
// i2c devices. It is about 300ms
: i2-valid
        100000 
        for 
                i2stat  @  &f8  <>  if  leave  then
        next
;               

// Checks status of I2c device with timeout, if
// no agreement will abort, otherwise continues
// ( stat ---)
: i2-stat
        i2stat  @  2dup  <>
        if 
                cr  ."  i2c  Error  -  Status  recieved  "  ph.  ."  Expecting  "  ph.
                abort
        else
                2drop
        then               
;

// I2c data register for putting and fetching the data
: i2-dat@i2dat  @  ;  // ( --- data)
: i2-dat!i2dat  !  ;  // ( data ---)

// In general i2c3 will do as a stop condition, but not always
// these commands take a finite time to establish, and when they are
// not ready the status is &f8, i2-valid returns when these commands
// return a valid state or a time out occures
// conditions, see datasheet STA ST0 SI AA
: i2c1I2_STA  I2_STO  +  I2_SI  +  i2conclr  !  i2-valid  ;              // 0 0 0 x
: i2c2I2_STA  i2conset  !  I2_STO  I2_SI  +  i2conclr  !  i2-valid  ;  // 1 0 0 x
: i2c3I2_STO  i2conset  !  I2_STA  I2_SI  +  i2conclr  !  i2-valid  ;  // 0 1 0 x
: i2c4I2_STA  I2_STO  +  i2conset  !  I2_SI  i2conclr  !  i2-valid  ;  // 1 1 0 x
: i2c5I2_STA  I2_STO  +  I2_SI  +  I2_AA  +  i2conclr  !  i2-valid  ;    // 0 0 0 0
: i2c6I2_AA  i2conset  !  I2_STA  I2_STO  +  I2_SI  +  i2conclr  !  i2-valid  ; 
// 0 0 0 1
//
: i2-8i2dat  !  I2_STO  I2_SI  +  i2conclr  !  i2-valid  ;  // ( device-address --- )
: i2-10i2dat  !  I2_STO  I2_SI  +  i2conclr  !  i2-valid  ;  // ( device-address --- )


// **************************************************************
// The following uses the above to create an I2C interface
// **************************************************************
// Example
// To write to a simple device address &50
// &50 s ; start and sends address
// 12 i2-sb ; send byte
// p ; stop
// To read
// &51 s
// i2-rn
// i2-rl ; lasyt byte ** bus will hang if not used
// p



// Start and send address
// ( address ---)
: (s)
        i2-start  0=  abort"  Error  I2C  cant  start"
        i2stat  @  &8  =    if  i2-8    escape  then
        i2stat  @  &10  =  if  i2-10  escape  then
        ."  Error  start  returns  "  i2stat  @  ph.
        ."  as  status  value"
;       

// =================== Public interface ==========================
// Stop - should return &f8 as a status but may need
// a small amount of time to do this.
: <0>pI2_STO  i2conset  !  I2_STA  I2_SI  +  i2conclr  !  // i2c3 without valid checkg
        -1
        100000 
        for 
                i2stat  @  &f8  =
                if
                        1+  leave
                then   
        next
        if
                ."  I2C  Stop  error"
        then       
;                       

// Start and send address
// ( address ---)
: <0>s
      (s)   // check if device exists & bus okay
        i2stat  @  // should not be 38,48,or 0x58
        dup  &38  =  swap  dup  &48  =  swap  &58  =  or  or
        if  ."  Device  does  not  acknowledge"  p  then
;

// repeated start
// ( address ---)
: <0>rs     
        i2c2  i2stat  @  &10  =
        if
                i2-10 
        else
                ."  Repeated  start  error"
        then
;                       
         
// send next byte, no need for last byte
// ( data ---)
: <0>sb
        i2dat  !
        i2c1
;       
       
// read next byte
// ( --- data)
: <0>rn
        i2c6  &50  i2-stat
        i2-dat@
;

// read last byte - does not do stop
// ( --- data)
: <0>rl
        i2c5  &58  i2-stat
        i2-dat@
; 

: <0>I2-init ( -- )   i2c-init  ;
: <0>i2Speed ( Hz -- )   I2-speed  ;