Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • garlichs/dw1000_driver_freertos
  • cwulf/dw1000_driver_freertos
  • cm-projects/dw1000_driver_freertos
3 results
Show changes
Commits on Source (15)
......@@ -2,6 +2,8 @@
#define __dw1000_H
#include "FreeRTOS.h"
#include <stdint.h>
#include "cmsis_os.h"
#include "dw1000_util.h"
//DECA:DW1000 SLEEP and WAKEUP configuration parameters
#define DWT_LOADLDO 0x1000 // ONW_LLDO - on wakeup load the LDO tune value
#define DWT_LOADUCODE 0x0800 // ONW_LLDE - on wakeup load the LDE ucode
......@@ -16,6 +18,61 @@
#define DWT_WAKE_WK 0x2 // wake up on WAKEUP PIN
#define DWT_SLP_EN 0x1 // enable sleep/deep sleep functionality
/**
* Defines for channel and prf selection and Preamble Code.
* Refer to Page 204 in the dw1000 User Manual 2.04
*/
#define PRF_SHIFT 0
#define CHANNEL_SHIFT 1
#define PREAMBLE_SHIFT 4
//16MHz
#define CH1_16MHZ_1 (0 << PRF_SHIFT) | (1 << CHANNEL_SHIFT) | (1 << PREAMBLE_SHIFT)
#define CH1_16MHZ_2 (0 << PRF_SHIFT) | (1 << CHANNEL_SHIFT) | (2 << PREAMBLE_SHIFT)
#define CH2_16MHZ_3 (0 << PRF_SHIFT) | (2 << CHANNEL_SHIFT) | (3 << PREAMBLE_SHIFT)
#define CH2_16MHZ_4 (0 << PRF_SHIFT) | (2 << CHANNEL_SHIFT) | (4 << PREAMBLE_SHIFT)
#define CH3_16MHZ_5 (0 << PRF_SHIFT) | (3 << CHANNEL_SHIFT) | (5 << PREAMBLE_SHIFT)
#define CH3_16MHZ_6 (0 << PRF_SHIFT) | (3 << CHANNEL_SHIFT) | (6 << PREAMBLE_SHIFT)
#define CH4_16MHZ_7 (0 << PRF_SHIFT) | (4 << CHANNEL_SHIFT) | (7 << PREAMBLE_SHIFT)
#define CH4_16MHZ_8 (0 << PRF_SHIFT) | (4 << CHANNEL_SHIFT) | (8 << PREAMBLE_SHIFT)
#define CH5_16MHZ_3 (0 << PRF_SHIFT) | (5 << CHANNEL_SHIFT) | (3 << PREAMBLE_SHIFT)
#define CH5_16MHZ_4 (0 << PRF_SHIFT) | (5 << CHANNEL_SHIFT) | (4 << PREAMBLE_SHIFT)
#define CH7_16MHZ_7 (0 << PRF_SHIFT) | (7 << CHANNEL_SHIFT) | (7 << PREAMBLE_SHIFT)
#define CH7_16MHZ_8 (0 << PRF_SHIFT) | (7 << CHANNEL_SHIFT) | (8 << PREAMBLE_SHIFT)
//64MHz
#define CH1_64MHZ_9 (1 << PRF_SHIFT) | (1 << CHANNEL_SHIFT) | (9 << PREAMBLE_SHIFT)
#define CH1_64MHZ_10 (1 << PRF_SHIFT) | (1 << CHANNEL_SHIFT) | (10 << PREAMBLE_SHIFT)
#define CH1_64MHZ_11 (1 << PRF_SHIFT) | (1 << CHANNEL_SHIFT) | (11 << PREAMBLE_SHIFT)
#define CH1_64MHZ_12 (1 << PRF_SHIFT) | (1 << CHANNEL_SHIFT) | (12 << PREAMBLE_SHIFT)
#define CH2_64MHZ_9 (1 << PRF_SHIFT) | (2 << CHANNEL_SHIFT) | (9 << PREAMBLE_SHIFT)
#define CH2_64MHZ_10 (1 << PRF_SHIFT) | (2 << CHANNEL_SHIFT) | (10 << PREAMBLE_SHIFT)
#define CH2_64MHZ_11 (1 << PRF_SHIFT) | (2 << CHANNEL_SHIFT) | (11 << PREAMBLE_SHIFT)
#define CH2_64MHZ_12 (1 << PRF_SHIFT) | (2 << CHANNEL_SHIFT) | (12 << PREAMBLE_SHIFT)
#define CH3_64MHZ_9 (1 << PRF_SHIFT) | (3 << CHANNEL_SHIFT) | (9 << PREAMBLE_SHIFT)
#define CH3_64MHZ_10 (1 << PRF_SHIFT) | (3 << CHANNEL_SHIFT) | (10 << PREAMBLE_SHIFT)
#define CH3_64MHZ_11 (1 << PRF_SHIFT) | (3 << CHANNEL_SHIFT) | (11 << PREAMBLE_SHIFT)
#define CH3_64MHZ_12 (1 << PRF_SHIFT) | (3 << CHANNEL_SHIFT) | (12 << PREAMBLE_SHIFT)
#define CH4_64MHZ_17 (1 << PRF_SHIFT) | (4 << CHANNEL_SHIFT) | (17 << PREAMBLE_SHIFT)
#define CH4_64MHZ_18 (1 << PRF_SHIFT) | (4 << CHANNEL_SHIFT) | (18 << PREAMBLE_SHIFT)
#define CH4_64MHZ_19 (1 << PRF_SHIFT) | (4 << CHANNEL_SHIFT) | (19 << PREAMBLE_SHIFT)
#define CH4_64MHZ_20 (1 << PRF_SHIFT) | (4 << CHANNEL_SHIFT) | (20 << PREAMBLE_SHIFT)
#define CH5_64MHZ_9 (1 << PRF_SHIFT) | (5 << CHANNEL_SHIFT) | (9 << PREAMBLE_SHIFT)
#define CH5_64MHZ_10 (1 << PRF_SHIFT) | (5 << CHANNEL_SHIFT) | (10 << PREAMBLE_SHIFT)
#define CH5_64MHZ_11 (1 << PRF_SHIFT) | (5 << CHANNEL_SHIFT) | (11 << PREAMBLE_SHIFT)
#define CH5_64MHZ_12 (1 << PRF_SHIFT) | (5 << CHANNEL_SHIFT) | (12 << PREAMBLE_SHIFT)
#define CH7_64MHZ_17 (1 << PRF_SHIFT) | (7 << CHANNEL_SHIFT) | (17 << PREAMBLE_SHIFT)
#define CH7_64MHZ_18 (1 << PRF_SHIFT) | (7 << CHANNEL_SHIFT) | (18 << PREAMBLE_SHIFT)
#define CH7_64MHZ_19 (1 << PRF_SHIFT) | (7 << CHANNEL_SHIFT) | (19 << PREAMBLE_SHIFT)
#define CH7_64MHZ_20 (1 << PRF_SHIFT) | (7 << CHANNEL_SHIFT) | (20 << PREAMBLE_SHIFT)
//DECA:DW1000 INIT configuration parameters
#define DWT_LOADLDOTUNE 0x8
#define DWT_LOADTXCONFIG 0x4
......@@ -81,13 +138,24 @@ typedef struct {
uint16_t sfdTO; //!< SFD timeout value (in symbols)
}dwt_config_t;
} dwt_config_t;
int dw1000_init(uint16_t config, BaseType_t (*sendCallback)(),
BaseType_t (*receiveCallback)(uint32_t bufferLength));
BaseType_t (*receiveCallback)(uint32_t bufferLength, uint8_t ts_valid));
int dw1000_configure(dwt_config_t *config, uint8_t use_otpconfigvalues);
int dw1000_sendFrame(uint8_t *payload, uint16_t len);
int dw1000_writeFrameIntoBuffer(uint16_t txBufferOffset, uint8_t *payload, uint16_t len);
int dw1000_transmitFrame(uint16_t txBufferOffset, uint16_t len);
int dw_1000_receiveFrameFromIsr(uint8_t * buffer, uint32_t length);
void dw1000_extiCallback(void);
void vTaskGlobalTimeIncrement(void *pvParameters);
void dw1000_generateConfig(uint16_t mode, dwt_config_t *config);
#endif /*__ dw1000_H */
/**
* Defines various return codes for driver functions
*/
#define DW1000_RET_OK 0
#define DW1000_RET_MSG_TO_LONG -1
#define DW1000_RET_TX_BUFFER_OVERFLOW -2
......@@ -17,6 +17,8 @@ int dw1000Hal_readRegister(uint8_t regID, uint8_t *dest, uint16_t len);
int dw1000Hal_writeRegister(uint8_t regID, uint8_t *src, uint16_t len);
int dw1000Hal_readRegisterFromIsr(uint8_t regID, uint8_t *dest, uint16_t len);
int dw1000Hal_writeRegisterFromIsr(uint8_t regID, uint8_t *dest, uint16_t len);
int dw1000Hal_readSubRegisterFromIsr(uint8_t regID, uint16_t offset, uint8_t *dest, uint16_t len);
int dw1000Hal_writeSubRegisterFromIsr(uint8_t regID, uint16_t offset, uint8_t *src, uint16_t len);
int dw1000Hal_readDmaRegister(uint8_t regID, uint8_t *dest, uint16_t len, void (*callback)(int state, void *data, uint16_t len));
int dw1000Hal_writeDmaRegister(uint8_t regID, uint8_t *src, uint16_t len, void (*callback)(int state, void *data, uint16_t len));
#endif /*__ dw1000_hal_H */
......@@ -2,8 +2,9 @@
#define __dw1000_util_H
#include "FreeRTOS.h"
#include <stdint.h>
#include <string.h>
#include "deca_regs.h"
//#define DOUBLE_BUFFER
//DECA:Defines for enable_clocks function
#define FORCE_SYS_XTI 0
......@@ -31,6 +32,14 @@
#define NUM_CH_SUPPORTED 8 //supported channels are '0', 1, 2, 3, 4, 5, '6', 7
#define PCODES 25 //supported preamble codes
#define ever ;;
#define GLOBAL_TIME_TICK_MS 17592
typedef struct {
uint64_t ms;
uint64_t subms;
} dw1000_global_time_t;
typedef struct {//DECA
uint32_t txFCTRL; // keep TX_FCTRL register config
uint16_t rfrxDly; // rf delay (delay though the RF blocks before the signal comes out of the antenna i.e. "antenna delay")
......@@ -41,16 +50,17 @@ typedef struct {//DECA
uint32_t sysCFGreg; // local copy of system config register
uint32_t txPowCfg[12]; // stores the Tx power configuration read from OTP (6 channels consecutively with PRF16 then 64, e.g. Ch 1 PRF16 is index 0 and 64 index 1)
BaseType_t (*sendCB)();
BaseType_t (*receiveCB)(uint32_t bufferLength);
BaseType_t (*receiveCB)(uint32_t bufferLength, uint8_t ts_valid);
TaskHandle_t taskHandle;
int prfIndex;
uint8_t longFrames ; // flag in non-standard long frame mode
uint32_t ldoTune; //low 32 bits of LDO tune value
uint8_t chan; // added chan here - used in the reading of acc
dw1000_global_time_t last_rx_time;
} dw1000_local_data_t;
extern dw1000_local_data_t dw1000local; // Static local device data
extern dw1000_local_data_t dw1000local; // Static local device data
extern const uint8_t pll2calcfg;
// SFD Threshold
......@@ -78,15 +88,14 @@ extern const uint16_t lde_replicaCoeff[PCODES];
#define DEBUG
void dw1000Util_enableclocks(int clocks);
void dw1000Util_enableRX();
uint32_t dw1000Util_otpread(uint32_t address);
void dw1000Util_forceTrxOff(void);
void dw1000Util_reset(void);
void dw1000Util_resetRxOnly(void);
void dw1000Util_getRxTimestamp(dw1000_global_time_t *timeBuffer);
void dw1000Util_printGlobalTimestamp(dw1000_global_time_t *time);
#ifdef DEBUG
void hexdump(uint8_t * buffer, uint8_t len);
......
#include "dw1000.h"
#include "dw1000_util.h"
#include "dw1000_hal.h"
#include "dw1000_isr.h"
#include "deca_regs.h"
......@@ -14,9 +13,13 @@
#define ANTDLY_ADDRESS (0x1C)
#define XTRIM_ADDRESS (0x1E)
volatile uint32_t global_time = 0;
uint16_t maximum_message_length = 1024; //Fixme: put right message length
int dw1000_init(uint16_t config, BaseType_t (*sendCallback)(),
BaseType_t (*receiveCallback)(uint32_t bufferLength)) {
BaseType_t (*receiveCallback)(uint32_t bufferlength, uint8_t ts_valid)) {
// Clear control-structure
......@@ -38,9 +41,7 @@ int dw1000_init(uint16_t config, BaseType_t (*sendCallback)(),
uint32_t sys_mask = 0;
dw1000Hal_readRegister(SYS_MASK_ID, (uint8_t *) &sys_mask, SYS_MASK_LEN);
trace_printf("SYS_MASK: %x\n", sys_mask);
sys_mask |= ( SYS_MASK_MTXFRS | SYS_MASK_MRXDFR | SYS_MASK_MRXFCG
| SYS_MASK_MLDEDONE
);
sys_mask |= ( SYS_MASK_MTXFRS | SYS_MASK_MRXDFR | SYS_MASK_MLDEDONE);
trace_printf("SYS_MASK: %x\n", sys_mask);
dw1000Hal_writeRegister(SYS_MASK_ID, (uint8_t *) &sys_mask, SYS_MASK_LEN);
......@@ -105,6 +106,14 @@ int dw1000_init(uint16_t config, BaseType_t (*sendCallback)(),
//FIXME: Sleep in FreeRTOS? Sleep(1); // Allow time for code to upload (should take up to 120 us)
osDelay(1);
wr_buf[1] = 0x02; //Force TX clock off.
wr_buf[0] = 0x00; //Force system clock to be the 19.2 MHz XTI clock.
//DECA:dwt_writetodevice(PMSC_ID, PMSC_CTRL0_OFFSET, 2, wr_buf);
dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, wr_buf, 2); //Just first 2 byte instead of whole crtl0
//default clocks (ENABLE_ALL_SEQ)
//DECA:enable clocks for sequencing
dw1000Util_enableclocks(ENABLE_ALL_SEQ);
......@@ -128,14 +137,20 @@ int dw1000_init(uint16_t config, BaseType_t (*sendCallback)(),
dw1000Hal_readRegister(SYS_CFG_ID, (uint8_t *) &dw1000local.sysCFGreg,
SYS_CFG_LEN);
#ifdef DOUBLE_BUFFER
//Enable double buffer
dw1000local.sysCFGreg &= (~SYS_CFG_DIS_DRXB);
dw1000Hal_writeRegister(SYS_CFG_ID, (uint8_t *) &dw1000local.sysCFGreg,
SYS_CFG_LEN);
#endif
uint32_t event_clear = 0xFFFFFFFF;
dw1000Hal_writeRegister(SYS_STATUS_ID, (uint8_t*) &event_clear,
SYS_STATUS_LEN);
//Enable Receiver
dw1000Util_enableRX();
uint32_t event_clear = 0xFFFFFFFF;
dw1000Hal_writeRegister(SYS_STATUS_ID, (uint8_t*) &event_clear,
SYS_STATUS_LEN);
return 0;
}
......@@ -163,10 +178,10 @@ int dw1000_configure(dwt_config_t *config, uint8_t use_otpconfigvalues) {
dw1000local.sysCFGreg |= (SYS_CFG_PHR_MODE_11 & (config->phrMode << 16)); //Set to enable PhyHdr for long frames
dw1000local.sysCFGreg |= (1 << 29); //RXAUTR
dw1000local.sysCFGreg |= (SYS_CFG_RXAUTR); //Automatic reenable of the receiver
dw1000Hal_writeRegister(SYS_CFG_ID, (uint8_t *) &dw1000local.sysCFGreg,
SYS_CFG_LEN);
dw1000Hal_writeRegister(SYS_CFG_ID, (uint8_t *) &dw1000local.sysCFGreg, SYS_CFG_LEN);
//DECA:write/set the lde_replicaCoeff
dw1000Hal_writeSubRegister(LDE_IF_ID, LDE_REPC_OFFSET, (uint8_t *) &reg16,
......@@ -342,46 +357,56 @@ int dw1000_configure(dwt_config_t *config, uint8_t use_otpconfigvalues) {
return 0;
}
uint16_t txBufferOffset = 0;
// sends a frame and blocks until finished
int dw1000_sendFrame(uint8_t *payload, uint16_t len) {
//Write payload to the buffer with no offset
int ret = dw1000_writeFrameIntoBuffer(0, payload, len);
if(ret != DW1000_RET_OK){
return ret;
}
//Invoke transmission
return dw1000_transmitFrame(0,len);
}
int dw1000_writeFrameIntoBuffer(uint16_t txBufferOffset, uint8_t *payload, uint16_t len){
if ((len + 2) > maximum_message_length){
// Message + CRC is longer than the allowed msg length (usually 127, but decawave
return DW1000_RET_MSG_TO_LONG;
}
if ((txBufferOffset + len + 2) > 1024){
return -1; //FIXME: ERRORCODE
return DW1000_RET_TX_BUFFER_OVERFLOW;
}
//Write payload
//Write payload into tx buffer
dw1000Hal_writeRegister(TX_BUFFER_ID + txBufferOffset, payload, len);
return DW1000_RET_OK;
}
int dw1000_transmitFrame(uint16_t txBufferOffset, uint16_t len){
//Set length and offset
uint32_t reg32 = dw1000local.txFCTRL | len+2 | (txBufferOffset << 22);
dw1000Hal_writeSubRegister(TX_FCTRL_ID, 0, (uint8_t *) &reg32, TX_FCTRL_LEN-1);
txBufferOffset += len + 2;
txBufferOffset = 0; //FIXME: Löschen, wenn anständige Offsetbehandlung.
// /* WITHOUT THE NEXT PART: SECOND TIME NO SENDING POSSIBLE, BUT CAN'T BE FOUND IN ORIGINAL DRIVER */
// uint32_t sys_ctrl = 0;
// dw1000Hal_readRegister(SYS_CTRL_ID, (uint8_t *)&sys_ctrl, 4);
// //trace_printf("sys_ctrl: %x\n", sys_ctrl);
// sys_ctrl |= SYS_CTRL_TRXOFF;// Immediately cancel all RX and TX operations, bring radio to IDLE state
//// trace_printf("sys_ctrl: %x\n", sys_ctrl);
// dw1000Hal_writeRegister(SYS_CTRL_ID, (uint8_t *)&sys_ctrl, 4);
// sys_ctrl = 0;
dw1000Util_forceTrxOff();
/* WITHOUT THE NEXT PART: SECOND TIME NO SENDING POSSIBLE, BUT CAN'T BE FOUND IN ORIGINAL DRIVER */
dw1000Util_forceTrxOff();
uint8_t temp = (uint8_t) SYS_CTRL_TXSTRT;
dw1000Hal_writeRegister(SYS_CTRL_ID, (uint8_t *)&temp,1);
return DW1000_RET_OK;
}
return 0;
void vTaskGlobalTimeIncrement(void *pvParameters) {
TickType_t xNextWakeTime;
xNextWakeTime = xTaskGetTickCount();
for(ever) {
// Task is delayed until radio timestamp approximately overflows
vTaskDelayUntil(&xNextWakeTime, GLOBAL_TIME_TICK_MS / portTICK_PERIOD_MS);
global_time++;
}
vTaskDelete( NULL);
}
void dw1000_extiCallback(void) {
dw1000Isr_handleInterrupt();
}
......@@ -400,3 +425,38 @@ int dw1000_setPanId(uint16_t addr) {
return dw1000Hal_writeSubRegister(PANADR_ID, PANADR_PAN_ID_OFFSET,
(uint8_t*) &addr, PANADR_PAN_ID_LEN);
}
void dw1000_generateConfig(uint16_t mode, dwt_config_t *config){
uint8_t prf64Mhz = mode & 1; //0, if 16Mhz is selected
//Set channel
config->chan = (mode >> CHANNEL_SHIFT) & 7;
//Set rxCode/txCode, which can be different, but should be the same
config->rxCode = (mode >> PREAMBLE_SHIFT) & 31;
config->txCode = (mode >> PREAMBLE_SHIFT) & 31;
//Set PRF
if(prf64Mhz){
//64MHz PRF
config->prf = DWT_PRF_64M;
}else{
//16MHz PRF
config->prf = DWT_PRF_16M;
}
config->sfdTO = (129 + 8 - 8); //Fixme: How to calculate SFD Timeout
config->dataRate = DWT_BR_6M8;
config->rxPAC = DWT_PAC8;
//Use IEEE Conform Header and SFD Fixme: Support Decawave later?
config->nsSFD = 0;
config->phrMode = 0;
config->txPreambLength = DWT_PLEN_128;
}
......@@ -75,7 +75,7 @@ int dw1000Hal_readSubRegisterFromIsr(uint8_t regID, uint16_t offset,
int ret;
//portENTER_CRITICAL();
if ((spiSema != NULL)
&& (xSemaphoreTake(spiSema, ( TickType_t ) DW1000HAL_SPI_TIMEOUT)
&& (xSemaphoreTakeFromISR(spiSema, pdFALSE)
== pdTRUE)) {
if (len <= 127) {
dummy[0] = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
......@@ -97,7 +97,7 @@ int dw1000Hal_readSubRegisterFromIsr(uint8_t regID, uint16_t offset,
dw1000Hal_chipDeselect();
while (hspi->State != HAL_SPI_STATE_READY)
;
xSemaphoreGive(spiSema);
xSemaphoreGiveFromISR(spiSema, pdFALSE);
} else {
ret = HAL_LOCKED;
}
......
#include "dw1000_hal.h"
#include "deca_regs.h"
#include "dw1000_util.h"
#include "Trace.h"
BaseType_t dw1000Hal_handleTx(uint64_t * event, uint64_t * event_clear) {
// Ignore unused parameters, may be needed for later purposes
(void) event;
(void) event_clear;
BaseType_t dw1000Hal_handleTx(uint64_t event) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
dw1000Util_enableRX();
if (dw1000local.sendCB != NULL) {
xHigherPriorityTaskWoken |= dw1000local.sendCB();
} else {
trace_printf("TX handler null\n");
}
return xHigherPriorityTaskWoken;
}
BaseType_t dw1000Hal_handleRx(uint64_t event) {
BaseType_t dw1000Hal_handleRx(uint64_t * event, uint64_t * event_clear) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
//if (event & SYS_STATUS_LDEDONE) // LDE done/finished
{
//trace_printf("LDEDONE\n");
uint16_t len = 0;
if (event & SYS_STATUS_RXOVRR) //NOTE when overrun both HS and RS pointers point to the same buffer
{
trace_printf("SYS_STATUS_RXOVRR\n");
//when the overrun happens the frame info data of the buffer A (which contains the older frame e.g. seq. num = x)
//will be corrupted with the latest frame (seq. num = x + 2) data, both the host and IC are pointing to buffer A
//we are going to discard this frame - turn off transceiver and reset receiver
dw1000Util_forceTrxOff();
dw1000Util_resetRxOnly();
uint32_t sys_ctrl = 0;
dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t*) &sys_ctrl,
SYS_CTRL_LEN); // switch to rx mode
sys_ctrl |= SYS_CTRL_RXENAB;
dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t*) &sys_ctrl,
SYS_CTRL_LEN);
return pdFALSE;
} else //no overrun condition - proceed to process the frame
{
trace_printf("NO OVERRUN\n");
uint32_t rx_frame_info;
dw1000Hal_readRegisterFromIsr(RX_FINFO_ID,
(uint8_t *) &rx_frame_info,
RX_FINFO_LEN);
uint32_t rx_buffer_len;
rx_buffer_len = rx_frame_info & RX_FINFO_RXFLEN_MASK; // No shifting required
trace_printf("Paketlength: %u\n", rx_buffer_len);
xHigherPriorityTaskWoken = dw1000local.receiveCB(rx_buffer_len);
uint32_t sys_ctrl = 0;
//dw1000Hal_resetRxOnly();
dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t*) &sys_ctrl,
SYS_CTRL_LEN); // switch to rx mode
sys_ctrl |= SYS_CTRL_RXENAB;
dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t*) &sys_ctrl,
SYS_CTRL_LEN);
} //end of no overrun
} //if LDE_DONE is set (this means we have both SYS_STATUS_RXFCG and SYS_STATUS_LDEDONE)
// else //no LDE_DONE ?
{
// trace_printf("NO LDE done or LDE error\n");
//Fixme: Wann kann ein Overrun auftreten?
//Get get length
uint32_t rx_frame_info;
dw1000Hal_readRegisterFromIsr(RX_FINFO_ID, (uint8_t *) &rx_frame_info,
RX_FINFO_LEN);
uint32_t rx_buffer_len;
rx_buffer_len = rx_frame_info & RX_FINFO_RXFLEN_MASK; // No shifting required
uint8_t lde_done = (*event & SYS_STATUS_LDEDONE) ? 1 : 0;
//Trigger Callback
if (dw1000local.receiveCB != NULL) {
xHigherPriorityTaskWoken = dw1000local.receiveCB(rx_buffer_len,
lde_done);
} else if (dw1000local.taskHandle != NULL) {
//TODO Notify taskHandle
}
#ifdef DOUBLE_BUFFER
if((*event & SYS_STATUS_HSRBP) != (*event & SYS_STATUS_ICRBP)){
*event_clear |= *event & CLEAR_DBLBUFF_EVENTS ;
}
#endif
//Set the clear bits.
*event_clear |= CLEAR_ALLRXGOOD_EVENTS;
*event_clear |= CLEAR_ALLRXERROR_EVENTS;
dw1000Util_enableRX();
return xHigherPriorityTaskWoken;
}
void dw1000Isr_handleInterrupt(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
trace_printf("ISR ENTRY\n");
uint64_t event = 0;
uint64_t event_clear = 0;
dw1000Hal_readRegisterFromIsr(SYS_STATUS_ID, (uint8_t*) &event,
SYS_STATUS_LEN);
uint64_t event_clear = 0;
// Handle weird somehow random occuring losing lock events
if (event & SYS_STATUS_CLKPLL_LL) { // Clock PLL Losing Lock
event_clear |= SYS_STATUS_CLKPLL_LL;
if (event & SYS_STATUS_CPLOCK) {
......@@ -88,105 +71,32 @@ void dw1000Isr_handleInterrupt(void) {
event &= ~(SYS_STATUS_CLKPLL_LL);
}
//
// if((status & SYS_STATUS_LDEDONE) && (dw1000local.dblbuffon == 0))
// if((event & (SYS_STATUS_LDEDONE | SYS_STATUS_RXPHD | SYS_STATUS_RXSFDD)) != (SYS_STATUS_LDEDONE | SYS_STATUS_RXPHD | SYS_STATUS_RXSFDD)){
// dw1000_forceTrxOff();
// //trace_printf("SHIT\n");
// dw1000Hal_resetRxOnly();
// }
#ifdef DEBUG
hexdump(&event, 5);
#endif
if (event & SYS_STATUS_TXFRS) { // Frame sent
event_clear |= SYS_STATUS_TXFRS; //clear interrupt
dw1000Hal_handleTx(event);
if (event & SYS_STATUS_TXFRS) {
// Frame sent
dw1000Hal_handleTx(&event, &event_clear);
} else if ((event
& ( SYS_STATUS_RXFCG | SYS_STATUS_RXPHD | SYS_STATUS_RXSFDD))
!= (SYS_STATUS_RXFCG | SYS_STATUS_RXPHD | SYS_STATUS_RXSFDD)) {
#ifdef DOUBLE_BUFFER
dw1000Hal_handleRx(&event, &event_clear);
#else
//Error Case
trace_printf("Error!\n");
hexdump(&event, 5);
event_clear |= CLEAR_ALLRXERROR_EVENTS;
event_clear |= CLEAR_ALLRXGOOD_EVENTS;
//re-enable the receiver - if auto rx re-enable set
dw1000Util_enableRX();
#endif
} else {
if (event & SYS_STATUS_RXFCG) {
event_clear |= CLEAR_ALLRXGOOD_EVENTS;
event_clear |= CLEAR_ALLRXERROR_EVENTS;
dw1000Hal_handleRx(event);
} else if (event & SYS_STATUS_RXDFR) {
//trace_printf("Received\n");
trace_printf("RX DFR\n");
event_clear |= CLEAR_ALLRXGOOD_EVENTS;
dw1000Util_enableRX();
} else if (event & SYS_STATUS_RXPHE) {
trace_printf("PH ERROR\n");
event_clear |= CLEAR_ALLRXERROR_EVENTS;
dw1000Util_enableRX();
}
dw1000Hal_handleRx(&event, &event_clear);
}
// if (event & SYS_STATUS_RXDFR){ // Frame received
// event_clear |= SYS_STATUS_RXDFR; //clear interrupt
// trace_printf("dw1000Hal_extiCallback:received %lu\n",event);
//
// uint32_t rx_frame_info;
// dw1000Hal_readRegisterFromIsr(RX_FINFO_ID, (uint8_t *)&rx_frame_info, RX_FINFO_LEN);
// uint32_t rx_buffer_len;
// rx_buffer_len = rx_frame_info & RX_FINFO_RXFLEN_MASK ; // No shifting required
// trace_printf("%d\n", rx_buffer_len);
// xHigherPriorityTaskWoken |= receiveCB(rx_buffer_len);
// uint32_t sys_ctrl = 0;
// //dw1000Hal_resetRxOnly();
// dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t*)&sys_ctrl, SYS_CTRL_LEN); // switch to rx mode
// sys_ctrl |= SYS_CTRL_RXENAB;
// dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t*)&sys_ctrl, SYS_CTRL_LEN);
// }
// if (event & SYS_STATUS_RXSFDD){ // Frame received
// event_clear |= SYS_STATUS_RXSFDD; //clear interrupt
// // trace_printf("dw1000Hal_extiCallback: sfd detected\n");
// uint32_t sys_ctrl = 0;
// dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t*)&sys_ctrl, SYS_CTRL_LEN); // switch to rx mode
// sys_ctrl |= SYS_CTRL_RXENAB;
// dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t*)&sys_ctrl, SYS_CTRL_LEN);
// }
// if (event & SYS_STATUS_RXPRD){ // Frame received
// event_clear |= SYS_STATUS_RXPRD; //clear interrupt
// // trace_printf("dw1000Hal_extiCallback:preamble detected \n");
// uint32_t sys_ctrl = 0;
// dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t*)&sys_ctrl, SYS_CTRL_LEN); // switch to rx mode
// sys_ctrl |= SYS_CTRL_RXENAB;
// dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t*)&sys_ctrl, SYS_CTRL_LEN);
// }
// if (event & SYS_STATUS_RXPHD){ // Frame received
// event_clear |= SYS_STATUS_RXPHD; //clear interrupt
// //trace_printf("dw1000Hal_extiCallback:PHR detected\n");
// uint32_t sys_ctrl = 0;
// dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t*)&sys_ctrl, SYS_CTRL_LEN); // switch to rx mode
// sys_ctrl |= SYS_CTRL_RXENAB;
// dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t*)&sys_ctrl, SYS_CTRL_LEN);
// }
// if (event & SYS_STATUS_RXFCG) { // Frame received
// event_clear = 0x6F00; //clear interrupt
//
// trace_printf("dw1000Hal_extiCallback: CRC stuff %lu\n");
// uint32_t sys_ctrl = 0;
// dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t*) &sys_ctrl,
// SYS_CTRL_LEN); // switch to rx mode
// sys_ctrl |= SYS_CTRL_RXENAB;
// dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t*) &sys_ctrl,
// SYS_CTRL_LEN);
// }
//Clear the status register
dw1000Hal_writeRegisterFromIsr(SYS_STATUS_ID, (uint8_t*) &event_clear,
SYS_STATUS_LEN);
//Schedule higher priority task ASAP
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
//trace_printf("ISR DONE\n");
}
......@@ -2,6 +2,9 @@
#include "dw1000_hal.h"
#include "dw1000_util.h"
#include <stdio.h>
#include "Trace.h"
extern volatile uint32_t global_time;
dw1000_local_data_t dw1000local; // Static local device data
//-----------------------------------------
......@@ -223,6 +226,19 @@ void dw1000Util_enableclocks(int clocks)
void dw1000Util_enableRX(){
#ifdef DOUBLE_BUFFER
//Align HSRBP and ICRBP if needed (see page 37 in the Usermanual)
uint64_t event = 0;
dw1000Hal_readRegisterFromIsr(SYS_STATUS_ID, (uint8_t*) &event,
SYS_STATUS_LEN);
if((event & SYS_STATUS_HSRBP) != (event & SYS_STATUS_ICRBP)){
uint32_t reg;
dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t *)&reg, SYS_CTRL_LEN);
reg |= SYS_CTRL_HSRBTOGGLE;
dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t *)&reg, SYS_CTRL_LEN);
}
#endif
uint32_t sys_ctrl = 0;
dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t*) &sys_ctrl,
SYS_CTRL_LEN); // switch to rx mode
......@@ -257,12 +273,65 @@ uint32_t dw1000Util_otpread(uint32_t address)
return (ret_data);
}
void dw1000Util_getRxTimestamp(dw1000_global_time_t *time_buffer){
uint8_t buf[5] = {0};
uint64_t radio_rx_time = 0;
// Read rx timestamp from radio
dw1000Hal_readSubRegisterFromIsr(RX_TIME_ID, RX_TIME_RX_STAMP_OFFSET, buf, RX_TIME_RX_STAMP_LEN);
radio_rx_time = ((uint64_t) buf[4]) << 32 |
((uint64_t) buf[3]) << 24 |
((uint64_t) buf[2]) << 16 |
((uint64_t) buf[1]) << 8 |
((uint64_t) buf[0]) << 0;
// multiply by 16 to get picoseconds (actually ~15.65 is right)
radio_rx_time <<= 4;
// Calculate timestamp in milliseconds and sub-milliseconds parts separately
uint64_t ms_buf = global_time * GLOBAL_TIME_TICK_MS + radio_rx_time / 1000000000llu;
uint64_t subms_buf = radio_rx_time - (global_time * 1000000000llu);
if(ms_buf < dw1000local.last_rx_time.ms) {
// The radio timer had an overflow, but the global timer didn't, yet
ms_buf += GLOBAL_TIME_TICK_MS;
}
// Write calculated timestamp to provided structure
time_buffer->ms = ms_buf;
time_buffer->subms = subms_buf;
// Store new timestamp to be able to detect asynchronous overflows
dw1000local.last_rx_time.ms = ms_buf;
}
void lltoa(uint64_t val, char *dest_buf, uint8_t base) {
char buf[64] = {0};
uint32_t i = 62;
for(; val && i ; --i, val /= base) {
buf[i] = "0123456789abcdef"[val % base];
}
memcpy(dest_buf, &buf[i + 1], 64);
}
void dw1000Util_printGlobalTimestamp(dw1000_global_time_t *time) {
char ms_buf[64] = {0};
char subms_buf[64] = {0};
// Convert uint64_t timestamp to strings, because printf can't handle 64-bit integers
lltoa(time->ms, ms_buf, 10);
lltoa(time->subms, subms_buf, 10);
printf("RX time = %s.%sms\n", ms_buf, subms_buf);
}
void dw1000Util_forceTrxOff(void) {
uint32_t sys_ctrl = 0;
//DECA: decaIrqStatus_t stat ; ???
uint32_t sys_mask;
dw1000Hal_readRegister(SYS_MASK_ID, (uint8_t *) &sys_mask, SYS_MASK_LEN);
dw1000Hal_readRegisterFromIsr(SYS_MASK_ID, (uint8_t *) &sys_mask, SYS_MASK_LEN);
// need to beware of interrupts occurring in the middle of following read modify write cycle
......@@ -274,20 +343,20 @@ void dw1000Util_forceTrxOff(void) {
uint32_t tmp_mask = 0;
// No interrupts
dw1000Hal_writeRegister(SYS_MASK_ID, (uint8_t *) &tmp_mask, SYS_MASK_LEN);
dw1000Hal_writeRegisterFromIsr(SYS_MASK_ID, (uint8_t *) &tmp_mask, SYS_MASK_LEN);
//Disable radio
dw1000Hal_readRegister(SYS_CTRL_ID, (uint8_t *) &sys_ctrl, 4);
dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t *) &sys_ctrl, 4);
sys_ctrl |= SYS_CTRL_TRXOFF;// Immediately cancel all RX and TX operations, bring radio to IDLE state
dw1000Hal_writeRegister(SYS_CTRL_ID, (uint8_t *) &sys_ctrl, 4);
dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t *) &sys_ctrl, 4);
uint32_t tmp = (CLEAR_ALLTX_EVENTS | CLEAR_ALLRXERROR_EVENTS | CLEAR_ALLRXGOOD_EVENTS);
dw1000Hal_writeRegister(SYS_STATUS_ID,(uint8_t *) &tmp, 4) ;
dw1000Hal_writeRegisterFromIsr(SYS_STATUS_ID,(uint8_t *) &tmp, 4) ;
//TODO dwt_syncrxbufptrs();
dw1000Hal_writeRegister(SYS_MASK_ID, (uint8_t *) &sys_mask, SYS_MASK_LEN);
dw1000Hal_writeRegisterFromIsr(SYS_MASK_ID, (uint8_t *) &sys_mask, SYS_MASK_LEN);
portENABLE_INTERRUPTS();
......
CFLAGS+=-I"Inc" -I"dw1000/Inc/"
SRC+=$(wildcard dw1000/Src/*.c)
\ No newline at end of file