44
44
45
45
#include < stdio.h>
46
46
#include < stdlib.h>
47
- #include < SPI.h>
48
47
#include < string.h>
48
+ #include " DW1000Ng.hpp"
49
49
#include " DW1000NgUtils.hpp"
50
50
#include " DW1000NgConstants.hpp"
51
51
#include " DW1000NgRegisters.hpp"
52
- #include " DW1000Ng .hpp"
52
+ #include " SPIporting .hpp"
53
53
54
54
namespace DW1000Ng {
55
55
@@ -103,15 +103,6 @@ namespace DW1000Ng {
103
103
uint16_t _antennaTxDelay = 0 ;
104
104
uint16_t _antennaRxDelay = 0 ;
105
105
106
- /* SPI relative variables */
107
- #if defined(ESP32) || defined(ESP8266)
108
- const SPISettings _fastSPI = SPISettings(20000000L , MSBFIRST, SPI_MODE0);
109
- #else
110
- const SPISettings _fastSPI = SPISettings(16000000L , MSBFIRST, SPI_MODE0);
111
- #endif
112
- const SPISettings _slowSPI = SPISettings(2000000L , MSBFIRST, SPI_MODE0);
113
- const SPISettings* _currentSPI = &_fastSPI;
114
-
115
106
/* ############################# PRIVATE METHODS ################################### */
116
107
/*
117
108
* Write bytes to the DW1000Ng. Single bytes can be written to registers via sub-addressing.
@@ -130,8 +121,7 @@ namespace DW1000Ng {
130
121
131
122
void _writeBytesToRegister (byte cmd, uint16_t offset, byte data[], uint16_t data_size) {
132
123
byte header[3 ];
133
- uint8_t headerLen = 1 ;
134
- uint16_t i = 0 ;
124
+ uint8_t headerLen = 1 ;
135
125
136
126
// TODO proper error handling: address out of bounds
137
127
// build SPI header
@@ -148,17 +138,7 @@ namespace DW1000Ng {
148
138
headerLen += 2 ;
149
139
}
150
140
}
151
- SPI.beginTransaction (*_currentSPI);
152
- digitalWrite (_ss, LOW);
153
- for (i = 0 ; i < headerLen; i++) {
154
- SPI.transfer (header[i]); // send header
155
- }
156
- for (i = 0 ; i < data_size; i++) {
157
- SPI.transfer (data[i]); // write values
158
- }
159
- delayMicroseconds (5 );
160
- digitalWrite (_ss, HIGH);
161
- SPI.endTransaction ();
141
+ SPIporting::writeToSPI (_ss, headerLen, header, data_size, data);
162
142
}
163
143
164
144
void _writeToRegister (byte cmd, uint16_t offset, uint32_t data, uint16_t data_size) {
@@ -182,10 +162,9 @@ namespace DW1000Ng {
182
162
* The number of bytes expected to be received.
183
163
*/
184
164
// TODO incomplete doc
185
- void _readBytes (byte cmd, uint16_t offset, byte data[], uint16_t n ) {
165
+ void _readBytes (byte cmd, uint16_t offset, byte data[], uint16_t data_size ) {
186
166
byte header[3 ];
187
167
uint8_t headerLen = 1 ;
188
- uint16_t i = 0 ;
189
168
190
169
// build SPI header
191
170
if (offset == NO_SUB) {
@@ -201,17 +180,7 @@ namespace DW1000Ng {
201
180
headerLen += 2 ;
202
181
}
203
182
}
204
- SPI.beginTransaction (*_currentSPI);
205
- digitalWrite (_ss, LOW);
206
- for (i = 0 ; i < headerLen; i++) {
207
- SPI.transfer (header[i]); // send header
208
- }
209
- for (i = 0 ; i < n; i++) {
210
- data[i] = SPI.transfer (0x00 ); // read values
211
- }
212
- delayMicroseconds (5 );
213
- digitalWrite (_ss, HIGH);
214
- SPI.endTransaction ();
183
+ SPIporting::readFromSPI (_ss, headerLen, header, data_size, data);
215
184
}
216
185
217
186
// always 4 bytes
@@ -253,6 +222,31 @@ namespace DW1000Ng {
253
222
254
223
_writeBytesToRegister (bitRegister, RegisterOffset+idx, &targetByte, 1 );
255
224
}
225
+
226
+ void _enableClock (byte clock) {
227
+ byte pmscctrl0[LEN_PMSC_CTRL0];
228
+ memset (pmscctrl0, 0 , LEN_PMSC_CTRL0);
229
+ _readBytes (PMSC, PMSC_CTRL0_SUB, pmscctrl0, LEN_PMSC_CTRL0);
230
+ if (clock == SYS_AUTO_CLOCK) {
231
+ pmscctrl0[0 ] = SYS_AUTO_CLOCK;
232
+ pmscctrl0[1 ] &= 0xFE ;
233
+ } else if (clock == SYS_XTI_CLOCK) {
234
+ pmscctrl0[0 ] &= 0xFC ;
235
+ pmscctrl0[0 ] |= SYS_XTI_CLOCK;
236
+ } else if (clock == SYS_PLL_CLOCK) {
237
+ pmscctrl0[0 ] &= 0xFC ;
238
+ pmscctrl0[0 ] |= SYS_PLL_CLOCK;
239
+ } else if (clock == TX_PLL_CLOCK) {
240
+ pmscctrl0[0 ] &= 0xCF ;
241
+ pmscctrl0[0 ] |= TX_PLL_CLOCK;
242
+ } else if (clock == LDE_CLOCK) {
243
+ pmscctrl0[0 ] = SYS_XTI_CLOCK;
244
+ pmscctrl0[1 ] = 0x03 ;
245
+ } else {
246
+ // TODO deliver proper warning
247
+ }
248
+ _writeBytesToRegister (PMSC, PMSC_CTRL0_SUB, pmscctrl0, 2 );
249
+ }
256
250
257
251
/* Steps used to get Temp and Voltage */
258
252
void _vbatAndTempSteps () {
@@ -756,23 +750,6 @@ namespace DW1000Ng {
756
750
_writeBytesToRegister (FS_CTRL, FS_PLLCFG_SUB, fspllcfg, LEN_FS_PLLCFG);
757
751
}
758
752
759
- /* Crystal calibration from OTP (if available)
760
- * FS_XTALT - reg:0x2B, sub-reg:0x0E
761
- * OTP(one-time-programmable) memory map - table 10 */
762
- void _fsxtalt () {
763
- byte fsxtalt[LEN_FS_XTALT];
764
- byte buf_otp[4 ];
765
- _readBytesOTP (0x01E , buf_otp); // 0x01E -> byte[0]=XTAL_Trim
766
- if (buf_otp[0 ] == 0 ) {
767
- // No trim value available from OTP, use midrange value of 0x10
768
- DW1000NgUtils::writeValueToBytes (fsxtalt, ((0x10 & 0x1F ) | 0x60 ), LEN_FS_XTALT);
769
- } else {
770
- DW1000NgUtils::writeValueToBytes (fsxtalt, ((buf_otp[0 ] & 0x1F ) | 0x60 ), LEN_FS_XTALT);
771
- }
772
- // write configuration back to chip
773
- _writeBytesToRegister (FS_CTRL, FS_XTALT_SUB, fsxtalt, LEN_FS_XTALT);
774
- }
775
-
776
753
void _tune () {
777
754
// these registers are going to be tuned/configured
778
755
_agctune1 ();
@@ -791,7 +768,6 @@ namespace DW1000Ng {
791
768
_rftxctrl ();
792
769
if (_autoTCPGDelay) _tcpgdelaytune ();
793
770
_fspll ();
794
- _fsxtalt ();
795
771
}
796
772
797
773
void _writeNetworkIdAndDeviceAddress () {
@@ -1050,7 +1026,8 @@ namespace DW1000Ng {
1050
1026
void _manageLDE () {
1051
1027
// transfer any ldo tune values
1052
1028
byte ldoTune[LEN_OTP_RDAT];
1053
- _readBytesOTP (0x04 , ldoTune); // TODO #define
1029
+ uint16_t LDOTUNE_ADDRESS = 0x04 ;
1030
+ _readBytesOTP (LDOTUNE_ADDRESS, ldoTune); // TODO #define
1054
1031
if (ldoTune[0 ] != 0 ) {
1055
1032
// TODO tuning available, copy over to RAM: use OTP_LDO bit
1056
1033
}
@@ -1067,38 +1044,33 @@ namespace DW1000Ng {
1067
1044
otpctrl[0 ] = 0x00 ;
1068
1045
otpctrl[1 ] = 0x80 ;
1069
1046
_writeBytesToRegister (PMSC, PMSC_CTRL0_SUB, pmscctrl0, 2 );
1047
+ // uCode
1048
+ _enableClock (LDE_CLOCK);
1049
+ delay (5 );
1070
1050
_writeBytesToRegister (OTP_IF, OTP_CTRL_SUB, otpctrl, 2 );
1051
+ delay (1 );
1052
+ _enableClock (SYS_AUTO_CLOCK);
1071
1053
delay (5 );
1072
1054
pmscctrl0[0 ] = 0x00 ;
1073
1055
pmscctrl0[1 ] &= 0x02 ;
1074
1056
_writeBytesToRegister (PMSC, PMSC_CTRL0_SUB, pmscctrl0, 2 );
1075
1057
}
1076
1058
1077
- void _enableClock (byte clock) {
1078
- byte pmscctrl0[LEN_PMSC_CTRL0];
1079
- memset (pmscctrl0, 0 , LEN_PMSC_CTRL0);
1080
- _readBytes (PMSC, PMSC_CTRL0_SUB, pmscctrl0, LEN_PMSC_CTRL0);
1081
- /* SYSCLKS */
1082
- if (clock == SYS_AUTO_CLOCK) {
1083
- _currentSPI = &_fastSPI;
1084
- pmscctrl0[0 ] = SYS_AUTO_CLOCK;
1085
- pmscctrl0[1 ] &= 0xFE ;
1086
- } else if (clock == SYS_XTI_CLOCK) {
1087
- _currentSPI = &_slowSPI;
1088
- pmscctrl0[0 ] &= 0xFC ;
1089
- pmscctrl0[0 ] |= SYS_XTI_CLOCK;
1090
- } else if (clock == SYS_PLL_CLOCK) {
1091
- _currentSPI = &_fastSPI;
1092
- pmscctrl0[0 ] &= 0xFC ;
1093
- pmscctrl0[0 ] |= SYS_PLL_CLOCK;
1094
- } else if (clock == TX_PLL_CLOCK) { /* NOT SYSCLKS but TX */
1095
- _currentSPI = &_fastSPI;
1096
- pmscctrl0[0 ] &= 0xCF ;
1097
- pmscctrl0[0 ] |= TX_PLL_CLOCK;
1059
+ /* Crystal calibration from OTP (if available)
1060
+ * FS_XTALT - reg:0x2B, sub-reg:0x0E
1061
+ * OTP(one-time-programmable) memory map - table 10 */
1062
+ void _fsxtalt () {
1063
+ byte fsxtalt[LEN_FS_XTALT];
1064
+ byte buf_otp[4 ];
1065
+ _readBytesOTP (0x01E , buf_otp); // 0x01E -> byte[0]=XTAL_Trim
1066
+ if (buf_otp[0 ] == 0 ) {
1067
+ // No trim value available from OTP, use midrange value of 0x10
1068
+ DW1000NgUtils::writeValueToBytes (fsxtalt, ((0x10 & 0x1F ) | 0x60 ), LEN_FS_XTALT);
1098
1069
} else {
1099
- // TODO deliver proper warning
1070
+ DW1000NgUtils::writeValueToBytes (fsxtalt, ((buf_otp[ 0 ] & 0x1F ) | 0x60 ), LEN_FS_XTALT);
1100
1071
}
1101
- _writeBytesToRegister (PMSC, PMSC_CTRL0_SUB, pmscctrl0, 2 );
1072
+ // write configuration back to chip
1073
+ _writeBytesToRegister (FS_CTRL, FS_XTALT_SUB, fsxtalt, LEN_FS_XTALT);
1102
1074
}
1103
1075
1104
1076
void _clearReceiveStatus () {
@@ -1237,23 +1209,29 @@ namespace DW1000Ng {
1237
1209
// DW1000 data sheet v2.08 §5.6.1 page 20, the RSTn pin should not be driven high but left floating.
1238
1210
pinMode (_rst, INPUT);
1239
1211
}
1240
- // start SPI
1241
- SPI. begin ();
1212
+
1213
+ SPIporting::SPIinit ();
1242
1214
// pin and basic member setup
1243
1215
// attach interrupt
1244
1216
// TODO throw error if pin is not a interrupt pin
1245
1217
if (_irq != 0xff )
1246
1218
attachInterrupt (digitalPinToInterrupt (_irq), interruptServiceRoutine, RISING);
1247
- select ( );
1219
+ SPIporting::SPIselect (_ss, _irq );
1248
1220
// reset chip (either soft or hard)
1249
-
1250
1221
reset ();
1251
1222
1223
+ SPIporting::setSPIspeed (SPIClock::SLOW);
1252
1224
_enableClock (SYS_XTI_CLOCK);
1253
1225
delay (5 );
1226
+
1227
+ // Configure the CPLL lock detect
1228
+ _writeBitToRegister (EXT_SYNC, EC_CTRL_SUB, LEN_EC_CTRL, PLLLDT_BIT, true );
1229
+
1230
+ // Configure XTAL trim
1231
+ _fsxtalt ();
1232
+
1254
1233
// load LDE micro-code
1255
1234
_manageLDE ();
1256
- delay (5 );
1257
1235
1258
1236
// read the temp and vbat readings from OTP that were recorded during production test
1259
1237
// see 6.3.1 OTP memory map
@@ -1265,6 +1243,7 @@ namespace DW1000Ng {
1265
1243
1266
1244
_enableClock (SYS_AUTO_CLOCK);
1267
1245
delay (5 );
1246
+ SPIporting::setSPIspeed (SPIClock::FAST);
1268
1247
1269
1248
_readNetworkIdAndDeviceAddress ();
1270
1249
_readSystemConfigurationRegister ();
@@ -1274,25 +1253,13 @@ namespace DW1000Ng {
1274
1253
1275
1254
/* Cleared AON:CFG1(0x2C:0x0A) for proper operation of deepSleep */
1276
1255
_writeToRegister (AON, AON_CFG1_SUB, 0x00 , LEN_AON_CFG1);
1256
+
1277
1257
}
1278
1258
1279
1259
void initializeNoInterrupt (uint8_t ss, uint8_t rst) {
1280
1260
initialize (ss, 0xff , rst);
1281
1261
}
1282
1262
1283
- void select () {
1284
- #if !defined(ESP32) && !defined(ESP8266)
1285
- if (_irq != 0xff )
1286
- SPI.usingInterrupt (digitalPinToInterrupt (_irq));
1287
- #endif
1288
- pinMode (_ss, OUTPUT);
1289
- digitalWrite (_ss, HIGH);
1290
- }
1291
-
1292
- void end () {
1293
- SPI.end ();
1294
- }
1295
-
1296
1263
/* callback handler management. */
1297
1264
void attachErrorHandler (void (* handleError)(void )) {
1298
1265
_handleError = handleError;
@@ -1479,11 +1446,15 @@ namespace DW1000Ng {
1479
1446
}
1480
1447
1481
1448
void softwareReset () {
1449
+ SPIporting::setSPIspeed (SPIClock::SLOW);
1450
+
1482
1451
/* Disable sequencing and go to state "INIT" - (a) Sets SYSCLKS to 01 */
1483
1452
_disableSequencing ();
1484
1453
/* Clear AON and WakeUp configuration */
1485
1454
_writeToRegister (AON, AON_WCFG_SUB, 0x00 , LEN_AON_WCFG);
1486
1455
_writeToRegister (AON, AON_CFG0_SUB, 0x00 , LEN_AON_CFG0);
1456
+ // TODO change this with uploadToAON
1457
+ _writeToRegister (AON, AON_CTRL_SUB, 0x00 , LEN_AON_CTRL);
1487
1458
_writeToRegister (AON, AON_CTRL_SUB, 0x02 , LEN_AON_CTRL);
1488
1459
/* (b) Clear SOFTRESET to all zero’s */
1489
1460
_writeToRegister (PMSC, PMSC_SOFTRESET_SUB, 0x00 , LEN_PMSC_SOFTRESET);
@@ -1652,6 +1623,7 @@ namespace DW1000Ng {
1652
1623
void getTemperatureAndBatteryVoltage (float & temp, float & vbat) {
1653
1624
// follow the procedure from section 6.4 of the User Manual
1654
1625
_vbatAndTempSteps ();
1626
+ delay (1 );
1655
1627
byte sar_lvbat = 0 ; _readBytes (TX_CAL, 0x03 , &sar_lvbat, 1 );
1656
1628
byte sar_ltemp = 0 ; _readBytes (TX_CAL, 0x04 , &sar_ltemp, 1 );
1657
1629
@@ -1869,6 +1841,10 @@ namespace DW1000Ng {
1869
1841
}
1870
1842
1871
1843
void enableTransmitPowerSpectrumTestMode (int32_t repeat_interval) {
1844
+ /* DW1000 clocks must be set to crystal speed so SPI rate have to be lowered and will
1845
+ not be increased again */
1846
+ SPIporting::setSPIspeed (SPIClock::SLOW);
1847
+
1872
1848
_disableSequencing ();
1873
1849
_configureRFTransmitPowerSpectrumTestMode ();
1874
1850
_enableClock (SYS_PLL_CLOCK);
0 commit comments