Hello,
I am trying to setup the DWM1000 with an AVR AtMega 328P (8MHz, 3.3V). I have set up SPI and am able to read the device ID and have confirmed SPI is working via the suggestion in the aps022 debugging manual. I have tried using the SimpleTx example and that program seems to run fine. However, the SimpleRx example gets stuck in the loop checking if RXFCG or ALL_RX_ERR gets set in the SYS_STATUS. Neither bit ever gets set. Reading the status register, it always reads 0x2. The aps022 manual (as well as other threads on this forum on similar topics) suggest reading the SYS_STATE register. I have done that and read 0, which according to aps022 means the DWM1000 is still in INIT mode. Interestingly, when I use the arduino library for the DWM1000, communication between the 2 modules works.
My Rx code is as follows:
#define DW1000_RST_DIR DDRD
#define DW1000_RST_PORT PORTD
#define DW1000_RST_PIN PD3
#define LOG(str) uart::writeBytes((uint8_t*) str, sizeof(str));
static dwt_config_t config = {
.chan = 2, /* Channel number. */
.prf = DWT_PRF_64M, /* Pulse repetition frequency. */
.txPreambLength = DWT_PLEN_1024, /* Preamble length. Used in TX only. */
.rxPAC = DWT_PAC32, /* Preamble acquisition chunk size. Used in RX only. */
.txCode = 9, /* TX preamble code. Used in TX only. */
.rxCode = 9, /* RX preamble code. Used in RX only. */
.nsSFD = 1, /* 0 to use standard SFD, 1 to use non-standard SFD. */
.dataRate = DWT_BR_110K, /* Data rate. */
.phrMode = DWT_PHRMODE_STD, /* PHY header mode. */
.sfdTO = (1025 + 64 - 32) /* SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. */
};
/* Buffer to store received frame. See NOTE 1 below. */
#define FRAME_LEN_MAX 127
static uint8 rx_buffer[FRAME_LEN_MAX];
/* Hold copy of status register state here for reference so that it can be examined at a debug breakpoint. */
static uint32 status_reg = 0;
/* Hold copy of frame length of frame received (if good) so that it can be examined at a debug breakpoint. */
static uint16 frame_len = 0;
void init_hardware();
void reset_dw1000();
/**
* Application entry point.
*/
int main(void)
{
/* Start with board specific hardware init. */
uart::init(9600);
LOG("Simple rx, polling\r\n");
spi::init();
init_hardware();
/* Reset and initialise DW1000. See NOTE 2 below.
* For initialisation, DW1000 clocks must be temporarily set to crystal speed. After initialisation SPI rate can be increased for optimum
* performance. */
reset_dw1000(); /* Target specific drive of RSTn line into DW1000 low for a period. */
uint32_t devid = dwt_readdevid();
if (devid == 0xDECA0130) {
LOG("Correct device id\r\n");
} else {
LOG("Incorrect device ID. Broken SPI?\r\n");
while (1) {}
}
spi::set_clock_div(128);
if (dwt_initialise(DWT_LOADNONE) == DWT_ERROR)
{
LOG("Init failed\r\n");
while (1) { };
}
spi::set_clock_div(2);
/* Configure DW1000. */
dwt_configure(&config);
char buf[32];
uint8_t sz;
uint32_t partid = dwt_getpartid();
sz = sprintf(buf, "part id: %d\r\n", partid);
uart::writeBytes((uint8_t*) buf, sz);
uint8_t c = 0;
/* Loop forever receiving frames. */
while (1)
{
sz = sprintf(buf, "[%d]", c);
uart::writeBytes((uint8_t*) buf, sz);
int i;
/* TESTING BREAKPOINT LOCATION #1 */
/* Clear local RX buffer to avoid having leftovers from previous receptions This is not necessary but is included here to aid reading
* the RX buffer.
* This is a good place to put a breakpoint. Here (after first time through the loop) the local status register will be set for last event
* and if a good receive has happened the data buffer will have the data in it, and frame_len will be set to the length of the RX frame. */
for (i = 0 ; i < FRAME_LEN_MAX; i++ )
{
rx_buffer[i] = 0;
}
/* Activate reception immediately. See NOTE 3 below. */
dwt_rxenable(DWT_START_RX_IMMEDIATE);
/* Poll until a frame is properly received or an error/timeout occurs. See NOTE 4 below.
* STATUS register is 5 bytes long but, as the event we are looking at is in the first byte of the register, we can use this simplest API
* function to access it. */
while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_RXFCE | SYS_STATUS_ALL_RX_ERR))) {
sz = sprintf(buf, "status: 0x%x\r\n", status_reg);
uart::writeBytes((uint8_t*) buf, sz);
} // never exits this loop
if (status_reg & SYS_STATUS_RXFCG)
{
LOG("status_reg & SYS_STATUS_RXFCG\r\n");
/* A frame has been received, copy it to our local buffer. */
frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
if (frame_len <= FRAME_LEN_MAX)
{
dwt_readrxdata(rx_buffer, frame_len, 0);
LOG("Received: ");
LOG(rx_buffer);
LOG("\r\n");
}
/* Clear good RX frame event in the DW1000 status register. */
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);
}
else
{
LOG("RX err\r\n");
/* Clear RX error events in the DW1000 status register. */
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);
}
++c;
}
}
void init_hardware() {
// use DW1000_RST_PIN as pin to reset dw1000. configure as input, high impedance for now
DW1000_RST_DIR &= ~(1 << DW1000_RST_PIN);
DW1000_RST_PORT &= ~(1 << DW1000_RST_PIN);
}
void reset_dw1000() {
deca_sleep(5);
DW1000_RST_DIR |= (1 << DW1000_RST_PIN); // set DW1000_RST_PIN as output
DW1000_RST_PORT &= ~(1 << DW1000_RST_PIN); // drive DW1000_RST_PIN low
// delay minimum 10ns
deca_sleep(2);
// put DW1000_RST_PIN back to input, high impedance
DW1000_RST_DIR &= ~(1 << DW1000_RST_PIN); // set DW1000_RST_PIN as input
DW1000_RST_PORT &= ~(1 << DW1000_RST_PIN); // set DW1000_RST_PIN to have high impedance
deca_sleep(10);
}