Skip to content
This repository was archived by the owner on Nov 9, 2023. It is now read-only.

Commit 0ab114d

Browse files
anacromaniacSonic0
authored andcommitted
Added abstraction for Arduino SPI (#137)
Now when you change clock mode the SPI speed not changes automatically.
1 parent 24ec6d7 commit 0ab114d

File tree

12 files changed

+290
-116
lines changed

12 files changed

+290
-116
lines changed

examples/StandardRTLSAnchorB_TWR/StandardRTLSAnchorB_TWR.ino

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
* This is an example slave anchor in a RTLS using two way ranging ISO/IEC 24730-62_2013 messages
1313
*/
1414

15-
#include <SPI.h>
1615
#include <DW1000Ng.hpp>
1716
#include <DW1000NgUtils.hpp>
1817
#include <DW1000NgRanging.hpp>
@@ -109,7 +108,7 @@ void transmitRangeReport() {
109108
void loop() {
110109
RangeAcceptResult result = DW1000NgRTLS::anchorRangeAccept(NextActivity::RANGING_CONFIRM, next_anchor);
111110
if(result.success) {
112-
delay(3); // Tweak based on your hardware
111+
delay(2); // Tweak based on your hardware
113112
range_self = result.range;
114113
transmitRangeReport();
115114

examples/StandardRTLSAnchorC_TWR/StandardRTLSAnchorC_TWR.ino

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
* This is an example slave anchor in a RTLS using two way ranging ISO/IEC 24730-62_2013 messages
1313
*/
1414

15-
#include <SPI.h>
1615
#include <DW1000Ng.hpp>
1716
#include <DW1000NgUtils.hpp>
1817
#include <DW1000NgRanging.hpp>
@@ -109,7 +108,7 @@ void transmitRangeReport() {
109108
void loop() {
110109
RangeAcceptResult result = DW1000NgRTLS::anchorRangeAccept(NextActivity::ACTIVITY_FINISHED, blink_rate);
111110
if(result.success) {
112-
delay(1); // Tweak based on your hardware
111+
delay(4); // Tweak based on your hardware
113112
range_self = result.range;
114113
transmitRangeReport();
115114

examples/StandardRTLSAnchorMain_TWR/StandardRTLSAnchorMain_TWR.ino

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
* This is an example master anchor in a RTLS using two way ranging ISO/IEC 24730-62_2013 messages
1313
*/
1414

15-
#include <SPI.h>
1615
#include <DW1000Ng.hpp>
1716
#include <DW1000NgUtils.hpp>
1817
#include <DW1000NgRanging.hpp>

examples/StandardRTLSTag_TWR/StandardRTLSTag_TWR.ino

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
* This is an example tag in a RTLS using two way ranging ISO/IEC 24730-62_2013 messages
1313
*/
1414

15-
#include <SPI.h>
1615
#include <DW1000Ng.hpp>
1716
#include <DW1000NgUtils.hpp>
1817
#include <DW1000NgTime.hpp>

src/DW1000Ng.cpp

+73-97
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@
4444

4545
#include <stdio.h>
4646
#include <stdlib.h>
47-
#include <SPI.h>
4847
#include <string.h>
48+
#include "DW1000Ng.hpp"
4949
#include "DW1000NgUtils.hpp"
5050
#include "DW1000NgConstants.hpp"
5151
#include "DW1000NgRegisters.hpp"
52-
#include "DW1000Ng.hpp"
52+
#include "SPIporting.hpp"
5353

5454
namespace DW1000Ng {
5555

@@ -103,15 +103,6 @@ namespace DW1000Ng {
103103
uint16_t _antennaTxDelay = 0;
104104
uint16_t _antennaRxDelay = 0;
105105

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-
115106
/* ############################# PRIVATE METHODS ################################### */
116107
/*
117108
* Write bytes to the DW1000Ng. Single bytes can be written to registers via sub-addressing.
@@ -130,8 +121,7 @@ namespace DW1000Ng {
130121

131122
void _writeBytesToRegister(byte cmd, uint16_t offset, byte data[], uint16_t data_size) {
132123
byte header[3];
133-
uint8_t headerLen = 1;
134-
uint16_t i = 0;
124+
uint8_t headerLen = 1;
135125

136126
// TODO proper error handling: address out of bounds
137127
// build SPI header
@@ -148,17 +138,7 @@ namespace DW1000Ng {
148138
headerLen += 2;
149139
}
150140
}
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);
162142
}
163143

164144
void _writeToRegister(byte cmd, uint16_t offset, uint32_t data, uint16_t data_size) {
@@ -182,10 +162,9 @@ namespace DW1000Ng {
182162
* The number of bytes expected to be received.
183163
*/
184164
// 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) {
186166
byte header[3];
187167
uint8_t headerLen = 1;
188-
uint16_t i = 0;
189168

190169
// build SPI header
191170
if(offset == NO_SUB) {
@@ -201,17 +180,7 @@ namespace DW1000Ng {
201180
headerLen += 2;
202181
}
203182
}
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);
215184
}
216185

217186
// always 4 bytes
@@ -253,6 +222,31 @@ namespace DW1000Ng {
253222

254223
_writeBytesToRegister(bitRegister, RegisterOffset+idx, &targetByte, 1);
255224
}
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+
}
256250

257251
/* Steps used to get Temp and Voltage */
258252
void _vbatAndTempSteps() {
@@ -756,23 +750,6 @@ namespace DW1000Ng {
756750
_writeBytesToRegister(FS_CTRL, FS_PLLCFG_SUB, fspllcfg, LEN_FS_PLLCFG);
757751
}
758752

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-
776753
void _tune() {
777754
// these registers are going to be tuned/configured
778755
_agctune1();
@@ -791,7 +768,6 @@ namespace DW1000Ng {
791768
_rftxctrl();
792769
if(_autoTCPGDelay) _tcpgdelaytune();
793770
_fspll();
794-
_fsxtalt();
795771
}
796772

797773
void _writeNetworkIdAndDeviceAddress() {
@@ -1050,7 +1026,8 @@ namespace DW1000Ng {
10501026
void _manageLDE() {
10511027
// transfer any ldo tune values
10521028
byte ldoTune[LEN_OTP_RDAT];
1053-
_readBytesOTP(0x04, ldoTune); // TODO #define
1029+
uint16_t LDOTUNE_ADDRESS = 0x04;
1030+
_readBytesOTP(LDOTUNE_ADDRESS, ldoTune); // TODO #define
10541031
if(ldoTune[0] != 0) {
10551032
// TODO tuning available, copy over to RAM: use OTP_LDO bit
10561033
}
@@ -1067,38 +1044,33 @@ namespace DW1000Ng {
10671044
otpctrl[0] = 0x00;
10681045
otpctrl[1] = 0x80;
10691046
_writeBytesToRegister(PMSC, PMSC_CTRL0_SUB, pmscctrl0, 2);
1047+
// uCode
1048+
_enableClock(LDE_CLOCK);
1049+
delay(5);
10701050
_writeBytesToRegister(OTP_IF, OTP_CTRL_SUB, otpctrl, 2);
1051+
delay(1);
1052+
_enableClock(SYS_AUTO_CLOCK);
10711053
delay(5);
10721054
pmscctrl0[0] = 0x00;
10731055
pmscctrl0[1] &= 0x02;
10741056
_writeBytesToRegister(PMSC, PMSC_CTRL0_SUB, pmscctrl0, 2);
10751057
}
10761058

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);
10981069
} else {
1099-
// TODO deliver proper warning
1070+
DW1000NgUtils::writeValueToBytes(fsxtalt, ((buf_otp[0] & 0x1F) | 0x60), LEN_FS_XTALT);
11001071
}
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);
11021074
}
11031075

11041076
void _clearReceiveStatus() {
@@ -1237,23 +1209,29 @@ namespace DW1000Ng {
12371209
// DW1000 data sheet v2.08 §5.6.1 page 20, the RSTn pin should not be driven high but left floating.
12381210
pinMode(_rst, INPUT);
12391211
}
1240-
// start SPI
1241-
SPI.begin();
1212+
1213+
SPIporting::SPIinit();
12421214
// pin and basic member setup
12431215
// attach interrupt
12441216
// TODO throw error if pin is not a interrupt pin
12451217
if(_irq != 0xff)
12461218
attachInterrupt(digitalPinToInterrupt(_irq), interruptServiceRoutine, RISING);
1247-
select();
1219+
SPIporting::SPIselect(_ss, _irq);
12481220
// reset chip (either soft or hard)
1249-
12501221
reset();
12511222

1223+
SPIporting::setSPIspeed(SPIClock::SLOW);
12521224
_enableClock(SYS_XTI_CLOCK);
12531225
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+
12541233
// load LDE micro-code
12551234
_manageLDE();
1256-
delay(5);
12571235

12581236
// read the temp and vbat readings from OTP that were recorded during production test
12591237
// see 6.3.1 OTP memory map
@@ -1265,6 +1243,7 @@ namespace DW1000Ng {
12651243

12661244
_enableClock(SYS_AUTO_CLOCK);
12671245
delay(5);
1246+
SPIporting::setSPIspeed(SPIClock::FAST);
12681247

12691248
_readNetworkIdAndDeviceAddress();
12701249
_readSystemConfigurationRegister();
@@ -1274,25 +1253,13 @@ namespace DW1000Ng {
12741253

12751254
/* Cleared AON:CFG1(0x2C:0x0A) for proper operation of deepSleep */
12761255
_writeToRegister(AON, AON_CFG1_SUB, 0x00, LEN_AON_CFG1);
1256+
12771257
}
12781258

12791259
void initializeNoInterrupt(uint8_t ss, uint8_t rst) {
12801260
initialize(ss, 0xff, rst);
12811261
}
12821262

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-
12961263
/* callback handler management. */
12971264
void attachErrorHandler(void (* handleError)(void)) {
12981265
_handleError = handleError;
@@ -1479,11 +1446,15 @@ namespace DW1000Ng {
14791446
}
14801447

14811448
void softwareReset() {
1449+
SPIporting::setSPIspeed(SPIClock::SLOW);
1450+
14821451
/* Disable sequencing and go to state "INIT" - (a) Sets SYSCLKS to 01 */
14831452
_disableSequencing();
14841453
/* Clear AON and WakeUp configuration */
14851454
_writeToRegister(AON, AON_WCFG_SUB, 0x00, LEN_AON_WCFG);
14861455
_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);
14871458
_writeToRegister(AON, AON_CTRL_SUB, 0x02, LEN_AON_CTRL);
14881459
/* (b) Clear SOFTRESET to all zero’s */
14891460
_writeToRegister(PMSC, PMSC_SOFTRESET_SUB, 0x00, LEN_PMSC_SOFTRESET);
@@ -1652,6 +1623,7 @@ namespace DW1000Ng {
16521623
void getTemperatureAndBatteryVoltage(float& temp, float& vbat) {
16531624
// follow the procedure from section 6.4 of the User Manual
16541625
_vbatAndTempSteps();
1626+
delay(1);
16551627
byte sar_lvbat = 0; _readBytes(TX_CAL, 0x03, &sar_lvbat, 1);
16561628
byte sar_ltemp = 0; _readBytes(TX_CAL, 0x04, &sar_ltemp, 1);
16571629

@@ -1869,6 +1841,10 @@ namespace DW1000Ng {
18691841
}
18701842

18711843
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+
18721848
_disableSequencing();
18731849
_configureRFTransmitPowerSpectrumTestMode();
18741850
_enableClock(SYS_PLL_CLOCK);

0 commit comments

Comments
 (0)