Announcement

Collapse
No announcement yet.

Bit-bang I2C solution for MPL3115A2 that supports repeated Start conditions

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Bit-bang I2C solution for MPL3115A2 that supports repeated Start conditions

    EDIT This code serves no purpose on the Diablo architecture as it provides multiple I2C ports that fully support I2C repeated starts. See This Post



    For the MPL3115A2 altimeter/pressure-sensor: Here's a fully-blocking, slow, and depressingly written block of code that also happens to work. Just in case anyone else is looking for this solution.

    Code:
    #platform "uLCD-70DT"
    
    #inherit "4DGL_16bitColours.fnc"
    #constant #define $#constant
    #define STATUS 0x00
    #define OUT_P_MSB 0x01
    #define OUT_P_CSB 0x02
    #define OUT_P_LSB 0x03
    #define OUT_T_MSB 0x04
    #define OUT_T_LSB 0x05
    #define DR_STATUS 0x06
    #define OUT_P_DELTA_MSB 0x07
    #define OUT_P_DELTA_CSB 0x08
    #define OUT_P_DELTA_LSB 0x09
    #define OUT_T_DELTA_MSB 0x0A
    #define OUT_T_DELTA_LSB 0x0B
    #define WHO_AM_I 0x0C
    #define F_STATUS 0x0D
    #define F_DATA 0x0E
    #define F_SETUP 0x0F
    #define TIME_DLY 0x10
    #define SYSMOD 0x11
    #define INT_SOURCE 0x12
    #define PT_DATA_CFG 0x13
    #define BAR_IN_MSB 0x14
    #define BAR_IN_LSB 0x15
    #define P_TGT_MSB 0x16
    #define P_TGT_LSB 0x17
    #define T_TGT 0x18
    #define P_WND_MSB 0x19
    #define P_WND_LSB 0x1A
    #define T_WND 0x1B
    #define P_MIN_MSB 0x1C
    #define P_MIN_CSB 0x1D
    #define P_MIN_LSB 0x1E
    #define T_MIN_MSB 0x1F
    #define T_MIN_LSB 0x20
    #define P_MAX_MSB 0x21
    #define P_MAX_CSB 0x22
    #define P_MAX_LSB 0x23
    #define T_MAX_MSB 0x24
    #define T_MAX_LSB 0x25
    #define CTRL_REG1 0x26
    #define CTRL_REG2 0x27
    #define CTRL_REG3 0x28
    #define CTRL_REG4 0x29
    #define CTRL_REG5 0x2A
    #define OFF_P 0x2B
    #define OFF_T 0x2C
    #define OFF_H 0x2D
    #define MPL3115A2_ADDRESS 0xC0 // 7-bit I2C address
    #CONST
    scl := $PA10
    sda := $PA11
    true := 1
    false := 0
    high := 1
    low := 0
    #END
    
    func main()
    var a;
    
    gfx_ScreenMode(LANDSCAPE) ; // change manually if orientation change
    
    //Setup
    setOverSampleRate(7);
    setModeAltimeter();
    setModeActive();
    
    repeat
    //The loop just reads all registers and displays them on screen
    print (i2cReadReg(MPL3115A2_ADDRESS,a)," ");
    a++;
    if (a==0x2E)
    a:=0;
    gfx_MoveTo(1,1);
    endif
    forever
    
    endfunc
    
    
    func setModeActive()
    var tempSetting;
    tempSetting:=i2cReadReg(MPL3115A2_ADDRESS,CTRL_REG1);
    tempSetting |= (1<<0);
    i2cWriteReg(MPL3115A2_ADDRESS,CTRL_REG1, tempSetting);
    endfunc
    
    func setModeStandby()
    var tempSetting;
    tempSetting:=i2cReadReg(MPL3115A2_ADDRESS,CTRL_REG1);
    tempSetting &= ~(1<<0); //Clear SBYB bit for Standby mode
    i2cWriteReg(MPL3115A2_ADDRESS,CTRL_REG1, tempSetting);
    endfunc
    
    func toggleOneShot ()
    var tempSetting;
    tempSetting:=i2cReadReg(MPL3115A2_ADDRESS,CTRL_REG1);
    tempSetting &= ~(1<<1);
    i2cWriteReg(MPL3115A2_ADDRESS,CTRL_REG1, tempSetting);
    tempSetting:=i2cReadReg(MPL3115A2_ADDRESS,CTRL_REG1);
    tempSetting |= ~(1<<1);
    i2cWriteReg(MPL3115A2_ADDRESS,CTRL_REG1, tempSetting);
    endfunc
    
    func enableEventFlags()
    i2cWriteReg(MPL3115A2_ADDRESS,PT_DATA_CFG, 0x07);
    endfunc
    
    func setOverSampleRate(var sampleRate)
    var private tempSetting;
    if(sampleRate > 7) sampleRate := 7; //OS cannot be larger than 0b.0111
    sampleRate <<= 3; //Align it for the CTRL_REG1 register
    tempSetting:=i2cReadReg(MPL3115A2_ADDRESS,CTRL_REG1);
    tempSetting &= 0b11000111; //Clear out old OS bits
    tempSetting |= sampleRate; //Mask in new OS bits
    i2cWriteReg(MPL3115A2_ADDRESS,CTRL_REG1, tempSetting);
    endfunc
    
    
    func setModeAltimeter()
    var tempSetting;
    tempSetting:=i2cReadReg(MPL3115A2_ADDRESS,CTRL_REG1);
    tempSetting |= (1<<7);
    i2cWriteReg(MPL3115A2_ADDRESS,CTRL_REG1,tempSetting);
    endfunc
    
    func i2cStart()
    pin_HI(scl);
    pin_HI(sda);
    i2cWait();
    pin_LO(sda);
    i2cWait();
    pin_LO(scl);
    endfunc
    
    func i2cStop ()
    pin_LO(sda);
    pin_HI(scl);
    i2cWait();
    pin_HI(sda);
    i2cWait();
    pin_LO(scl);
    endfunc
    
    func i2cBang(var databyte)
    var b := 128;
    while (b>0)
    if (databyte&b)
    pin_HI(sda);
    pin_HI(scl);
    i2cWait();
    pin_LO(scl);
    i2cWait();
    else
    pin_LO(sda);
    pin_HI(scl);
    i2cWait();
    pin_LO(scl);
    i2cWait();
    endif
    b := b>>1;
    wend
    pin_Set(PIN_INP, sda);
    i2cWait();
    pin_HI(scl);
    i2cWait();
    var ack;
    ack:=pin_Read(sda);
    pin_LO(scl);
    return ack;
    endfunc
    
    func i2cReadByte()
    var private databyte;
    databyte:=0;
    pin_Set(PIN_INP,sda);
    var a:=8;
    while (a>0)
    pin_HI(scl);
    i2cWait();
    a--;
    databyte +=pin_Read(sda)<<a;
    pin_LO(scl);
    i2cWait();
    wend
    i2cAck();
    //print ("Read ",databyte);
    return databyte;
    endfunc
    
    func i2cWait()
    var a;
    while (a<1)
    a++;
    wend
    a:=0;
    endfunc
    
    func i2cAck()
    pin_LO(scl);
    pin_HI(sda);
    pin_HI(scl);
    i2cWait();
    pin_LO(scl);
    pin_LO(sda);
    pin_Set(PIN_INP,sda);
    endfunc
    
    func i2cReadReg(var adr,var reg)
    var private databyte;
    i2cStart();
    i2cBang(adr);
    i2cBang(reg);
    i2cStart();
    i2cBang(adr+1);
    databyte:=(i2cReadByte());
    i2cStop();
    return databyte;
    endfunc
    
    func i2cWriteReg(var adr,var reg,var databyte)
    i2cStart();
    i2cBang(adr);
    i2cBang(reg);
    i2cBang(databyte);
    i2cStop();
    endfunc
    Also here's some code for calculating altitude in feet. If you want meters just remove the line multiplying by 3.28.

    Code:
    func main()
    
        gfx_ScreenMode(LANDSCAPE) ; // change manually if orientation change
    
        //Setup
        setOverSampleRate(7);
        setModeAltimeter();
        setModeActive();
    
        repeat
    
      var msb,floatLsb[2],lsb,csb,altitude,floatAltitude[2];
    
        msb:=i2cReadReg(MPL3115A2_ADDRESS,OUT_P_MSB);
        csb:=i2cReadReg(MPL3115A2_ADDRESS,OUT_P_CSB);
        lsb:=i2cReadReg(MPL3115A2_ADDRESS,OUT_P_LSB);
        lsb := (lsb>>4);
        altitude := (( (msb << 8) | csb));
        flt_ITOF (floatAltitude,altitude);
        flt_ITOF(floatLsb,lsb);
        flt_DIV(floatLsb,floatLsb,"16");
        flt_MUL(floatAltitude,floatAltitude,"3.28");
        flt_ADD(floatAltitude,floatAltitude,floatLsb);
        flt_PRINT(floatAltitude, "Altitude: %f Ft");
        gfx_MoveTo(1,1);
        forever
    
    endfunc
    Last edited by jchowdy; 14 November 2014, 07:02 AM.
    J.Dyess

  • #2
    Thanks for that, we hope to have a codebase up and running soon that users can contribute this sort of stuff too.
    Mark

    Comment


    • #3
      A codebase would be awesome!
      J.Dyess

      Comment

      Working...
      X