HMC6352 Library

Committer:
richardparker
Date:
Thu Apr 29 19:26:30 2010 +0000
Revision:
2:dc4867624d5a
Parent:
1:1f500fa755c8

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
richardparker 0:78e66010e47b 1 // Copyright 2009 Richard Parker
richardparker 0:78e66010e47b 2
richardparker 0:78e66010e47b 3 #include "mbed.h"
richardparker 0:78e66010e47b 4 #include "HMC6352.h"
richardparker 0:78e66010e47b 5
richardparker 0:78e66010e47b 6 // Misc defines.
richardparker 0:78e66010e47b 7 #define HMC6352_DEFAULT_ADDRESS 0x42
richardparker 0:78e66010e47b 8
richardparker 0:78e66010e47b 9 // Masks.
richardparker 0:78e66010e47b 10 #define HMC6352_OP_MODE_MASK 0x03
richardparker 0:78e66010e47b 11 #define HMC6352_OP_FREQ_MASK 0x60
richardparker 0:78e66010e47b 12 #define HMC6352_OP_AUTO_MASK 0x10
richardparker 0:78e66010e47b 13
richardparker 0:78e66010e47b 14 // Register addresses.
richardparker 0:78e66010e47b 15 #define HMC6352_ADDRESS_ADDRESS 0x00
richardparker 0:78e66010e47b 16 #define HMC6352_XO_MSB_ADDRESS 0x01
richardparker 0:78e66010e47b 17 #define HMC6352_XO_LSB_ADDRESS 0x02
richardparker 0:78e66010e47b 18 #define HMC6352_YO_MSB_ADDRESS 0x03
richardparker 0:78e66010e47b 19 #define HMC6352_YO_LSB_ADDRESS 0x04
richardparker 0:78e66010e47b 20 #define HMC6352_TIME_DELAY_ADDRESS 0x05
richardparker 0:78e66010e47b 21 #define HMC6352_SUMMING_ADDRESS 0x06
richardparker 0:78e66010e47b 22 #define HMC6352_VERSION_ADDRESS 0x07
richardparker 0:78e66010e47b 23 #define HMC6352_OPERATION_ADDRESS 0x08
richardparker 0:78e66010e47b 24
richardparker 0:78e66010e47b 25 #define HMC6352_OUTPUT_REGISTER 0x4E
richardparker 0:78e66010e47b 26 #define HMC6352_OPERATION_REGISTER 0x74
richardparker 0:78e66010e47b 27
richardparker 0:78e66010e47b 28 // Commands for HMC6352.
richardparker 0:78e66010e47b 29 #define HMC6352_WRITE_EEPROM 0x77 // 'w'
richardparker 0:78e66010e47b 30 #define HMC6352_READ_EEPROM 0x72 // 'r'
richardparker 0:78e66010e47b 31 #define HMC6352_WRITE_RAM 0x47 // 'G'
richardparker 0:78e66010e47b 32 #define HMC6352_READ_RAM 0x67 // 'g'
richardparker 0:78e66010e47b 33 #define HMC6352_WAKE_UP 0x57 // 'W'
richardparker 0:78e66010e47b 34 #define HMC6352_SLEEP 0x53 // 'S'
richardparker 0:78e66010e47b 35 #define HMC6352_RESET 0x4F // 'O'
richardparker 0:78e66010e47b 36 #define HMC6352_START_CAL 0x43 // 'C'
richardparker 0:78e66010e47b 37 #define HMC6352_END_CAL 0x45 // 'E'
richardparker 0:78e66010e47b 38 #define HMC6352_SAVE_OPERATION 0x4C // 'L'
richardparker 0:78e66010e47b 39 #define HMC6352_RETRIEVE_HEADING 0x41 // 'A'
richardparker 0:78e66010e47b 40
richardparker 0:78e66010e47b 41 HMC6352::HMC6352(PinName sda, PinName scl)
richardparker 0:78e66010e47b 42 : _i2c(sda, scl),
richardparker 0:78e66010e47b 43 _address(HMC6352_DEFAULT_ADDRESS)
richardparker 0:78e66010e47b 44 {
richardparker 0:78e66010e47b 45 // Set the frequency of the transfers in Hz for HMC6352 is 100000 Hz.
richardparker 0:78e66010e47b 46 _i2c.frequency(100000);
richardparker 0:78e66010e47b 47 }
richardparker 0:78e66010e47b 48
richardparker 0:78e66010e47b 49 HMC6352::~HMC6352()
richardparker 0:78e66010e47b 50 {
richardparker 0:78e66010e47b 51 }
richardparker 0:78e66010e47b 52
richardparker 0:78e66010e47b 53 char HMC6352::getVersion()
richardparker 0:78e66010e47b 54 {
richardparker 0:78e66010e47b 55 // Read the version number of the chip will be above 0x00 if it
richardparker 0:78e66010e47b 56 // is a production chip.
richardparker 0:78e66010e47b 57 _readFromMemory(HMC6352_VERSION_ADDRESS, true);
richardparker 0:78e66010e47b 58 return _buffer[0];
richardparker 0:78e66010e47b 59 }
richardparker 0:78e66010e47b 60
richardparker 0:78e66010e47b 61 void HMC6352::setVersion(const char version)
richardparker 0:78e66010e47b 62 {
richardparker 0:78e66010e47b 63 // Write the version number to the chip.
richardparker 0:78e66010e47b 64 _writeToMemory(HMC6352_VERSION_ADDRESS, version, true);
richardparker 0:78e66010e47b 65 }
richardparker 0:78e66010e47b 66
richardparker 0:78e66010e47b 67 char HMC6352::getTimeDelay()
richardparker 0:78e66010e47b 68 {
richardparker 0:78e66010e47b 69 // Read the time delay
richardparker 0:78e66010e47b 70 _readFromMemory(HMC6352_TIME_DELAY_ADDRESS, true);
richardparker 0:78e66010e47b 71 return _buffer[0];
richardparker 0:78e66010e47b 72 }
richardparker 0:78e66010e47b 73
richardparker 0:78e66010e47b 74 void HMC6352::setTimeDelay(const char delay)
richardparker 0:78e66010e47b 75 {
richardparker 0:78e66010e47b 76 // Write the time delay to the chip.
richardparker 0:78e66010e47b 77 _writeToMemory(HMC6352_TIME_DELAY_ADDRESS, delay, true);
richardparker 0:78e66010e47b 78 }
richardparker 0:78e66010e47b 79
richardparker 0:78e66010e47b 80 char HMC6352::getSumming()
richardparker 0:78e66010e47b 81 {
richardparker 0:78e66010e47b 82 // Read the number of summing samples.
richardparker 0:78e66010e47b 83 _readFromMemory(HMC6352_SUMMING_ADDRESS, true);
richardparker 0:78e66010e47b 84 return _buffer[0];
richardparker 0:78e66010e47b 85 }
richardparker 0:78e66010e47b 86
richardparker 0:78e66010e47b 87 void HMC6352::setSumming(const char samples)
richardparker 0:78e66010e47b 88 {
richardparker 0:78e66010e47b 89 // Write the number of summing samples to the chip.
richardparker 0:78e66010e47b 90 _writeToMemory(HMC6352_SUMMING_ADDRESS, samples, true);
richardparker 0:78e66010e47b 91 }
richardparker 0:78e66010e47b 92
richardparker 0:78e66010e47b 93 float HMC6352::getHeading()
richardparker 0:78e66010e47b 94 {
richardparker 0:78e66010e47b 95 // Send the retrieve heading command.
richardparker 0:78e66010e47b 96 _buffer[0] = HMC6352_RETRIEVE_HEADING;
richardparker 0:78e66010e47b 97 _i2c.write(this->address(), _buffer, 1);
richardparker 0:78e66010e47b 98 // Retrieve takes 6000us.
richardparker 0:78e66010e47b 99 wait_us(6000);
richardparker 0:78e66010e47b 100
richardparker 0:78e66010e47b 101 // As soon as the rerieve command has been sent read the result read
richardparker 0:78e66010e47b 102 // commands only return 2 bytes.
richardparker 0:78e66010e47b 103 _clearBuffer();
richardparker 0:78e66010e47b 104 _i2c.read(this->address(), _buffer, 2);
richardparker 0:78e66010e47b 105
richardparker 0:78e66010e47b 106 return _bufferToHeading();
richardparker 0:78e66010e47b 107 }
richardparker 0:78e66010e47b 108
richardparker 0:78e66010e47b 109 HMC6352::Mode HMC6352::getMode()
richardparker 0:78e66010e47b 110 {
richardparker 0:78e66010e47b 111 // Read the operation mode.
richardparker 0:78e66010e47b 112 _readFromMemory(HMC6352_OPERATION_REGISTER, false);
richardparker 0:78e66010e47b 113
richardparker 0:78e66010e47b 114 // Buffer now contains the op mode register, mask to get values.
richardparker 0:78e66010e47b 115 int opmode = _buffer[0];
richardparker 0:78e66010e47b 116 opmode = opmode & HMC6352_OP_MODE_MASK;
richardparker 0:78e66010e47b 117
richardparker 0:78e66010e47b 118 // Convert the value into the mode.
richardparker 0:78e66010e47b 119 switch (opmode)
richardparker 0:78e66010e47b 120 {
richardparker 0:78e66010e47b 121 case 0x0:
richardparker 0:78e66010e47b 122 return HMC6352::Standby;
richardparker 0:78e66010e47b 123 case 0x1:
richardparker 0:78e66010e47b 124 return HMC6352::Query;
richardparker 0:78e66010e47b 125 case 0x2:
richardparker 0:78e66010e47b 126 return HMC6352::Continuous;
richardparker 0:78e66010e47b 127 default:
richardparker 0:78e66010e47b 128 return HMC6352::None;
richardparker 0:78e66010e47b 129 }
richardparker 0:78e66010e47b 130 }
richardparker 0:78e66010e47b 131
richardparker 0:78e66010e47b 132 void HMC6352::setMode(HMC6352::Mode mode)
richardparker 0:78e66010e47b 133 {
richardparker 0:78e66010e47b 134 _readFromMemory(HMC6352_OPERATION_REGISTER, false);
richardparker 0:78e66010e47b 135
richardparker 0:78e66010e47b 136 switch (mode)
richardparker 0:78e66010e47b 137 {
richardparker 0:78e66010e47b 138 case HMC6352::Standby:
richardparker 0:78e66010e47b 139 _writeToMemory(HMC6352_OPERATION_REGISTER, (_buffer[0] & 0xFC) | 0x0, false);
richardparker 0:78e66010e47b 140 break;
richardparker 0:78e66010e47b 141 case HMC6352::Query:
richardparker 0:78e66010e47b 142 _writeToMemory(HMC6352_OPERATION_REGISTER, (_buffer[0] & 0xFC) | 0x1, false);
richardparker 0:78e66010e47b 143 break;
richardparker 0:78e66010e47b 144 case HMC6352::Continuous:
richardparker 0:78e66010e47b 145 _writeToMemory(HMC6352_OPERATION_REGISTER, (_buffer[0] & 0xFC) | 0x2, false);
richardparker 0:78e66010e47b 146 break;
richardparker 0:78e66010e47b 147 default:
richardparker 0:78e66010e47b 148 return;
richardparker 0:78e66010e47b 149 }
richardparker 0:78e66010e47b 150 }
richardparker 0:78e66010e47b 151
richardparker 0:78e66010e47b 152 HMC6352::Output HMC6352::getOutput()
richardparker 0:78e66010e47b 153 {
richardparker 0:78e66010e47b 154 // Read the output mode from RAM
richardparker 0:78e66010e47b 155 _readFromMemory(HMC6352_OUTPUT_REGISTER, false);
richardparker 0:78e66010e47b 156
richardparker 0:78e66010e47b 157 // Buffer now contains the output register.
richardparker 0:78e66010e47b 158 int output = _buffer[0];
richardparker 0:78e66010e47b 159
richardparker 0:78e66010e47b 160 // Convert the value into the mode.
richardparker 0:78e66010e47b 161 switch (output)
richardparker 0:78e66010e47b 162 {
richardparker 0:78e66010e47b 163 case 0x0:
richardparker 0:78e66010e47b 164 return HMC6352::Heading;
richardparker 0:78e66010e47b 165 case 0x1:
richardparker 0:78e66010e47b 166 return HMC6352::RawX;
richardparker 0:78e66010e47b 167 case 0x2:
richardparker 0:78e66010e47b 168 return HMC6352::RawY;
richardparker 0:78e66010e47b 169 case 0x3:
richardparker 0:78e66010e47b 170 return HMC6352::X;
richardparker 0:78e66010e47b 171 case 0x4:
richardparker 0:78e66010e47b 172 return HMC6352::Y;
richardparker 0:78e66010e47b 173 default:
richardparker 0:78e66010e47b 174 return HMC6352::Unknown;
richardparker 0:78e66010e47b 175 }
richardparker 0:78e66010e47b 176 }
richardparker 0:78e66010e47b 177
richardparker 0:78e66010e47b 178 void HMC6352::setOutput(HMC6352::Output output)
richardparker 0:78e66010e47b 179 {
richardparker 0:78e66010e47b 180 switch (output)
richardparker 0:78e66010e47b 181 {
richardparker 0:78e66010e47b 182 case HMC6352::Heading:
richardparker 0:78e66010e47b 183 _writeToMemory(HMC6352_OUTPUT_REGISTER, 0x0, false);
richardparker 0:78e66010e47b 184 break;
richardparker 0:78e66010e47b 185 case HMC6352::RawX:
richardparker 0:78e66010e47b 186 _writeToMemory(HMC6352_OUTPUT_REGISTER, 0x1, false);
richardparker 0:78e66010e47b 187 break;
richardparker 0:78e66010e47b 188 case HMC6352::RawY:
richardparker 0:78e66010e47b 189 _writeToMemory(HMC6352_OUTPUT_REGISTER, 0x2, false);
richardparker 0:78e66010e47b 190 break;
richardparker 0:78e66010e47b 191 case HMC6352::X:
richardparker 0:78e66010e47b 192 _writeToMemory(HMC6352_OUTPUT_REGISTER, 0x3, false);
richardparker 0:78e66010e47b 193 break;
richardparker 0:78e66010e47b 194 case HMC6352::Y:
richardparker 0:78e66010e47b 195 _writeToMemory(HMC6352_OUTPUT_REGISTER, 0x4, false);
richardparker 0:78e66010e47b 196 break;
richardparker 0:78e66010e47b 197 default:
richardparker 0:78e66010e47b 198 return;
richardparker 0:78e66010e47b 199 }
richardparker 0:78e66010e47b 200 }
richardparker 0:78e66010e47b 201
richardparker 0:78e66010e47b 202 void HMC6352::calibrate(int delay)
richardparker 0:78e66010e47b 203 {
richardparker 1:1f500fa755c8 204 startCalibrate();
richardparker 1:1f500fa755c8 205
richardparker 1:1f500fa755c8 206 // Now wait an optimal 20s in which two full turns should be
richardparker 1:1f500fa755c8 207 // made of the compass to gather enough data, see page 7 of
richardparker 1:1f500fa755c8 208 // the data sheet.
richardparker 1:1f500fa755c8 209 wait(delay);
richardparker 1:1f500fa755c8 210
richardparker 1:1f500fa755c8 211 endCalibrate();
richardparker 1:1f500fa755c8 212 }
richardparker 1:1f500fa755c8 213
richardparker 1:1f500fa755c8 214 void HMC6352::startCalibrate()
richardparker 1:1f500fa755c8 215 {
richardparker 0:78e66010e47b 216 // Send the enter calibrate command.
richardparker 0:78e66010e47b 217 _buffer[0] = HMC6352_START_CAL;
richardparker 0:78e66010e47b 218 _i2c.write(this->address(), _buffer, 1);
richardparker 0:78e66010e47b 219 // Enter takes 10us.
richardparker 0:78e66010e47b 220 wait_us(10);
richardparker 1:1f500fa755c8 221 }
richardparker 1:1f500fa755c8 222
richardparker 1:1f500fa755c8 223 void HMC6352::endCalibrate()
richardparker 1:1f500fa755c8 224 {
richardparker 0:78e66010e47b 225 // Send the exit calibrate command.
richardparker 0:78e66010e47b 226 _buffer[0] = HMC6352_END_CAL;
richardparker 0:78e66010e47b 227 _i2c.write(this->address(), _buffer, 1);
richardparker 0:78e66010e47b 228 // Enter takes 14000us.
richardparker 0:78e66010e47b 229 wait_us(14000);
richardparker 0:78e66010e47b 230 }
richardparker 0:78e66010e47b 231
richardparker 0:78e66010e47b 232 void HMC6352::saveOperation()
richardparker 0:78e66010e47b 233 {
richardparker 0:78e66010e47b 234 // Send the enter calibrate command.
richardparker 0:78e66010e47b 235 _buffer[0] = HMC6352_SAVE_OPERATION;
richardparker 0:78e66010e47b 236 _i2c.write(this->address(), _buffer, 1);
richardparker 0:78e66010e47b 237 // Save takes 125us.
richardparker 0:78e66010e47b 238 wait_us(125);
richardparker 0:78e66010e47b 239 }
richardparker 0:78e66010e47b 240
richardparker 0:78e66010e47b 241 void HMC6352::reset()
richardparker 0:78e66010e47b 242 {
richardparker 0:78e66010e47b 243 // Send the reset command.
richardparker 0:78e66010e47b 244 _buffer[0] = HMC6352_RESET;
richardparker 0:78e66010e47b 245 _i2c.write(this->address(), _buffer, 1);
richardparker 0:78e66010e47b 246 // Reset takes 6000us.
richardparker 0:78e66010e47b 247 wait_us(6000);
richardparker 0:78e66010e47b 248 }
richardparker 0:78e66010e47b 249
richardparker 0:78e66010e47b 250 void HMC6352::wakeUp()
richardparker 0:78e66010e47b 251 {
richardparker 0:78e66010e47b 252 // Send the wakeup command.
richardparker 0:78e66010e47b 253 _buffer[0] = HMC6352_WAKE_UP;
richardparker 0:78e66010e47b 254 _i2c.write(this->address(), _buffer, 1);
richardparker 0:78e66010e47b 255 wait_us(100);
richardparker 0:78e66010e47b 256 }
richardparker 0:78e66010e47b 257
richardparker 0:78e66010e47b 258 void HMC6352::goToSleep()
richardparker 0:78e66010e47b 259 {
richardparker 0:78e66010e47b 260 // Send the reset command.
richardparker 0:78e66010e47b 261 _buffer[0] = HMC6352_SLEEP;
richardparker 0:78e66010e47b 262 _i2c.write(this->address(), _buffer, 1);
richardparker 0:78e66010e47b 263 wait_us(10);
richardparker 0:78e66010e47b 264 }
richardparker 0:78e66010e47b 265
richardparker 0:78e66010e47b 266 void HMC6352::_readFromMemory(const char address, const bool eeprom)
richardparker 0:78e66010e47b 267 {
richardparker 0:78e66010e47b 268 char command;
richardparker 0:78e66010e47b 269
richardparker 0:78e66010e47b 270 // Decide what the command should be (either read from eeprom or
richardparker 0:78e66010e47b 271 // currently loaded memory).
richardparker 0:78e66010e47b 272 if (eeprom == true)
richardparker 0:78e66010e47b 273 {
richardparker 0:78e66010e47b 274 command = HMC6352_READ_EEPROM;
richardparker 0:78e66010e47b 275 } else {
richardparker 0:78e66010e47b 276 command = HMC6352_READ_RAM;
richardparker 0:78e66010e47b 277 }
richardparker 0:78e66010e47b 278
richardparker 0:78e66010e47b 279 // Send the read command to the current address (commands are always
richardparker 0:78e66010e47b 280 // two bytes long).
richardparker 0:78e66010e47b 281 _buffer[0] = command;
richardparker 0:78e66010e47b 282 _buffer[1] = address;
richardparker 0:78e66010e47b 283 _i2c.write(this->address(), _buffer, 2);
richardparker 0:78e66010e47b 284 wait_us(70);
richardparker 0:78e66010e47b 285
richardparker 0:78e66010e47b 286 // As soon as the read command has been sent read the result read
richardparker 0:78e66010e47b 287 // commands only return 1 byte.
richardparker 0:78e66010e47b 288 _clearBuffer();
richardparker 0:78e66010e47b 289 _i2c.read(this->address(), _buffer, 1);
richardparker 0:78e66010e47b 290 }
richardparker 0:78e66010e47b 291
richardparker 0:78e66010e47b 292 void HMC6352::_writeToMemory(const char address, const char data, const bool eeprom)
richardparker 0:78e66010e47b 293 {
richardparker 0:78e66010e47b 294 char command;
richardparker 0:78e66010e47b 295
richardparker 0:78e66010e47b 296 // Decide what the command should be (either write to eeprom or
richardparker 0:78e66010e47b 297 // currently loaded memory).
richardparker 0:78e66010e47b 298 if (eeprom == true)
richardparker 0:78e66010e47b 299 {
richardparker 0:78e66010e47b 300 command = HMC6352_WRITE_EEPROM;
richardparker 0:78e66010e47b 301 } else {
richardparker 0:78e66010e47b 302 command = HMC6352_WRITE_RAM;
richardparker 0:78e66010e47b 303 }
richardparker 0:78e66010e47b 304
richardparker 0:78e66010e47b 305 // Send the write data to the current address (commands are always
richardparker 0:78e66010e47b 306 // three bytes long).
richardparker 0:78e66010e47b 307 _buffer[0] = command;
richardparker 0:78e66010e47b 308 _buffer[1] = address;
richardparker 0:78e66010e47b 309 _buffer[2] = data;
richardparker 0:78e66010e47b 310 _i2c.write(this->address(), _buffer, 3);
richardparker 0:78e66010e47b 311 wait_us(70);
richardparker 0:78e66010e47b 312 }
richardparker 0:78e66010e47b 313
richardparker 0:78e66010e47b 314 void HMC6352::_clearBuffer()
richardparker 0:78e66010e47b 315 {
richardparker 0:78e66010e47b 316 // Set both buffer bytes to null.
richardparker 0:78e66010e47b 317 _buffer[0] = 0x0;
richardparker 0:78e66010e47b 318 _buffer[1] = 0x0;
richardparker 0:78e66010e47b 319 _buffer[2] = 0x0;
richardparker 0:78e66010e47b 320 }
richardparker 0:78e66010e47b 321
richardparker 0:78e66010e47b 322 float HMC6352::_bufferToHeading()
richardparker 0:78e66010e47b 323 {
richardparker 0:78e66010e47b 324 // The heading is returned as a 16 bit number with the msb in the first
richardparker 0:78e66010e47b 325 // byte and the lsb in the next byte.
richardparker 0:78e66010e47b 326 return (((_buffer[0] << 8) + _buffer[1])/10.0);
richardparker 0:78e66010e47b 327 }