Driver for AK7451 Angle Senor(SPI).
Fork of AK7451 by
ak7451.cpp@3:1e0cfed43467, 2017-04-28 (annotated)
- 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?
User | Revision | Line number | New 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 | } |