// i2c slave addresses
#define HMC5883L_WRT_ADDR  0x3C
#define HMC5883L_READ_ADDR 0x3D

// Register addresses
#define HMC5883L_CFG_A_REG 0x00
#define HMC5883L_CFG_B_REG 0x01
#define HMC5883L_MODE_REG  0x02
#define HMC5883L_X_MSB_REG 0x03

//------------------------------
// Low level routines
//------------------------------
void hmc5883l_write_reg(int8 reg, int8 data)
{
i2c_start();
i2c_write(HMC5883L_WRT_ADDR);
i2c_write(reg);
i2c_write(data);
i2c_stop();
}

//------------------------------
int8 hmc5883l_read_reg(int8 reg)
{
int8 retval;

i2c_start();
i2c_write(HMC5883L_WRT_ADDR);
i2c_write(reg);
i2c_start();
i2c_write(HMC5883L_READ_ADDR);
retval = i2c_read(0);
i2c_stop();

return(retval);
}

//------------------------------
typedef struct
{
signed int16 x;
signed int16 y;
signed int16 z;
}hmc5883l_result;

// This global structure holds the values read
// from the HMC5883L x,y,z registers.
hmc5883l_result compass = {0,0,0};

//------------------------------
void hmc5883l_read_data(void)
{
unsigned int8 x_lsb;
unsigned int8 x_msb;

unsigned int8 y_lsb;
unsigned int8 y_msb;

unsigned int8 z_lsb;
unsigned int8 z_msb;

i2c_start();
i2c_write(HMC5883L_WRT_ADDR);
i2c_write(HMC5883L_X_MSB_REG);  // Point to X-msb register
i2c_start();
i2c_write(HMC5883L_READ_ADDR);

x_msb = i2c_read();
x_lsb = i2c_read();

z_msb = i2c_read();
z_lsb = i2c_read();   

y_msb = i2c_read();
y_lsb = i2c_read(0); // do a NACK on last read

i2c_stop();
 
// Combine high and low bytes into 16-bit values.
compass.x = make16(x_msb, x_lsb);
compass.y = make16(y_msb, y_lsb);
compass.z = make16(z_msb, z_lsb);
}