HMC6352 Library
HMC6352.cpp
- Committer:
- richardparker
- Date:
- 2010-04-29
- Revision:
- 2:dc4867624d5a
- Parent:
- 1:1f500fa755c8
File content as of revision 2:dc4867624d5a:
// Copyright 2009 Richard Parker #include "mbed.h" #include "HMC6352.h" // Misc defines. #define HMC6352_DEFAULT_ADDRESS 0x42 // Masks. #define HMC6352_OP_MODE_MASK 0x03 #define HMC6352_OP_FREQ_MASK 0x60 #define HMC6352_OP_AUTO_MASK 0x10 // Register addresses. #define HMC6352_ADDRESS_ADDRESS 0x00 #define HMC6352_XO_MSB_ADDRESS 0x01 #define HMC6352_XO_LSB_ADDRESS 0x02 #define HMC6352_YO_MSB_ADDRESS 0x03 #define HMC6352_YO_LSB_ADDRESS 0x04 #define HMC6352_TIME_DELAY_ADDRESS 0x05 #define HMC6352_SUMMING_ADDRESS 0x06 #define HMC6352_VERSION_ADDRESS 0x07 #define HMC6352_OPERATION_ADDRESS 0x08 #define HMC6352_OUTPUT_REGISTER 0x4E #define HMC6352_OPERATION_REGISTER 0x74 // Commands for HMC6352. #define HMC6352_WRITE_EEPROM 0x77 // 'w' #define HMC6352_READ_EEPROM 0x72 // 'r' #define HMC6352_WRITE_RAM 0x47 // 'G' #define HMC6352_READ_RAM 0x67 // 'g' #define HMC6352_WAKE_UP 0x57 // 'W' #define HMC6352_SLEEP 0x53 // 'S' #define HMC6352_RESET 0x4F // 'O' #define HMC6352_START_CAL 0x43 // 'C' #define HMC6352_END_CAL 0x45 // 'E' #define HMC6352_SAVE_OPERATION 0x4C // 'L' #define HMC6352_RETRIEVE_HEADING 0x41 // 'A' HMC6352::HMC6352(PinName sda, PinName scl) : _i2c(sda, scl), _address(HMC6352_DEFAULT_ADDRESS) { // Set the frequency of the transfers in Hz for HMC6352 is 100000 Hz. _i2c.frequency(100000); } HMC6352::~HMC6352() { } char HMC6352::getVersion() { // Read the version number of the chip will be above 0x00 if it // is a production chip. _readFromMemory(HMC6352_VERSION_ADDRESS, true); return _buffer[0]; } void HMC6352::setVersion(const char version) { // Write the version number to the chip. _writeToMemory(HMC6352_VERSION_ADDRESS, version, true); } char HMC6352::getTimeDelay() { // Read the time delay _readFromMemory(HMC6352_TIME_DELAY_ADDRESS, true); return _buffer[0]; } void HMC6352::setTimeDelay(const char delay) { // Write the time delay to the chip. _writeToMemory(HMC6352_TIME_DELAY_ADDRESS, delay, true); } char HMC6352::getSumming() { // Read the number of summing samples. _readFromMemory(HMC6352_SUMMING_ADDRESS, true); return _buffer[0]; } void HMC6352::setSumming(const char samples) { // Write the number of summing samples to the chip. _writeToMemory(HMC6352_SUMMING_ADDRESS, samples, true); } float HMC6352::getHeading() { // Send the retrieve heading command. _buffer[0] = HMC6352_RETRIEVE_HEADING; _i2c.write(this->address(), _buffer, 1); // Retrieve takes 6000us. wait_us(6000); // As soon as the rerieve command has been sent read the result read // commands only return 2 bytes. _clearBuffer(); _i2c.read(this->address(), _buffer, 2); return _bufferToHeading(); } HMC6352::Mode HMC6352::getMode() { // Read the operation mode. _readFromMemory(HMC6352_OPERATION_REGISTER, false); // Buffer now contains the op mode register, mask to get values. int opmode = _buffer[0]; opmode = opmode & HMC6352_OP_MODE_MASK; // Convert the value into the mode. switch (opmode) { case 0x0: return HMC6352::Standby; case 0x1: return HMC6352::Query; case 0x2: return HMC6352::Continuous; default: return HMC6352::None; } } void HMC6352::setMode(HMC6352::Mode mode) { _readFromMemory(HMC6352_OPERATION_REGISTER, false); switch (mode) { case HMC6352::Standby: _writeToMemory(HMC6352_OPERATION_REGISTER, (_buffer[0] & 0xFC) | 0x0, false); break; case HMC6352::Query: _writeToMemory(HMC6352_OPERATION_REGISTER, (_buffer[0] & 0xFC) | 0x1, false); break; case HMC6352::Continuous: _writeToMemory(HMC6352_OPERATION_REGISTER, (_buffer[0] & 0xFC) | 0x2, false); break; default: return; } } HMC6352::Output HMC6352::getOutput() { // Read the output mode from RAM _readFromMemory(HMC6352_OUTPUT_REGISTER, false); // Buffer now contains the output register. int output = _buffer[0]; // Convert the value into the mode. switch (output) { case 0x0: return HMC6352::Heading; case 0x1: return HMC6352::RawX; case 0x2: return HMC6352::RawY; case 0x3: return HMC6352::X; case 0x4: return HMC6352::Y; default: return HMC6352::Unknown; } } void HMC6352::setOutput(HMC6352::Output output) { switch (output) { case HMC6352::Heading: _writeToMemory(HMC6352_OUTPUT_REGISTER, 0x0, false); break; case HMC6352::RawX: _writeToMemory(HMC6352_OUTPUT_REGISTER, 0x1, false); break; case HMC6352::RawY: _writeToMemory(HMC6352_OUTPUT_REGISTER, 0x2, false); break; case HMC6352::X: _writeToMemory(HMC6352_OUTPUT_REGISTER, 0x3, false); break; case HMC6352::Y: _writeToMemory(HMC6352_OUTPUT_REGISTER, 0x4, false); break; default: return; } } void HMC6352::calibrate(int delay) { startCalibrate(); // Now wait an optimal 20s in which two full turns should be // made of the compass to gather enough data, see page 7 of // the data sheet. wait(delay); endCalibrate(); } void HMC6352::startCalibrate() { // Send the enter calibrate command. _buffer[0] = HMC6352_START_CAL; _i2c.write(this->address(), _buffer, 1); // Enter takes 10us. wait_us(10); } void HMC6352::endCalibrate() { // Send the exit calibrate command. _buffer[0] = HMC6352_END_CAL; _i2c.write(this->address(), _buffer, 1); // Enter takes 14000us. wait_us(14000); } void HMC6352::saveOperation() { // Send the enter calibrate command. _buffer[0] = HMC6352_SAVE_OPERATION; _i2c.write(this->address(), _buffer, 1); // Save takes 125us. wait_us(125); } void HMC6352::reset() { // Send the reset command. _buffer[0] = HMC6352_RESET; _i2c.write(this->address(), _buffer, 1); // Reset takes 6000us. wait_us(6000); } void HMC6352::wakeUp() { // Send the wakeup command. _buffer[0] = HMC6352_WAKE_UP; _i2c.write(this->address(), _buffer, 1); wait_us(100); } void HMC6352::goToSleep() { // Send the reset command. _buffer[0] = HMC6352_SLEEP; _i2c.write(this->address(), _buffer, 1); wait_us(10); } void HMC6352::_readFromMemory(const char address, const bool eeprom) { char command; // Decide what the command should be (either read from eeprom or // currently loaded memory). if (eeprom == true) { command = HMC6352_READ_EEPROM; } else { command = HMC6352_READ_RAM; } // Send the read command to the current address (commands are always // two bytes long). _buffer[0] = command; _buffer[1] = address; _i2c.write(this->address(), _buffer, 2); wait_us(70); // As soon as the read command has been sent read the result read // commands only return 1 byte. _clearBuffer(); _i2c.read(this->address(), _buffer, 1); } void HMC6352::_writeToMemory(const char address, const char data, const bool eeprom) { char command; // Decide what the command should be (either write to eeprom or // currently loaded memory). if (eeprom == true) { command = HMC6352_WRITE_EEPROM; } else { command = HMC6352_WRITE_RAM; } // Send the write data to the current address (commands are always // three bytes long). _buffer[0] = command; _buffer[1] = address; _buffer[2] = data; _i2c.write(this->address(), _buffer, 3); wait_us(70); } void HMC6352::_clearBuffer() { // Set both buffer bytes to null. _buffer[0] = 0x0; _buffer[1] = 0x0; _buffer[2] = 0x0; } float HMC6352::_bufferToHeading() { // The heading is returned as a 16 bit number with the msb in the first // byte and the lsb in the next byte. return (((_buffer[0] << 8) + _buffer[1])/10.0); }