forked from monolithicpower/MagAlpha-Arduino-Library
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMagAlphaGen4.cpp
More file actions
277 lines (250 loc) · 9.5 KB
/
Copy pathMagAlphaGen4.cpp
File metadata and controls
277 lines (250 loc) · 9.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/***************************************************
Arduino library for the MPS MagAlpha magnetic angle sensor
Supports MagAlpha 4th generation Sensors.
Support Part Number includes: MA780, MA782, MA734
MagAlpha sensor detects the
absolute angular position of a permanent magnet, typically a diametrically
magnetized cylinder on the rotating shaft.
----> http://www.monolithicpower.com/Products/Position-Sensors/Products-Overview
Written by Mathieu Kaelin for Monolithic Power Systems.
MIT license, all text above must be included in any redistribution
****************************************************/
#include "MagAlphaGen4.h"
//MagAlpha Read/Write Register Command
#define READ_REG_COMMAND (0b010 << 13)
#define WRITE_REG_COMMAND (0b100 << 13)
#define STORE_SINGLE_REGISTER_COMMAND (0b111 << 13)
#define STORE_ALL_REGISTERS_COMMAND (0b110 << 13)
#define RESTORE_ALL_REGISTERS_COMMAND (0b101 << 13)
#define CLEAR_ERROR_FLAGS_COMMAND (0b001 << 13)
#define REG_REGMAPID 23
#define REG_SID 24
#define REG_PID 25
#define REG_LOCK0 28
#define REG_LOCK1 29
#define REG_LOCK2 30
#define REG_LOCK3 31
MagAlphaGen4::MagAlphaGen4(){
}
uint16_t MagAlphaGen4::readAngleRaw16(){
uint16_t angle;
digitalWrite(_spiChipSelectPin, LOW);
angle = _spi->transfer16(0x0000); //Read 16-bit angle
digitalWrite(_spiChipSelectPin, HIGH);
return angle;
}
uint8_t MagAlphaGen4::readAngleRaw8(){
uint8_t angle;
digitalWrite(_spiChipSelectPin, LOW);
angle = _spi->transfer(0x00); //Read 8-bit angle
digitalWrite(_spiChipSelectPin, HIGH);
return angle;
}
uint16_t MagAlphaGen4::readAngleRaw(bool* error){
uint16_t angle;
uint8_t parity;
uint8_t highStateCount = 0;
digitalWrite(_spiChipSelectPin, LOW);
angle = _spi->transfer16(0x0000);
parity = _spi->transfer(0x00);
digitalWrite(_spiChipSelectPin, HIGH);
parity = ((parity & 0x80) >> 7);
//Count the number of 1 in the angle binary value
for (int i=0;i<16;++i){
if ((angle & (1 << i)) != 0){
highStateCount++;
}
}
//check if parity bit is correct
if ((highStateCount % 2) == 0){
if (parity == 0){
*error = false;
}
else{
*error = true;
}
}
else{
if (parity == 1){
*error = false;
}
else{
*error = true;
}
}
return angle;
}
uint8_t MagAlphaGen4::readRegister(uint8_t address){
uint8_t readbackRegisterValue;
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(READ_REG_COMMAND | ((address & 0x1F) << 8) | 0x00);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout
digitalWrite(_spiChipSelectPin, LOW);
readbackRegisterValue = (_spi->transfer16(0x0000) & 0x00FF);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout
return readbackRegisterValue;
}
uint8_t MagAlphaGen4::writeRegister(uint8_t address, uint8_t value){
uint8_t readbackRegisterValue;
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(WRITE_REG_COMMAND | ((address & 0x1F) << 8) | value);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout
digitalWrite(_spiChipSelectPin, LOW);
readbackRegisterValue = (_spi->transfer16(0x0000) & 0x00FF);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout
return readbackRegisterValue;
}
void MagAlphaGen4::readRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){
uint8_t readbackRegisterValue;
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(READ_REG_COMMAND | (((address) & 0x1F) << 8) | 0x00);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout
for (uint8_t i=0;i<numberOfRegister-1;++i){
digitalWrite(_spiChipSelectPin, LOW);
valueArray[i] = (_spi->transfer16(READ_REG_COMMAND | (((address+i+1) & 0x1F) << 8) | 0x00) & 0x00FF);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout
}
digitalWrite(_spiChipSelectPin, LOW);
valueArray[numberOfRegister-1] = (_spi->transfer16(0x0000) & 0x00FF);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout
}
void MagAlphaGen4::writeRegisterBurst(uint8_t address, uint8_t valueArray[], uint16_t numberOfRegister){
for (uint8_t i=0;i<numberOfRegister;++i){
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(WRITE_REG_COMMAND | (((address+i) & 0x1F) << 8) | valueArray[i]);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout
}
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(0x0000);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout
}
/*
uint16_t MagAlphaGen4::detectSensorGeneration(){
uint16_t chipId;
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(0x6000);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns before register readout
digitalWrite(_spiChipSelectPin, LOW);
chipId = _spi->transfer16(0x0000) & 0x00FF;
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout
return chipId;
}
*/
uint16_t MagAlphaGen4::getZero()
{
return (readRegister(1)<<8) + readRegister(0);
}
void MagAlphaGen4::setZero(uint16_t zero){
writeRegister(0, zero&0xFF);
writeRegister(1, zero>>8);
}
uint16_t MagAlphaGen4::setCurrentAngleAsZero(){
uint16_t zero;
setZero(0);
zero=readAngleRaw16();
setZero(zero);
return zero;
}
uint16_t MagAlphaGen4::getBct(){
return readRegister(2);
}
void MagAlphaGen4::setBct(uint16_t bct){
writeRegister(2, bct&0xFF);
}
void MagAlphaGen4::restoreAllRegisters(){
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(RESTORE_ALL_REGISTERS_COMMAND);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(240); //Wait for 240us
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(0x0000);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout
}
void MagAlphaGen4::storeAllRegisters(){
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(STORE_ALL_REGISTERS_COMMAND);
digitalWrite(_spiChipSelectPin, HIGH);
delay(704); //Wait for 704ms
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(0x0000);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout
}
void MagAlphaGen4::storeRegister(uint8_t address){
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(STORE_SINGLE_REGISTER_COMMAND | ((address & 0x1F) << 8) | 0x00);
digitalWrite(_spiChipSelectPin, HIGH);
delay(23); //Wait for 23ms
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(0x0000);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout
}
void MagAlphaGen4::clearErrorFlags(){
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(CLEAR_ERROR_FLAGS_COMMAND);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tClearFault of 40ns before register readout
digitalWrite(_spiChipSelectPin, LOW);
_spi->transfer16(0x0000);
digitalWrite(_spiChipSelectPin, HIGH);
delayMicroseconds(1); //Wait for 1us (=1000 ns) to respect tIdleReg of 120ns after register readout
}
uint16_t MagAlphaGen4::getNumberOfRegisters(){
return 32;
}
void MagAlphaGen4::getLockedRegisters(uint8_t unlockedRegisters[]){
uint8_t registerArray[4] = {0};
readRegisterBurst(REG_LOCK0, registerArray, 4);
for(uint8_t i=0; i<4; i++){
for(uint8_t j=0; j<8; j++){
unlockedRegisters[i*8+j] = ((registerArray[i]>>j)&0x01) ? 0xFF : 0x00;
}
}
}
void MagAlphaGen4::getPartNumber(char *partNumber){
uint8_t partId = readRegister(REG_PID);
switch(partId) {
case 1:
sprintf(partNumber, "MA780");
break;
case 2:
sprintf(partNumber, "MA781");
break;
case 3:
sprintf(partNumber, "MA782");
break;
case 248:
sprintf(partNumber, "MA736");
break;
case 249:
sprintf(partNumber, "MA734");
break;
case 250:
sprintf(partNumber, "MA734");
break;
default:
sprintf(partNumber, "Gen4 [%u] Unknown Part Number", partId);
}
}
uint8_t MagAlphaGen4::getSiliconId(){
return (readRegister(REG_SID) & 0xF0) >> 4;
}
uint8_t MagAlphaGen4::getSiliconRevision(){
return readRegister(REG_SID) & 0x0F;
}
uint8_t MagAlphaGen4::getRegisterMapRevision(){
return readRegister(REG_REGMAPID);
}