I’ve packed my code into a library. Here are the methods I am using (I suppose there is something wrong in my init() method):
init():
void DW3000Class::init() {
Serial.println("\n+++ DecaWave DW3000 Test +++\n");
int shCmd[] = { 0 };
writeShortCommand(shCmd, 1);
int data1[] = {0x80,0xEB,0x7,0x0,0x0,0x1F}; //0xF0,0x2F //0x80,0x3E,0x0,0x0,0x0,0x1F //0x0
DW3000Class::write(0x0, 0x3C, data1, 6); //Set IRQ for successful received data frame
int data2[] = { 0x03, 0x3C };
DW3000Class::write(0x0, 0x24, data2, 2); //Frame length setup for Transmission
int data3[] = {0x00,0x9, 0x0};
DW3000Class::write(0xA, 0x0, data3, 3); //AON_DIG_CFG register setup; sets up auto-rx calibration and on-wakeup GO2IDLE //0xA
/*
* Set RX and TX config
*/
int data4[] = { 0x40,0x02,0x00,0x10 }; //DGC_CFG0 //0x3
DW3000Class::write(0x3, 0x1C, data4, 4);
int data5[] = { 0x89,0xa4,0x6d,0x1b }; //DGC_CFG1
DW3000Class::write(0x3, 0x20, data5, 4);
int data6[] = { 0xFD,0xC0,0x01,0x00 }; //DGC_LUT_0
DW3000Class::write(0x3, 0x38, data6, 4);
int data7[] = { 0x3E,0xC4,0x01,0x00 }; //DGC_LUT_1
DW3000Class::write(0x3, 0x3C, data7, 4);
int data8[] = { 0xBE,0xC6,0x01,0x00 }; //DGC_LUT_2
DW3000Class::write(0x3, 0x40, data8, 4);
int data9[] = { 0x7E,0xC7,0x01,0x00 }; //DGC_LUT_3
DW3000Class::write(0x3, 0x44, data9, 4);
int data10[] = { 0x36,0xCF,0x01,0x00 }; //DGC_LUT_4
DW3000Class::write(0x3, 0x48, data10, 4);
int data11[] = { 0xB5,0xCF,0x01,0x00 }; //DGC_LUT_5
DW3000Class::write(0x3, 0x4C, data11, 4);
int data12[] = { 0xF5,0xCF,0x01,0x00 }; //DGC_LUT_6
DW3000Class::write(0x3, 0x50, data12, 4);
int data13[] = { 0xF5,0xE4 };
DW3000Class::write(0x3, 0x18, data13, 2); //THR_64 value set to 0x32
//SET PAC TO 32 (0x00) reg:06:00 bits:1-0, bit 4 to 0 (00001100) (0xC)
int data14[] = { 0xE };
DW3000Class::write(0x6, 0x0, data14, 1); //0x6
//set SFD Detection timeout count to 1057 (0x21, 0x4); 1018 old: (0xFA, 0x3)
int data15[] = { 0x21, 0x4 };
DW3000Class::write(0x6, 0x2, data15, 2);
//SET PREAMBLE CODE (RX_PCODE, TX_PCODE) TO 10 (reg:01:14) //Standard SFD Type is 11 (data: 0x56, 0x5), trying 00 (0x50, 0x5)
int data16[] = { 0x56, 0x5 };
DW3000Class::write(0x1, 0x14, data16, 2); //0x1
// write preamble length, frame length, data rate and prf in TX_FCTRL //PSR = 1024, TXFLEN = 3 Byte (1 data, 2 CRC) TXBR = 6.81Mb/s, TR Bit enabled, FINE_PLEN = 0x0
// reg:00:24 bits 0 - 25
/*int data27[] = {0x03, 0x2C};
DW3000Class::write(0x0, 0x24, data27, 2);*/
/*
* Things to do as documented in https://gist.github.com/egnor/455d510e11c22deafdec14b09da5bf54
*/
int data17[] = { 0x14 };
DW3000Class::write(0x7, 0x48, data17, 1); //LDO_RLOAD to 0x14 //0x7
int data18[] = { 0xE };
DW3000Class::write(0x7, 0x1A, data18, 1); //RF_TX_CTRL_1 to 0x0E
int data19[] = { 0x34,0x11,0x07,0x1C };
DW3000Class::write(0x7, 0x1C, data19, 4); //RF_TX_CTRL_2 to 0x1C071134 (due to channel 5, else (9) to 0x1C010034)
int data20[] = { 0x3C,0x1F };
DW3000Class::write(0x9, 0x0, data20, 2); //PLL_CFG to 0x1F3C (due to channel 5, else (9) to 0x0F3C) //0x9
int data21[] = { 0x81 };
DW3000Class::write(0x9, 0x8, data21, 1); //PLL_CAL config to 0x81
int data22[] = { 0x11 };
int data23[] = { 0x0 }; //if finished with calibration go back in cal_mode //also used to reset LDO_CTRL to 0x0
delay(200);
for (int i = 0; i < 5; i++) {
delay(50);
uint32_t h = DW3000Class::read(0x4, 0x20); //Read antenna calibration //RX_CAL_STS => Status bit, if high antenna cal was successful
if (h > 0) {
Serial.println("Antenna calibration completed.");
break;
}
else {
if (i < 4) {
Serial.println("[WARNING] Antenna auto calibration failed! Retrying...");
DW3000Class::write(0x4, 0x0C, data22, 1);
}
else {
Serial.println("[ERROR] Antenna auto calibration failed! Aborting!");
}
}
}
DW3000Class::write(0x4, 0x0C, data23, 1); //Reset antenna calibration to standard mode
DW3000Class::resetIRQStatusBits();
Serial.println("\nInitialization finished.\n");
}
begin():
void DW3000Class::begin() {
delay(5);
pinMode(CHIP_SELECT_PIN, OUTPUT);
SPI.begin();
attachInterrupt(digitalPinToInterrupt(2), DW3000Class::interruptDetect, RISING);
}
write():
uint32_t DW3000Class::write(int base, int sub, int *data, int data_len) {
int* _base = DW3000Class::getBase(base);
int* _sub = DW3000Class::getSub(sub);
readOrWriteFullAddress(_base, 5, _sub, 7, data, data_len, 1);
free(_base);
free(_sub);
return 0;
}
read():
uint32_t DW3000Class::read(int base, int sub) {
int* _base = DW3000Class::getBase(base);
int* _sub = DW3000Class::getSub(sub);
int t[] = {0};
uint32_t tmp;
tmp = readOrWriteFullAddress(_base, 5, _sub, 7, t, 0, 0);
Serial.println("");
free(_base);
free(_sub);
return tmp;
}
getBase() & getSub():
int* DW3000Class::getBase(int hex_num)
{
return hexToBin(hex_num, 5);
}
int* DW3000Class::getSub(int hex_num)
{
return hexToBin(hex_num, 7);
}
hexToBin():
int* DW3000Class::hexToBin(int hex_num, int bit_size)
{
int bit_count = bit_size;
int* binary_num = (int*)malloc(bit_count * sizeof(int));
int i;
for (i = bit_count - 1; i >= 0; i--) {
binary_num[i] = hex_num % 2;
hex_num >>= 1;
}
return binary_num;
}
readOrWriteFullAddress():
uint32_t DW3000Class::readOrWriteFullAddress(int *base, int base_len, int *sub, int sub_len, int *data, int data_len, int readWriteBit) {
int fill_base_len = 5;
int num_zeros = fill_base_len - base_len;
if (num_zeros < 0) {
num_zeros = 0;
}
int fill_base[fill_base_len]; //fill leading zeros
for (int i = 0; i < fill_base_len; i++) {
fill_base[num_zeros + i] = base[i];
}
int fill_sub_len = 7;
int fill_sub[fill_sub_len]; //fill leading zeros
num_zeros = fill_sub_len - sub_len;
if (num_zeros < 0) {
num_zeros = 0;
}
for (int i = 0; i < fill_sub_len; i++) {
fill_sub[num_zeros + i] = sub[i];
}
int first_byte[8] = { readWriteBit, 1 };
for (int i = 0; i < fill_base_len; i++) {
first_byte[i + 2] = fill_base[i];
}
first_byte[7] = fill_sub[0];
int second_byte[8];
second_byte[8 - 1] = 0; //Last two bits are set to 0 (mode selector bits)
second_byte[8 - 2] = 0;
for (int i = 0; i < fill_sub_len - 1; i++) {
second_byte[i] = fill_sub[i + 1];
}
int byteOne = 0;
int byteTwo = 0;
for (int i = 7; i >= 0; i--) {
byteOne = byteOne + first_byte[i] * round(pow(2, 7 - i));
byteTwo = byteTwo + second_byte[i] * round(pow(2, 7 - i));
}
uint32_t val;
int bytes[data_len + 2] = { byteOne, byteTwo };
for (int i = 0; i < data_len; i++) {
bytes[i + 2] = data[i];
}
uint32_t res;
if (readWriteBit == 0) {
Serial.print("Reading from ");
for (int i = 0; i < fill_base_len; i++) {
Serial.print(fill_base[i]);
}
Serial.print(":");
for (int i = 0; i < fill_sub_len; i++) {
Serial.print(fill_sub[i]);
}
Serial.println("");
res = (uint32_t)sendBytes(bytes, 2 + data_len, 4);
Serial.print("Received result (HEX): ");
Serial.print(res, HEX);
Serial.print(" (BIN): ");
Serial.println(res, BIN);
return res;
}
else {
Serial.print("Writing to ");
for (int i = 0; i < fill_base_len; i++) {
Serial.print(fill_base[i]);
}
Serial.print(":");
for (int i = 0; i < fill_sub_len; i++) {
Serial.print(fill_sub[i]);
}
Serial.println("");
res = (uint32_t)sendBytes(bytes, 2 + data_len, 0);
return res;
}
}
sendBytes():
uint32_t DW3000Class::sendBytes(int b[], int lenB, int recLen) { //WORKING
digitalWrite(CHIP_SELECT_PIN, LOW);
for (int i = 0; i < lenB; i++) {
SPI.transfer(b[i]);
}
int rec;
uint32_t val, tmp;
if (recLen > 0) {
for (int i = 0; i < recLen; i++) {
tmp = SPI.transfer(0x00);
if (i == 0) {
val = tmp; //Read first 4 octets
}
else {
val |= (uint32_t)tmp << 8 * i;
}
}
}
else {
val = 0;
}
digitalWrite(CHIP_SELECT_PIN, HIGH);
return val;
}
standardTX():
void DW3000Class::standardTX() {
if (cmd_error) {
cmd_error = false;
int cmd[] = { 0 };
writeShortCommand(cmd, 1);
}
int data[] = { 0x36 };
DW3000Class::write(0x14, 0x0, data, 1);
int cmd[] = { 1 };
DW3000Class::writeShortCommand(cmd, 1);
}
standardRX():
void DW3000Class::standardRX() {
int cmd[] = { 1,0 };
DW3000Class::writeShortCommand(cmd, 2);
}
I am so so sorry, that’s actually quite more than I expected it to be. If any method is missing just let me know! I am still working on making it pretty, for now it’s just a “as long as it works, it’s not dumb” approach. As I stated above, I suppose I am doing something wrong in the init() function.
In my normal program, I do the following:
#include <DW3000.h>
bool mode = 0
bool sent_rx = false
void setup() {
Serial.begin(115200);
DW3000.begin();
DW3000.init();
}
void loop() {
if(mode){ //TX
DW3000.standardTX();
delay(1000);
}else{ //RX
if(!sent_rx){
DW3000.standardRX();
sent_rx = true;
}
}
}