Driver for AK7451 Angle Senor(SPI).

Fork of AK7451 by AKM Development Platform

Committer:
masahikofukasawa
Date:
Fri Apr 28 20:31:42 2017 +0000
Revision:
3:1e0cfed43467
Parent:
1:536cf25b0eb4
release RevD7.014. Add register access.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
masahikofukasawa 0:56b554871e05 1 #include "ak7451.h"
masahikofukasawa 0:56b554871e05 2
masahikofukasawa 0:56b554871e05 3 // OPCODE Specification
masahikofukasawa 0:56b554871e05 4 #define AK7451_OPCODE_WRITE_EEPROM 0x01 // Able to write a data on EEPROM
masahikofukasawa 0:56b554871e05 5 #define AK7451_OPCODE_READ_EEPROM 0x02 // Able to read an EEPROM
masahikofukasawa 0:56b554871e05 6 #define AK7451_OPCODE_WRITE_REGISTER 0x03 // Able to write a data on register
masahikofukasawa 0:56b554871e05 7 #define AK7451_OPCODE_READ_REGISTER 0x04 // Able to read a register
masahikofukasawa 0:56b554871e05 8 #define AK7451_OPCODE_CHANGE_MODE 0x05 // Able to change mode
masahikofukasawa 0:56b554871e05 9 #define AK7451_OPCODE_ANGLE_MEASURE_CODE 0x08 // Able to read angle measure in user mode
masahikofukasawa 0:56b554871e05 10 #define AK7451_OPCODE_READ_ANGLE 0x09 // Able to read an angle data
masahikofukasawa 0:56b554871e05 11
masahikofukasawa 0:56b554871e05 12 // Register Address Map
masahikofukasawa 0:56b554871e05 13 #define AK7451_REG_ANG 0x00 // 12bit angle data
masahikofukasawa 0:56b554871e05 14 #define AK7451_REG_MAG 0x01 // Magnetic flux density strength(1LSB/mT)
masahikofukasawa 0:56b554871e05 15 #define AK7451_REG_CHMD 0x02 // For mode state
masahikofukasawa 0:56b554871e05 16 #define AK7451_REG_ERRMON 0x03 // This register will show what kind of error is.
masahikofukasawa 0:56b554871e05 17 #define AK7451_REG_ID1 0x04 // For ID data (EEPROM Only)
masahikofukasawa 0:56b554871e05 18 #define AK7451_REG_ID2 0x05 // For ID data (EEPROM Only)
masahikofukasawa 0:56b554871e05 19 #define AK7451_REG_ZP 0x06 // For set up angle zero point
masahikofukasawa 0:56b554871e05 20 #define AK7451_REG_RDABZ 0x07 // For set up "Rotation direction",
masahikofukasawa 0:56b554871e05 21 #define AK7451_REG_MLK 0x08 // For memory lock
masahikofukasawa 0:56b554871e05 22 #define AK7451_REG_ABNRM 0x09 // For set up abnormal detection disable
masahikofukasawa 0:56b554871e05 23 #define AK7451_REG_UVW 0x0A // For set up "UVW output enable disable"
masahikofukasawa 0:56b554871e05 24
masahikofukasawa 0:56b554871e05 25 #define AK7451_READ_ANGLE_STATE_MD 0x80
masahikofukasawa 0:56b554871e05 26 #define AK7451_READ_ANGLE_STATE_P1 0x40
masahikofukasawa 0:56b554871e05 27 #define AK7451_READ_ANGLE_STATE_P2 0x20
masahikofukasawa 0:56b554871e05 28 #define AK7451_READ_ANGLE_STATE_ER 0x10
masahikofukasawa 0:56b554871e05 29
masahikofukasawa 0:56b554871e05 30 #define AK7451_BIT_MASK_ABZ_E 0x80 // ABZ output enable
masahikofukasawa 0:56b554871e05 31 #define AK7451_BIT_MASK_UVW_E 0x40 // UVW output enable
masahikofukasawa 0:56b554871e05 32
masahikofukasawa 0:56b554871e05 33 #define AK7451_ABNORMAL_STATE_NORMAL 0x03 //
masahikofukasawa 0:56b554871e05 34
masahikofukasawa 0:56b554871e05 35 /**
masahikofukasawa 0:56b554871e05 36 * Constructor.
masahikofukasawa 0:56b554871e05 37 *
masahikofukasawa 0:56b554871e05 38 */
masahikofukasawa 0:56b554871e05 39 AK7451::AK7451(){
masahikofukasawa 0:56b554871e05 40 _spi = NULL;
masahikofukasawa 0:56b554871e05 41 _cs = NULL;
masahikofukasawa 0:56b554871e05 42 AK7451::operationMode = AK7451::AK7451_NORMAL_MODE;
masahikofukasawa 0:56b554871e05 43 }
masahikofukasawa 0:56b554871e05 44
masahikofukasawa 0:56b554871e05 45 /**
masahikofukasawa 0:56b554871e05 46 * Destructor.
masahikofukasawa 0:56b554871e05 47 *
masahikofukasawa 0:56b554871e05 48 */
masahikofukasawa 0:56b554871e05 49 AK7451::~AK7451(){
masahikofukasawa 0:56b554871e05 50 if (_spi) delete _spi;
masahikofukasawa 0:56b554871e05 51 if(_cs) delete _cs;
masahikofukasawa 0:56b554871e05 52 }
masahikofukasawa 0:56b554871e05 53
masahikofukasawa 0:56b554871e05 54 /**
masahikofukasawa 0:56b554871e05 55 * begin
masahikofukasawa 0:56b554871e05 56 *
masahikofukasawa 0:56b554871e05 57 * @param *spi pointer to SPI instance
masahikofukasawa 0:56b554871e05 58 * @param *cs pointer to DigitalOut instance for CS
masahikofukasawa 0:56b554871e05 59 */
masahikofukasawa 0:56b554871e05 60 void AK7451::begin(SPI *spi, DigitalOut *cs){
masahikofukasawa 0:56b554871e05 61 if (_spi) delete _spi;
masahikofukasawa 0:56b554871e05 62 _spi=spi;
masahikofukasawa 0:56b554871e05 63 if (_cs) delete _cs;
masahikofukasawa 0:56b554871e05 64 _cs=cs;
masahikofukasawa 0:56b554871e05 65 _cs->write(1);
masahikofukasawa 0:56b554871e05 66 }
masahikofukasawa 0:56b554871e05 67
masahikofukasawa 0:56b554871e05 68 /**
masahikofukasawa 0:56b554871e05 69 * Check the connection.
masahikofukasawa 0:56b554871e05 70 *
masahikofukasawa 0:56b554871e05 71 * @note Connection check is performed by reading a register which has a fixed value and verify it.
masahikofukasawa 0:56b554871e05 72 *
masahikofukasawa 0:56b554871e05 73 * @return Returns SUCCESS when succeeded, otherwise returns another code.
masahikofukasawa 0:56b554871e05 74 */
masahikofukasawa 0:56b554871e05 75 AK7451::Status AK7451::checkConnection() {
masahikofukasawa 0:56b554871e05 76 AK7451::Status status;
masahikofukasawa 0:56b554871e05 77
masahikofukasawa 0:56b554871e05 78 status = AK7451::setOperationMode(AK7451::AK7451_USER_MODE);
masahikofukasawa 0:56b554871e05 79 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 0:56b554871e05 80
masahikofukasawa 0:56b554871e05 81 char data[2];
masahikofukasawa 1:536cf25b0eb4 82 // read current mode
masahikofukasawa 0:56b554871e05 83 data[0] = 0x00;
masahikofukasawa 0:56b554871e05 84 data[1] = 0x00;
masahikofukasawa 0:56b554871e05 85 status = AK7451::readRegister(AK7451_REG_CHMD, data);
masahikofukasawa 0:56b554871e05 86 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 0:56b554871e05 87 if(data[0] != 0x05 || data[1] != 0x0F) return AK7451::ERROR;
masahikofukasawa 0:56b554871e05 88 return AK7451::SUCCESS;
masahikofukasawa 0:56b554871e05 89 }
masahikofukasawa 0:56b554871e05 90
masahikofukasawa 0:56b554871e05 91 /**
masahikofukasawa 0:56b554871e05 92 * Writes data to EEPROM on the device.
masahikofukasawa 0:56b554871e05 93 * @param address EEPROM address
masahikofukasawa 0:56b554871e05 94 * @param data data to be written
masahikofukasawa 0:56b554871e05 95 * @return Returns SUCCESS when succeeded, otherwise returns another.
masahikofukasawa 0:56b554871e05 96 */
masahikofukasawa 0:56b554871e05 97 AK7451::Status AK7451::writeEEPROM(char address, const char *data){
masahikofukasawa 0:56b554871e05 98 if(AK7451::operationMode != AK7451::AK7451_USER_MODE) return AK7451::ERROR_IN_NORMAL_MODE;
masahikofukasawa 0:56b554871e05 99 AK7451::Status status = AK7451::write(AK7451_OPCODE_WRITE_EEPROM, address, data);
masahikofukasawa 0:56b554871e05 100 wait(0.005); // Wait Wt=5msec(MAX)
masahikofukasawa 0:56b554871e05 101 return status;
masahikofukasawa 0:56b554871e05 102 }
masahikofukasawa 0:56b554871e05 103 /**
masahikofukasawa 0:56b554871e05 104 * Reads data from EEPROM on the device.
masahikofukasawa 0:56b554871e05 105 * @param address EEPROM address
masahikofukasawa 0:56b554871e05 106 * @param data data to read
masahikofukasawa 0:56b554871e05 107 * @return Returns SUCCESS when succeeded, otherwise returns another.
masahikofukasawa 0:56b554871e05 108 */
masahikofukasawa 0:56b554871e05 109 AK7451::Status AK7451::readEEPROM(char address, char *data){
masahikofukasawa 0:56b554871e05 110 if(AK7451::operationMode != AK7451::AK7451_USER_MODE) return AK7451::ERROR_IN_NORMAL_MODE;
masahikofukasawa 0:56b554871e05 111 AK7451::Status status = read(AK7451_OPCODE_READ_EEPROM, address, data);
masahikofukasawa 0:56b554871e05 112 return status;
masahikofukasawa 0:56b554871e05 113 }
masahikofukasawa 0:56b554871e05 114
masahikofukasawa 0:56b554871e05 115 /**
masahikofukasawa 0:56b554871e05 116 * Writes data to register on the device.
masahikofukasawa 0:56b554871e05 117 * @param address register address
masahikofukasawa 0:56b554871e05 118 * @param data data to be written
masahikofukasawa 0:56b554871e05 119 * @return Returns SUCCESS when succeeded, otherwise returns another.
masahikofukasawa 0:56b554871e05 120 */
masahikofukasawa 0:56b554871e05 121 AK7451::Status AK7451::writeRegister(char address, const char *data){
masahikofukasawa 0:56b554871e05 122 if(AK7451::operationMode != AK7451::AK7451_USER_MODE) return AK7451::ERROR_IN_NORMAL_MODE;
masahikofukasawa 0:56b554871e05 123 AK7451::Status status = AK7451::write(AK7451_OPCODE_WRITE_REGISTER, address, data);
masahikofukasawa 0:56b554871e05 124 return status;
masahikofukasawa 0:56b554871e05 125 }
masahikofukasawa 0:56b554871e05 126
masahikofukasawa 0:56b554871e05 127 /**
masahikofukasawa 0:56b554871e05 128 * Reads data from register on the device.
masahikofukasawa 0:56b554871e05 129 * @param address register address
masahikofukasawa 0:56b554871e05 130 * @param data data to read
masahikofukasawa 0:56b554871e05 131 * @return Returns SUCCESS when succeeded, otherwise returns another.
masahikofukasawa 0:56b554871e05 132 */
masahikofukasawa 0:56b554871e05 133 AK7451::Status AK7451::readRegister(char address, char *data){
masahikofukasawa 0:56b554871e05 134 if(AK7451::operationMode != AK7451::AK7451_USER_MODE) return AK7451::ERROR_IN_NORMAL_MODE;
masahikofukasawa 0:56b554871e05 135 AK7451::Status status = AK7451::read(AK7451_OPCODE_READ_REGISTER, address, data);
masahikofukasawa 0:56b554871e05 136 return status;
masahikofukasawa 0:56b554871e05 137 }
masahikofukasawa 0:56b554871e05 138
masahikofukasawa 0:56b554871e05 139 /**
masahikofukasawa 0:56b554871e05 140 * Sets device operation mode.
masahikofukasawa 0:56b554871e05 141 *
masahikofukasawa 0:56b554871e05 142 * @param mode device opration mode
masahikofukasawa 0:56b554871e05 143 *
masahikofukasawa 0:56b554871e05 144 * @return Returns SUCCESS when succeeded, otherwise returns another code.
masahikofukasawa 0:56b554871e05 145 */
masahikofukasawa 0:56b554871e05 146 AK7451::Status AK7451::setOperationMode(AK7451::OperationMode mode){
masahikofukasawa 0:56b554871e05 147 char command[2];
masahikofukasawa 1:536cf25b0eb4 148 command[0] = (char)(0x0F&(mode>>8));
masahikofukasawa 1:536cf25b0eb4 149 command[1] = (char)(0x00FF&mode);
masahikofukasawa 0:56b554871e05 150
masahikofukasawa 0:56b554871e05 151 AK7451::operationMode = mode;
masahikofukasawa 1:536cf25b0eb4 152 AK7451::Status status = AK7451::write(AK7451_OPCODE_CHANGE_MODE, AK7451_REG_CHMD, command);
masahikofukasawa 1:536cf25b0eb4 153 wait(0.01);
masahikofukasawa 1:536cf25b0eb4 154 return status;
masahikofukasawa 0:56b554871e05 155 }
masahikofukasawa 0:56b554871e05 156
masahikofukasawa 0:56b554871e05 157 /**
masahikofukasawa 3:1e0cfed43467 158 * Gets device operation mode.
masahikofukasawa 3:1e0cfed43467 159 *
masahikofukasawa 3:1e0cfed43467 160 * @return Returns OperationMode.
masahikofukasawa 3:1e0cfed43467 161 */
masahikofukasawa 3:1e0cfed43467 162 AK7451::OperationMode AK7451::getOperationMode(){
masahikofukasawa 3:1e0cfed43467 163 return AK7451::operationMode;
masahikofukasawa 3:1e0cfed43467 164 }
masahikofukasawa 3:1e0cfed43467 165
masahikofukasawa 3:1e0cfed43467 166 /**
masahikofukasawa 0:56b554871e05 167 * Reads angle data from the device.
masahikofukasawa 0:56b554871e05 168 *
masahikofukasawa 0:56b554871e05 169 * @param angle pointer to read angle data buffer
masahikofukasawa 0:56b554871e05 170 *
masahikofukasawa 0:56b554871e05 171 * @return Returns SUCCESS when succeeded, otherwise returns another code.
masahikofukasawa 0:56b554871e05 172 */
masahikofukasawa 0:56b554871e05 173 AK7451::Status AK7451::readAngle(char *angle) {
masahikofukasawa 1:536cf25b0eb4 174
masahikofukasawa 0:56b554871e05 175 char command[2]={0x00,0x00};
masahikofukasawa 0:56b554871e05 176 AK7451::read(AK7451_OPCODE_READ_ANGLE, 0x00, command);
masahikofukasawa 0:56b554871e05 177
masahikofukasawa 0:56b554871e05 178 // status check
masahikofukasawa 0:56b554871e05 179 if( (command[0] & AK7451_READ_ANGLE_STATE_MD) != 0 ){
masahikofukasawa 3:1e0cfed43467 180 // AK7451::setOperationMode(AK7451::AK7451_NORMAL_MODE);
masahikofukasawa 0:56b554871e05 181 return AK7451::ERROR_IN_USER_MODE;
masahikofukasawa 0:56b554871e05 182 }else if( (command[0] & AK7451_READ_ANGLE_STATE_ER) == 0 ){
masahikofukasawa 0:56b554871e05 183 return AK7451::ERROR_ABNORMAL_STRENGTH;
masahikofukasawa 0:56b554871e05 184 }
masahikofukasawa 0:56b554871e05 185 // parity check
masahikofukasawa 0:56b554871e05 186 if( AK7451::parityCheck(command) != AK7451::SUCCESS ) return AK7451::ERROR_PARITY;
masahikofukasawa 0:56b554871e05 187
masahikofukasawa 0:56b554871e05 188 // status check passed, set angle data
masahikofukasawa 0:56b554871e05 189 angle[0] = command[0]&0x0F;
masahikofukasawa 0:56b554871e05 190 angle[1] = command[1];
masahikofukasawa 0:56b554871e05 191
masahikofukasawa 0:56b554871e05 192 return AK7451::SUCCESS;
masahikofukasawa 0:56b554871e05 193 }
masahikofukasawa 0:56b554871e05 194
masahikofukasawa 0:56b554871e05 195 /**
masahikofukasawa 0:56b554871e05 196 * Measures and reads angle, magnetic flux density and abnormal state code while in the user mode.
masahikofukasawa 0:56b554871e05 197 *
masahikofukasawa 0:56b554871e05 198 * @param angle pointer to angle data
masahikofukasawa 0:56b554871e05 199 * @param density magnetic flux density
masahikofukasawa 0:56b554871e05 200 * @param abnormal_state abnormal state
masahikofukasawa 0:56b554871e05 201 *
masahikofukasawa 0:56b554871e05 202 * @return Returns SUCCESS when succeeded, otherwise returns another code.
masahikofukasawa 0:56b554871e05 203 */
masahikofukasawa 0:56b554871e05 204 AK7451::Status AK7451::readAngleMeasureCommand(char *angle, char *density, char *abnormal_state) {
masahikofukasawa 0:56b554871e05 205 if(AK7451::operationMode != AK7451::AK7451_USER_MODE) return AK7451::ERROR_IN_NORMAL_MODE;
masahikofukasawa 0:56b554871e05 206 AK7451::Status status;
masahikofukasawa 0:56b554871e05 207 char data[2] = {0x00,0x00};
masahikofukasawa 0:56b554871e05 208
masahikofukasawa 0:56b554871e05 209 // perform measurement
masahikofukasawa 1:536cf25b0eb4 210 status = AK7451::write(AK7451_OPCODE_ANGLE_MEASURE_CODE, AK7451_REG_ANG, data);
masahikofukasawa 0:56b554871e05 211 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 3:1e0cfed43467 212
masahikofukasawa 3:1e0cfed43467 213 wait(0.01);
masahikofukasawa 3:1e0cfed43467 214
masahikofukasawa 0:56b554871e05 215 // angle read
masahikofukasawa 0:56b554871e05 216 status = AK7451::readRegister(AK7451_REG_ANG, data);
masahikofukasawa 0:56b554871e05 217 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 0:56b554871e05 218 angle[0] = data[0]&0x0F;
masahikofukasawa 0:56b554871e05 219 angle[1] = data[1];
masahikofukasawa 0:56b554871e05 220
masahikofukasawa 0:56b554871e05 221 // mag density read
masahikofukasawa 0:56b554871e05 222 status = AK7451::readRegister(AK7451_REG_MAG, data);
masahikofukasawa 0:56b554871e05 223 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 0:56b554871e05 224 *density = data[1];
masahikofukasawa 0:56b554871e05 225
masahikofukasawa 0:56b554871e05 226 // abnormal_state code read
masahikofukasawa 0:56b554871e05 227 status = AK7451::readRegister(AK7451_REG_ERRMON, data);
masahikofukasawa 0:56b554871e05 228 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 3:1e0cfed43467 229 *abnormal_state = data[1]&0x03;
masahikofukasawa 0:56b554871e05 230
masahikofukasawa 0:56b554871e05 231 return AK7451::SUCCESS;
masahikofukasawa 0:56b554871e05 232 }
masahikofukasawa 0:56b554871e05 233
masahikofukasawa 0:56b554871e05 234 /**
masahikofukasawa 0:56b554871e05 235 * Measures current angle and sets the value to EEPROM as zero angle position.
masahikofukasawa 0:56b554871e05 236 *
masahikofukasawa 0:56b554871e05 237 * @return Returns SUCCESS when succeeded, otherwise returns another code.
masahikofukasawa 0:56b554871e05 238 */
masahikofukasawa 0:56b554871e05 239 AK7451::Status AK7451::setAngleZero(){
masahikofukasawa 3:1e0cfed43467 240
masahikofukasawa 3:1e0cfed43467 241 AK7451::Status status = AK7451::SUCCESS;
masahikofukasawa 3:1e0cfed43467 242
masahikofukasawa 0:56b554871e05 243 char angle[2] = {0x00,0x00};
masahikofukasawa 0:56b554871e05 244 char density;
masahikofukasawa 0:56b554871e05 245 char abnormal_state;
masahikofukasawa 3:1e0cfed43467 246
masahikofukasawa 3:1e0cfed43467 247 // store the original mode
masahikofukasawa 3:1e0cfed43467 248 AK7451::OperationMode org = AK7451::operationMode;
masahikofukasawa 3:1e0cfed43467 249
masahikofukasawa 3:1e0cfed43467 250 // set to user mode
masahikofukasawa 3:1e0cfed43467 251 status = AK7451::setOperationMode(AK7451::AK7451_USER_MODE);
masahikofukasawa 3:1e0cfed43467 252 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 1:536cf25b0eb4 253
masahikofukasawa 1:536cf25b0eb4 254 // initialize ZP register. Set ZP value to zero.
masahikofukasawa 1:536cf25b0eb4 255 status = AK7451::writeRegister(0x06,angle);
masahikofukasawa 1:536cf25b0eb4 256 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 1:536cf25b0eb4 257
masahikofukasawa 1:536cf25b0eb4 258 // read angle data with zero ZP offset
masahikofukasawa 0:56b554871e05 259 status = AK7451::readAngleMeasureCommand(angle, &density, &abnormal_state);
masahikofukasawa 0:56b554871e05 260 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 0:56b554871e05 261 if(abnormal_state != AK7451_ABNORMAL_STATE_NORMAL) return AK7451::ERROR_ABNORMAL_STRENGTH;
masahikofukasawa 1:536cf25b0eb4 262
masahikofukasawa 1:536cf25b0eb4 263 // set read angle to ZP EEPROM
masahikofukasawa 0:56b554871e05 264 status = AK7451::setAngleZero(angle);
masahikofukasawa 3:1e0cfed43467 265 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 3:1e0cfed43467 266
masahikofukasawa 3:1e0cfed43467 267 // back to the original mode
masahikofukasawa 3:1e0cfed43467 268 status = AK7451::setOperationMode(org);
masahikofukasawa 3:1e0cfed43467 269 if(status != AK7451::SUCCESS) return status;
masahikofukasawa 3:1e0cfed43467 270
masahikofukasawa 0:56b554871e05 271 return status;
masahikofukasawa 0:56b554871e05 272 }
masahikofukasawa 0:56b554871e05 273
masahikofukasawa 0:56b554871e05 274 /**
masahikofukasawa 0:56b554871e05 275 * Sets the value to EEPROM as zero angle position.
masahikofukasawa 0:56b554871e05 276 *
masahikofukasawa 0:56b554871e05 277 * @param angle zero angle position
masahikofukasawa 0:56b554871e05 278 *
masahikofukasawa 0:56b554871e05 279 * @return Returns SUCCESS when succeeded, otherwise returns another code.
masahikofukasawa 0:56b554871e05 280 */
masahikofukasawa 0:56b554871e05 281 AK7451::Status AK7451::setAngleZero(const char *angle){
masahikofukasawa 3:1e0cfed43467 282 // if(AK7451::operationMode != AK7451::AK7451_USER_MODE) return AK7451::ERROR_IN_NORMAL_MODE;
masahikofukasawa 3:1e0cfed43467 283 AK7451::writeRegister(AK7451_REG_ZP, angle);
masahikofukasawa 0:56b554871e05 284 return AK7451::writeEEPROM(AK7451_REG_ZP, angle);
masahikofukasawa 0:56b554871e05 285 }
masahikofukasawa 0:56b554871e05 286
masahikofukasawa 0:56b554871e05 287 ////////////////////////////////////////////////////////
masahikofukasawa 0:56b554871e05 288 // private methods
masahikofukasawa 0:56b554871e05 289 ////////////////////////////////////////////////////////
masahikofukasawa 0:56b554871e05 290
masahikofukasawa 0:56b554871e05 291
masahikofukasawa 0:56b554871e05 292 /**
masahikofukasawa 3:1e0cfed43467 293 * Reads data from device.
masahikofukasawa 3:1e0cfed43467 294 * @param operation_code OPCODE
masahikofukasawa 3:1e0cfed43467 295 * @param address memory/register addredd
masahikofukasawa 3:1e0cfed43467 296 * @param *data pointer to the read buffer. length=2 fixed.
masahikofukasawa 0:56b554871e05 297 * @return Returns SUCCESS when succeeded, otherwise returns another.
masahikofukasawa 0:56b554871e05 298 */
masahikofukasawa 0:56b554871e05 299 AK7451::Status AK7451::read(char operation_code, char address, char *data) {
masahikofukasawa 0:56b554871e05 300 char command[3];
masahikofukasawa 0:56b554871e05 301 command[0] = (operation_code<<4) | (address>>3);
masahikofukasawa 0:56b554871e05 302 command[1] = 0xF0&(address<<5);
masahikofukasawa 0:56b554871e05 303 command[2] = 0x00;
masahikofukasawa 0:56b554871e05 304
masahikofukasawa 0:56b554871e05 305 _cs->write(0);
masahikofukasawa 0:56b554871e05 306 _spi->write(command[0]);
masahikofukasawa 0:56b554871e05 307 for(int i=0; i<2; i++){
masahikofukasawa 0:56b554871e05 308 data[i] = _spi->write(command[i+1]);
masahikofukasawa 0:56b554871e05 309 }
masahikofukasawa 0:56b554871e05 310 _cs->write(1);
masahikofukasawa 0:56b554871e05 311
masahikofukasawa 0:56b554871e05 312 return AK7451::SUCCESS;
masahikofukasawa 0:56b554871e05 313 }
masahikofukasawa 0:56b554871e05 314
masahikofukasawa 0:56b554871e05 315 /**
masahikofukasawa 0:56b554871e05 316 * Writes data to the device.
masahikofukasawa 3:1e0cfed43467 317 * @param operation_code OPCODE
masahikofukasawa 3:1e0cfed43467 318 * @param address memory/register addredd
masahikofukasawa 3:1e0cfed43467 319 * @param *data pointer to the read buffer. length=2 fixed.
masahikofukasawa 0:56b554871e05 320 * @return Returns SUCCESS when succeeded, otherwise returns another.
masahikofukasawa 0:56b554871e05 321 */
masahikofukasawa 0:56b554871e05 322 AK7451::Status AK7451::write(char operation_code, char address, const char *data) {
masahikofukasawa 0:56b554871e05 323 char command[3];
masahikofukasawa 0:56b554871e05 324 command[0] = (operation_code<<4) | (address>>3);
masahikofukasawa 0:56b554871e05 325 command[1] = (0xF0&(address<<5)) | (0x0F&data[0]);
masahikofukasawa 0:56b554871e05 326 command[2] = data[1];
masahikofukasawa 0:56b554871e05 327
masahikofukasawa 0:56b554871e05 328 _cs->write(0);
masahikofukasawa 0:56b554871e05 329 for(int i=0; i<3; i++){
masahikofukasawa 0:56b554871e05 330 _spi->write(command[i]);
masahikofukasawa 0:56b554871e05 331 }
masahikofukasawa 0:56b554871e05 332 _cs->write(1);
masahikofukasawa 0:56b554871e05 333
masahikofukasawa 0:56b554871e05 334 return AK7451::SUCCESS;
masahikofukasawa 0:56b554871e05 335 }
masahikofukasawa 0:56b554871e05 336
masahikofukasawa 0:56b554871e05 337 /**
masahikofukasawa 0:56b554871e05 338 * Checks parity bits sub function
masahikofukasawa 0:56b554871e05 339 * @param data data 12bit read data
masahikofukasawa 0:56b554871e05 340 * @param parity parity bit status
masahikofukasawa 0:56b554871e05 341 * @param error error bit status
masahikofukasawa 0:56b554871e05 342 * @return Returns SUCCESS when succeeded, otherwise returns another.
masahikofukasawa 0:56b554871e05 343 */
masahikofukasawa 0:56b554871e05 344 AK7451::Status AK7451::parityCheckSub(const char data, const char parity, const char error){
masahikofukasawa 0:56b554871e05 345 char sum = parity + error;
masahikofukasawa 0:56b554871e05 346 for(int i=0; i<6; i++){
masahikofukasawa 0:56b554871e05 347 if( ((data>>i) & 0x01) !=0 )sum++;
masahikofukasawa 0:56b554871e05 348 }
masahikofukasawa 0:56b554871e05 349 if( (sum & 0x01) == 0) return AK7451::SUCCESS;
masahikofukasawa 0:56b554871e05 350 else return AK7451::ERROR_PARITY;
masahikofukasawa 0:56b554871e05 351 }
masahikofukasawa 0:56b554871e05 352
masahikofukasawa 0:56b554871e05 353 /**
masahikofukasawa 0:56b554871e05 354 * Checks parity bits
masahikofukasawa 0:56b554871e05 355 * @param data 2 byte read data to chek parity
masahikofukasawa 0:56b554871e05 356 * @return Returns SUCCESS when succeeded, otherwise returns another.
masahikofukasawa 0:56b554871e05 357 */
masahikofukasawa 0:56b554871e05 358 AK7451::Status AK7451::parityCheck(const char *data){
masahikofukasawa 0:56b554871e05 359 char p1 = 0x01 & (data[0]>>6);
masahikofukasawa 0:56b554871e05 360 char p2 = 0x01 & (data[0]>>5);
masahikofukasawa 0:56b554871e05 361 char er = 0x01 & (data[0]>>4);
masahikofukasawa 0:56b554871e05 362 char hi = ( (data[0]&0x0F)<<2 ) | ((data[1] & 0xC0)>>6); // Data[11:6]
masahikofukasawa 0:56b554871e05 363 char lo = data[1] & 0x3F; // Data[5:0]
masahikofukasawa 0:56b554871e05 364 AK7451::Status status;
masahikofukasawa 0:56b554871e05 365 status = AK7451::parityCheckSub(hi, p1, er);
masahikofukasawa 0:56b554871e05 366 if( status != AK7451::SUCCESS) return AK7451::ERROR_PARITY;
masahikofukasawa 0:56b554871e05 367 status = parityCheckSub(lo, p2, er);
masahikofukasawa 0:56b554871e05 368 if( status != AK7451::SUCCESS) return AK7451::ERROR_PARITY;
masahikofukasawa 0:56b554871e05 369 return SUCCESS;
masahikofukasawa 0:56b554871e05 370 }