Here's code I used. Make sure that you have the Z-axis oriented so that it is vertical or experiencing 1G since the calibration works best this way.
void CMMA7455::CalibrateSensor()
{
#define AVG_READS 64
int err;
m_I2C.ModuleWriteByte(GSENSOR,MCTL_REGISTER,MCTL_MODE0+MCTL_GLVL0);
int x,y,z;
long xAvg,yAvg,zAvg;
xAvg=yAvg=zAvg=0;
int lastXOffset=0;
int lastYOffset=0;
int lastZOffset=0;
SetXAxisOffset(lastXOffset); TRACE(_T("Last X Offset= %i\n"),lastXOffset);
SetYAxisOffset(lastYOffset); TRACE(_T("Last Y Offset= %i\n"),lastYOffset);
SetZAxisOffset(lastZOffset); TRACE(_T("Last Z Offset= %i\n"),lastZOffset);
int loop=0;
do
{
xAvg=yAvg=zAvg=0;
// Read the axes multiple times and average;
for (int i=0; i<AVG_READS;i++)
{
signed int data;
err=ReadXAxis(&data);xAvg+=data;
err=ReadYAxis(&data);yAvg+=data;
err=ReadZAxis(&data);zAvg+=data;
}
x=int(xAvg>>6);
y=int(yAvg>>6);
z=int(zAvg>>6);
// Calculate the offset.
lastXOffset=lastXOffset+(x*-2);
lastYOffset=lastYOffset+(y*-2);
lastZOffset=lastZOffset+((64-z)*2);
//Set the offset.
SetXAxisOffset(lastXOffset); TRACE(_T("Last X Offset= %i\n"),lastXOffset);
SetYAxisOffset(lastYOffset); TRACE(_T("Last Y Offset= %i\n"),lastYOffset);
SetZAxisOffset(lastZOffset); TRACE(_T("Last Z Offset= %i\n"),lastZOffset);
// Remeasure the values
xAvg=yAvg=zAvg=0;
for (int i=0; i<=AVG_READS;i++)
{
signed int data;
err=ReadXAxis(&data);xAvg+=data;
err=ReadYAxis(&data);yAvg+=data;
err=ReadZAxis(&data);zAvg+=data;
}
x=int(xAvg>>6);
y=int(yAvg>>6);
z=int(zAvg>>6);
loop++;
}
while( ((abs(x)>2) ||(abs(y)>2)||(abs(z-64)>2))&& (loop<10) ) ;
}
I'll leave the other functions as an exercise for the reader. I assume you can already read and write registers on the device.