software i2c: error when compiling function(byte*) in a library

I am trying to place the example code from SoftI2CMaster/examples/MMA8452Q_Example_SoftI2C at master · todbot/SoftI2CMaster · GitHub into a library so that i can call the functions in my code, rather than have them cluttering it up inline.

I have been following the tutorial http://arduino.cc/en/Hacking/LibraryTutorial, but have got stuck at the following compile error:

"Arduino\libraries\MMA8452Q_SoftI2C\MMA8452Q_SoftI2C.cpp: In member function 'void MMA8452Q_SoftI2C::readRegisters(byte, int, byte*)':"

The code responsible for this error is here:

/* Read i registers sequentially, starting at address 
   into the dest byte array */
void MMA8452Q_SoftI2C::readRegisters(byte address, int i, byte * dest) 
{
    i2c.beginTransmission( 0x1D );
    i2c.send( address );
    i2c.endTransmission();

    i2c.requestFrom( 0x1D );
    int j;
    for( j=0; j<i-1; j++) {
        dest[j] = i2c.receive();
    }
    dest[j+1] = i2c.receiveLast();
    i2c.endTransmission();

}

So my question: why can i delcare this function inline, but not in a library?

I think it might be something to do with the "i2c" instance, which is created like so in the inline code:

SoftI2CMaster i2c = SoftI2CMaster(sdaPin, sdaPin, 0);

So, I tried to generate it in the library like this:

MMA8452Q_SoftI2C::MMA8452Q_SoftI2C(int sdaPin, int sclPin)
{
	SoftI2CMaster i2c = SoftI2CMaster(sdaPin, sdaPin, 0);
}

...with "i2c initialised as a public class variable in the header file, but i am unsure if it is working.

So my question: why can i delcare this function inline, but not in a library?

You can put that function in a library.

So, I tried to generate it in the library like this:

MMA8452Q_SoftI2C::MMA8452Q_SoftI2C(int sdaPin, int sclPin)

{
SoftI2CMaster i2c = SoftI2CMaster(sdaPin, sdaPin, 0);
}



...with "i2c initialised as a public class variable in the header file, but i am unsure if it is working.

In that snippet i2c is NOT a public class variable. It is a local variable - local to the constructor.

You need a public class variable that is value at the time your constructor is called, not valued in your constructor.

MMA8452Q_SoftI2C::MMA8452Q_SoftI2C(int sdaPin, int sclPin), i2c(sdaPin, sdaPin, 0)
{
}

Thanks for your reply. I do not understand how your code works, since it makes no reference to the softI2CMaster.h library, which is where i2c must be generated.

Anyhow, I replaced the declaration in the .cpp file and got the following errors:

MMA8452Q_SoftI2C\MMA8452Q_SoftI2C.cpp:11: error: declaration of 'MMA8452Q_SoftI2C::MMA8452Q_SoftI2C(int, int)' outside of class is not definition
MMA8452Q_SoftI2C\MMA8452Q_SoftI2C.cpp:11: error: expected identifier before numeric constant
MMA8452Q_SoftI2C\MMA8452Q_SoftI2C.cpp:11: error: expected ',' or '...' before numeric constant
MMA8452Q_SoftI2C\MMA8452Q_SoftI2C.cpp:12: error: a function-definition is not allowed here before '{' token

My full code for the library is as follows:

#include <Arduino.h>
#include <MMA8452Q_SoftI2C.h>
#include <SoftI2CMaster.h>

MMA8452Q_SoftI2C::MMA8452Q_SoftI2C(int sdaPin, int sclPin), i2c(sdaPin, sdaPin, 0)
{
}


/* Initialize the MMA8452 registers 
   See the many application notes for more info on setting 
   all of these registers:
   http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MMA8452Q
   
   Feel free to modify any values, these are settings that work well for me.
*/
void MMA8452Q_SoftI2C::initMMA8452(byte fsr, byte dataRate)
{
  MMA8452Standby();  // Must be in standby to change registers
  
  /* Set up the full scale range to 2, 4, or 8g. */
  if ((fsr==2)||(fsr==4)||(fsr==8))
    writeRegister(0x0E, fsr >> 2);  
  else
    writeRegister(0x0E, 0);
  /* Setup the 3 data rate bits, from 0 to 7 */
  writeRegister(0x2A, readRegister(0x2A) & ~(0x38));
  if (dataRate <= 7)
    writeRegister(0x2A, readRegister(0x2A) | (dataRate << 3));  
   
  MMA8452Active();  // Set to active to start reading
}

/* Sets the MMA8452 to standby mode.
   It must be in standby to change most register settings */
void MMA8452Q_SoftI2C::MMA8452Standby()
{
  byte c = readRegister(0x2A);
  writeRegister(0x2A, c & ~(0x01));
}

/* Sets the MMA8452 to active mode.
   Needs to be in this mode to output data */
void MMA8452Q_SoftI2C::MMA8452Active()
{
  byte c = readRegister(0x2A);
  writeRegister(0x2A, c | 0x01);
}

/* Read i registers sequentially, starting at address 
   into the dest byte arra */
void MMA8452Q_SoftI2C::readRegisters(byte address, int i, byte * dest) 
{
    i2c.beginTransmission( 0x1D );
    i2c.send( address );
    i2c.endTransmission();

    i2c.requestFrom( 0x1D );
    int j;
    for( j=0; j<i-1; j++) {
        dest[j] = i2c.receive();
    }
    dest[j+1] = i2c.receiveLast();
    i2c.endTransmission();

}

 // read a single byte from address and return it as a byte 
byte MMA8452Q_SoftI2C::readRegister(uint8_t address)
{
    byte data;
  
    i2c.beginTransmission( 0x1D );
    i2c.send( address );
    i2c.endTransmission();

    i2c.requestFrom( 0x1D );
    data = i2c.receiveLast();
    i2c.endTransmission();

    return data;
}


// Writes a single byte (data) into address 
void MMA8452Q_SoftI2C::writeRegister(unsigned char address, unsigned char data)
{
    i2c.beginTransmission( 0x1D );
    i2c.send( address );
    i2c.send( data );
    i2c.endTransmission();
}