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 (21)
#ifndef __dw1000_H
#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
#define DWT_PRESRV_SLEEP 0x0100 // PRES_SLEEP - on wakeup preserve sleep bit
#define DWT_LOADOPSET 0x0080 // ONW_L64P - on wakeup load operating parameter set for 64 PSR
#define DWT_CONFIG 0x0040 // ONW_LDC - on wakeup restore (load) the saved configurations (from AON array into HIF)
#define DWT_TANDV 0x0001 // ONW_RADC - on wakeup run ADC to sample temperature and voltage sensor values
#define DWT_XTAL_EN 0x10 // keep XTAL running during sleep
#define DWT_WAKE_SLPCNT 0x8 // wake up after sleep count
#define DWT_WAKE_CS 0x4 // wake up on chip select
#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
#define DWT_LOADANTDLY 0x2
#define DWT_LOADXTALTRIM 0x1
#define DWT_LOADNONE 0x0
//DECA:DW1000 OTP operating parameter set selection
#define DWT_OPSET_64LEN 0x0
#define DWT_OPSET_TIGHT 0x1
#define DWT_OPSET_DEFLT 0x2
#define DWT_SFDTOC_DEF 0x1041 // default SFD timeout value
#define DWT_PHRMODE_STD 0x0 // standard PHR mode
#define DWT_PHRMODE_EXT 0x3 // DW proprietary extended frames PHR mode
//! constants for selecting the bit rate for data TX (and RX)
//! These are defined for write (with just a shift) the TX_FCTRL register
#define DWT_BR_110K 0 //!< UWB bit rate 110 kbits/s
#define DWT_BR_850K 1 //!< UWB bit rate 850 kbits/s
#define DWT_BR_6M8 2 //!< UWB bit rate 6.8 Mbits/s
//! constants for specifying the (Nominal) mean Pulse Repetition Frequency
//! These are defined for direct write (with a shift if necessary) to CHAN_CTRL and TX_FCTRL regs
#define DWT_PRF_16M 1 //!< UWB PRF 16 MHz
#define DWT_PRF_64M 2 //!< UWB PRF 64 MHz
//! constants for specifying Preamble Acquisition Chunk (PAC) Size in symbols
#define DWT_PAC8 0 //!< PAC 8 (recommended for RX of preamble length 128 and below
#define DWT_PAC16 1 //!< PAC 16 (recommended for RX of preamble length 256
#define DWT_PAC32 2 //!< PAC 32 (recommended for RX of preamble length 512
#define DWT_PAC64 3 //!< PAC 64 (recommended for RX of preamble length 1024 and up
//! constants for specifying TX Preamble length in symbols
//! These are defined to allow them be directly written into byte 2 of the TX_FCTRL register
//! (i.e. a four bit value destined for bits 20..18 but shifted left by 2 for byte alignment)
#define DWT_PLEN_4096 0x0C //! Standard preamble length 4096 symbols
#define DWT_PLEN_2048 0x28 //! Non-standard preamble length 2048 symbols
#define DWT_PLEN_1536 0x18 //! Non-standard preamble length 1536 symbols
#define DWT_PLEN_1024 0x08 //! Standard preamble length 1024 symbols
#define DWT_PLEN_512 0x34 //! Non-standard preamble length 512 symbols
#define DWT_PLEN_256 0x24 //! Non-standard preamble length 256 symbols
#define DWT_PLEN_128 0x14 //! Non-standard preamble length 128 symbols
#define DWT_PLEN_64 0x04 //! Standard preamble length 64 symbols
typedef struct {
uint8_t chan; //!< channel number {1, 2, 3, 4, 5, 7 }
uint8_t prf; //!< Pulse Repetition Frequency {DWT_PRF_16M or DWT_PRF_64M}
uint8_t txPreambLength; //!< DWT_PLEN_64..DWT_PLEN_4096
uint8_t rxPAC; //!< Acquisition Chunk Size (Relates to RX preamble length)
uint8_t txCode; //!< TX preamble code
uint8_t rxCode; //!< RX preamble code
uint8_t nsSFD; //!< Boolean should we use non-standard SFD for better performance
uint8_t dataRate; //!< Data Rate {DWT_BR_110K, DWT_BR_850K or DWT_BR_6M8}
uint8_t phrMode; //!< PHR mode {0x0 - standard DWT_PHRMODE_STD, 0x3 - extended frames DWT_PHRMODE_EXT}
uint8_t smartPowerEn; //!< Smart Power enable / disable
uint16_t sfdTO; //!< SFD timeout value (in symbols)
} dwt_config_t;
int dw1000_init(uint16_t config, BaseType_t (*sendCallback)(),
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
#ifndef __dw1000_hal_H
#define __dw1000_hal_H
#include "FreeRTOS.h"
#include "task.h"
#define DW1000HAL_SPI_TIMEOUT 10
......@@ -8,15 +10,15 @@
#define DW1000HAL_SS_GPIO GPIOB
#include <stdint.h>
void dw1000Hal_init(void);
int dw1000Hal_readSubRegister(uint8_t regID, uint16_t offset, uint8_t *dest, uint16_t len);
int dw1000Hal_writeSubRegister(uint8_t regID, uint16_t offset, uint8_t *src, uint16_t len);
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));
void vTaskDW1000HAL(void *pvParameters);
void dw1000Hal_extiCallback(void);
#endif /*__ dw1000_hal_H */
#ifndef __dw1000_isr_H
#define __dw1000_isr_H
#include "FreeRTOS.h"
#include <stdint.h>
void dw1000Isr_handleInterrupt(void);
#endif /*__ dw1000_isr_H */
#ifndef __dw1000_util_H
#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
#define ENABLE_ALL_SEQ 1
#define FORCE_SYS_PLL 2
#define READ_ACC_ON 7
#define READ_ACC_OFF 8
#define FORCE_OTP_ON 11
#define FORCE_OTP_OFF 12
#define FORCE_TX_PLL 13
#define PEAK_MULTPLIER (0x60) //3 -> (0x3 * 32) & 0x00E0
#define N_STD_FACTOR (13)
#define LDE_PARAM1 (PEAK_MULTPLIER | N_STD_FACTOR)
#define LDE_PARAM3_16 (0x1607)
#define LDE_PARAM3_64 (0x0607)
#define NUM_BR 3
#define NUM_PRF 2
#define NUM_PACS 4
#define NUM_BW 2 //2 bandwidths are supported
#define NUM_SFD 2 //supported number of SFDs - standard = 0, non-standard = 1
#define NUM_CH 6 //supported channels are 1, 2, 3, 4, 5, 7
#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")
uint16_t rftxDly; // rf delay (delay though the RF blocks before the signal comes out of the antenna i.e. "antenna delay")
uint32_t antennaDly; // antenna delay read from OTP 64 PRF value is in high 16 bits and 16M PRF in low 16 bits
uint8_t xtrim; // xtrim value read from OTP
uint8_t dblbuffon; // double rx buffer mode flag
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, 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 const uint8_t pll2calcfg;
// SFD Threshold
extern const uint16_t sftsh[NUM_BR][NUM_SFD];
extern const uint16_t dtune1[NUM_PRF];
//-----------------------------------------
// map the channel number to the index in the configuration arrays below
// 0th element is chan 1, 1st is chan 2, 2nd is chan 3, 3rd is chan 4, 4th is chan 5, 5th is chan 7
extern const uint8_t chan_idx[NUM_CH_SUPPORTED];
extern const uint32_t tx_config[NUM_CH] ;
extern const uint8_t pll2_config[NUM_CH][5];
//bandwidth configuration
extern const uint8_t rx_config[NUM_BW];
extern const uint8_t dwnsSFDlen[NUM_BR]; //DW non-standard SFD length for 110k, 850k and 6.81M
extern const uint32_t digital_bb_config[NUM_PRF][NUM_PACS];
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);
#endif
#endif /*__ dw1000_util_H */
#include "dw1000.h"
#include "dw1000_hal.h"
#include "dw1000_isr.h"
#include "deca_regs.h"
#include "Trace.h"
#define LDOTUNE_ADDRESS (0x04)
#define PARTID_ADDRESS (0x06)
#define LOTID_ADDRESS (0x07)
#define VBAT_ADDRESS (0x08)
#define VTEMP_ADDRESS (0x09)
#define TXCFG_ADDRESS (0x10)
#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, uint8_t ts_valid)) {
// Clear control-structure
//memset(&dw1000local, 0, sizeof(dw1000_local_data_t));
// Callbacks
dw1000local.sendCB = sendCallback;
dw1000local.receiveCB = receiveCallback;
// Initialize HAL
dw1000Hal_init();
// Soft-Reset
dw1000Util_reset();
// Set allowed interrupts
// TODO: MLDEDONE
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_MLDEDONE);
trace_printf("SYS_MASK: %x\n", sys_mask);
dw1000Hal_writeRegister(SYS_MASK_ID, (uint8_t *) &sys_mask, SYS_MASK_LEN);
//set TX LED
uint32_t gpio = 0x5540; //equiv to MSGP0 = 01, MSGP1 = 01, MSGP2 = 01, MSGP3 = 01, enables LED for rec and sending
dw1000Hal_writeSubRegister(GPIO_CTRL_ID, GPIO_MODE_OFFSET, (uint8_t*) &gpio,
GPIO_MODE_LEN);
uint32_t led = 0;
dw1000Hal_readSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &led,
PMSC_CTRL0_LEN);
led |= (1 << 18) | (1 << 23); // Preparing LEDs for blink mode
dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &led,
PMSC_CTRL0_LEN);
dw1000Hal_readSubRegister(PMSC_ID, PMSC_LEDC_OFFSET, (uint8_t*) &led,
PMSC_LEDC_LEN);
led |= PMSC_LEDC_BLNKEN; // enable blink mode
led |= 0xF0000; // force leds to blink once
dw1000Hal_writeSubRegister(PMSC_ID, PMSC_LEDC_OFFSET, (uint8_t*) &led,
PMSC_LEDC_LEN);
led &= ~0xF0000; // reset froce blink bits. needed to make the leds blinking
dw1000Hal_writeSubRegister(PMSC_ID, PMSC_LEDC_OFFSET, (uint8_t*) &led,
PMSC_LEDC_LEN);
//DECA: set system clock to XTI - this is necessary to make sure the values read by _dwt_otpread are reliable
dw1000Util_enableclocks(FORCE_SYS_XTI);
if(config & DWT_LOADLDOTUNE)
{
dw1000local.ldoTune = dw1000Util_otpread(LDOTUNE_ADDRESS);
}
if ((dw1000local.ldoTune & 0xFF) != 0) //LDO tune values are stored in the OTP
{
uint8_t ldok = OTP_SF_LDO_KICK;
//kick LDO tune
// dwt_writetodevice(OTP_IF_ID, OTP_SF, 1, &ldok); // set load LDO kick bit
dw1000Hal_writeSubRegister(OTP_IF_ID, OTP_SF, &ldok, 1);
} else {
dw1000local.ldoTune = 0;
}
/* TODO: partID, lotID sinnvoll?
dw1000local.partID = _dwt_otpread(PARTID_ADDRESS);
dw1000local.lotID = _dwt_otpread(LOTID_ADDRESS);
*/
// load leading edge detect code
if (config & DWT_LOADUCODE) {
uint8_t wr_buf[2];
//set up clocks
wr_buf[1] = 0x03; //Force TX clock off.
wr_buf[0] = 0x01; //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
//kick off the LDE load
//DECA:dwt_write16bitoffsetreg(OTP_IF_ID, OTP_CTRL, OTP_CTRL_LDELOAD); // set load LDE kick bit
uint16_t otp_ctrl_ldeload = OTP_CTRL_LDELOAD;
dw1000Hal_writeSubRegister(OTP_IF_ID, OTP_CTRL,
(uint8_t *) &otp_ctrl_ldeload, 2);
//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);
} else //should disable the LDERUN enable bit in 0x36, 0x4
{
//DECA: uint16_t rega = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1) ;
uint32_t reg = 0;
dw1000Hal_readSubRegister(PMSC_ID, PMSC_CTRL1_OFFSET, (uint8_t *) &reg,
PMSC_CTRL1_LEN);
//clear LDERUN bit
reg &= 0xFFFDFFFF;
dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL1_OFFSET, (uint8_t *) &reg,
PMSC_CTRL1_LEN);
}
//DECA:enable clocks for sequencing
//Very important! Not sending on FORCE_SYS_XTI
dw1000Util_enableclocks(ENABLE_ALL_SEQ);
//DECA: read system register / store local copy
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
//Enable Receiver
dw1000Util_enableRX();
uint32_t event_clear = 0xFFFFFFFF;
dw1000Hal_writeRegister(SYS_STATUS_ID, (uint8_t*) &event_clear,
SYS_STATUS_LEN);
return 0;
}
int dw1000_configure(dwt_config_t *config, uint8_t use_otpconfigvalues) {
uint8_t nsSfd_result = 0;
uint8_t useDWnsSFD = 0;
uint8_t chan = config->chan;
uint32_t regval;
uint16_t reg16 = lde_replicaCoeff[config->rxCode];
uint8_t prfIndex = dw1000local.prfIndex = config->prf - DWT_PRF_16M;
uint8_t bw = ((chan == 4) || (chan == 7)) ? 1 : 0; //select wide or narrow band
dw1000local.chan = config->chan;
// DECA: for 110 kbps we need to special setup
if (DWT_BR_110K == config->dataRate) {
dw1000local.sysCFGreg |= SYS_CFG_RXM110K;
reg16 >>= 3; //div by 8 According to Page 170
} else {
dw1000local.sysCFGreg &= (~SYS_CFG_RXM110K);
}
dw1000local.longFrames = config->phrMode;
dw1000local.sysCFGreg |= (SYS_CFG_PHR_MODE_11 & (config->phrMode << 16)); //Set to enable PhyHdr for long frames
dw1000local.sysCFGreg |= (SYS_CFG_RXAUTR); //Automatic reenable of the receiver
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,
2); //Page 169
//configure LDE algorithm parameters
uint8_t x = LDE_PARAM1; //TODO WHAT??
/*8-bit configuration register*/
dw1000Hal_writeSubRegister(LDE_IF_ID, LDE_CFG1_OFFSET, &x, 1);
uint16_t lde_param3;
if (prfIndex) {
lde_param3 = (uint16_t) LDE_PARAM3_64;
} else {
lde_param3 = (uint16_t) LDE_PARAM3_16;
}
dw1000Hal_writeSubRegister(LDE_IF_ID, LDE_CFG2_OFFSET,
(uint8_t *) &lde_param3, 2);
// config RF pll (for a given channel)
// configure PLL2/RF PLL block CFG
//DECA: dwt_writetodevice(FS_CTRL_ID, FS_PLLCFG_OFFSET, 5, &pll2_config[chan_idx[chan]][0]);
//Configure FS_PLLTUNE too
dw1000Hal_writeSubRegister(FS_CTRL_ID, FS_PLLCFG_OFFSET,
(uint8_t *) &pll2_config[chan_idx[chan]][0], FS_PLLCFG_LEN);
//DECA: configure PLL2/RF PLL block CAL
//Crystal Oscillator Trim
dw1000Hal_writeSubRegister(FS_CTRL_ID, FS_XTALT_OFFSET,
(uint8_t *) &pll2calcfg, 1);
//DECA: Configure RF RX blocks (for specified channel/bandwidth)
dw1000Hal_writeSubRegister(RF_CONF_ID, RF_RXCTRLH_OFFSET,
(uint8_t *) &rx_config[bw], 1);
//DECA: Configure RF TX blocks (for specified channel and prf)
//DECA: Config RF TX control
dw1000Hal_writeSubRegister(RF_CONF_ID, RF_TXCTRL_OFFSET,
(uint8_t *) &tx_config[chan_idx[chan]], RF_TXCTRL_LEN);
//DECA: Configure the baseband parameters (for specified prf, bit rate, pac, and SFD settings)
//DECA:DTUNE0
dw1000Hal_writeSubRegister(DRX_CONF_ID, DRX_TUNE0b_OFFSET,
(uint8_t *) &sftsh[config->dataRate][config->nsSFD],
DRX_TUNE0b_LEN);
//DTUNE1 FIXME: Führt zu Abbruch vom Senden, bei zulangen ISR oder zu vielen interrupts
dw1000Hal_writeSubRegister(DRX_CONF_ID, DRX_TUNE1a_OFFSET,
(uint8_t *) &dtune1[prfIndex], DRX_TUNE1a_LEN);
if (config->dataRate == DWT_BR_110K) {
uint16_t reg = 0x64;
dw1000Hal_writeSubRegister(DRX_CONF_ID, DRX_TUNE1b_OFFSET,
(uint8_t *) &reg, DRX_TUNE1b_LEN);
//TODO: Hier kein DRX_DRX_TUNE4HOFFSET setzen?
} else {
if (config->txPreambLength == DWT_PLEN_64) //if preamble length is 64
{
uint8_t temp = 0x10;
dw1000Hal_writeSubRegister(DRX_CONF_ID, DRX_TUNE1b_OFFSET,
(uint8_t *) &temp, DRX_TUNE1b_LEN);
dw1000Hal_writeSubRegister(DRX_CONF_ID, DRX_DRX_TUNE4HOFFSET,
(uint8_t *) &temp, 1);
} else {
uint8_t temp = 0x20;
//DECA: dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, 0x20);
dw1000Hal_writeSubRegister(DRX_CONF_ID, DRX_TUNE1b_OFFSET,
(uint8_t *) &temp, DRX_TUNE1b_LEN);
temp = 0x28;
//DECA: dwt_writetodevice(DRX_CONF_ID, 0x26, 1, &temp);
dw1000Hal_writeSubRegister(DRX_CONF_ID, DRX_DRX_TUNE4HOFFSET,
(uint8_t *) &temp, 1);
}
}
// //DTUNE2
// dw1000Hal_writeSubRegister(DRX_CONF_ID, DRX_TUNE2_OFFSET,
// (uint8_t *) &digital_bb_config[prfIndex][config->rxPAC],
// DRX_TUNE2_LEN);
//
// uint32_t temp;
// dw1000Hal_readSubRegister(DRX_CONF_ID, DRX_TUNE2_OFFSET,
// (uint8_t *) &temp,
// DRX_TUNE2_LEN);
//
////#ifdef DEBUG
//// hexdump(&temp, 4);
////#endif
//DTUNE3 set SFD detection timeout count
if (config->sfdTO != DWT_SFDTOC_DEF) { //if default value no need to program it
dw1000Hal_writeSubRegister(DRX_CONF_ID, DRX_SFDTOC_OFFSET,
(uint8_t *) &config->sfdTO, DRX_SFDTOC_LEN);
}
//don't allow 0 - SFD timeout will always be enabled
if (config->sfdTO == 0) {
uint16_t tmp = DWT_SFDTOC_DEF;
dw1000Hal_writeSubRegister(DRX_CONF_ID, DRX_SFDTOC_OFFSET,
(uint8_t *) &tmp, DRX_SFDTOC_LEN);
}
/* TODO notwendig? was tut dies?
// configure AGC parameters
dwt_write32bitoffsetreg( AGC_CFG_STS_ID, 0xC, agc_config.lo32);
dwt_write16bitoffsetreg( AGC_CFG_STS_ID, 0x4, agc_config.target[prfIndex]);
*/
//DECA: set (non-standard) user SFD for improved performance,
if (config->nsSFD) {
//Write non standard (DW) SFD length
dw1000Hal_writeSubRegister(USR_SFD_ID, 0x00,
(uint8_t *) &dwnsSFDlen[config->dataRate], 1);
nsSfd_result = 3;
useDWnsSFD = 1;
}
//Set CHAN_CTRL, Channel Number etc
regval = (CHAN_CTRL_TX_CHAN_MASK & (chan << CHAN_CTRL_TX_CHAN_SHIFT)) | // Transmit Channel
(CHAN_CTRL_RX_CHAN_MASK & (chan << CHAN_CTRL_RX_CHAN_SHIFT)) | // Receive Channel
(CHAN_CTRL_RXFPRF_MASK & (config->prf << CHAN_CTRL_RXFPRF_SHIFT)) | // RX PRF
((CHAN_CTRL_TNSSFD | CHAN_CTRL_RNSSFD)
& (nsSfd_result << CHAN_CTRL_TNSSFD_SHIFT)) | // nsSFD enable RX&TX
(CHAN_CTRL_DWSFD & (useDWnsSFD << CHAN_CTRL_DWSFD_SHIFT)) | // use DW nsSFD
(CHAN_CTRL_TX_PCOD_MASK
& (config->txCode << CHAN_CTRL_TX_PCOD_SHIFT)) | // TX Preamble Code
(CHAN_CTRL_RX_PCOD_MASK
& (config->rxCode << CHAN_CTRL_RX_PCOD_SHIFT)); // RX Preamble Code
dw1000Hal_writeRegister(CHAN_CTRL_ID, (uint8_t *) &regval, CHAN_CTRL_LEN);
// Set up TX Preamble Size and TX PRF
// Set up TX Ranging Bit and Data Rate
{
uint32_t x = (config->txPreambLength | config->prf) << 16;
dw1000local.txFCTRL = x | TX_FCTRL_TR | /* always set ranging bit !!! */
(config->dataRate << TX_FCTRL_TXBR_SHFT);
//Transmit Frame Control
dw1000Hal_writeRegister(TX_FCTRL_ID, (uint8_t *) &dw1000local.txFCTRL,
TX_FCTRL_LEN - 1); // Just first 4 byte
}
if (use_otpconfigvalues & DWT_LOADXTALTRIM) {
//This is used adjust the crystal frequency
uint8_t write_buf;
//DECA: dwt_readfromdevice(FS_CTRL_ID,FS_XTALT_OFFSET,1,&write_buf);
dw1000Hal_readSubRegister(FS_CTRL_ID, FS_XTALT_OFFSET, &write_buf,
FS_XTALT_LEN);
write_buf &= ~FS_XTALT_MASK;
write_buf |= (FS_XTALT_MASK & dw1000local.xtrim); // we should not change high bits, cause it will cause malfunction
dw1000Hal_writeSubRegister(FS_CTRL_ID, FS_XTALT_OFFSET, &write_buf,
FS_XTALT_LEN);
}
/* TODO notwendig?
if (use_otpconfigvalues & DWT_LOADANTDLY)
{
//put half of the antenna delay value into tx and half into rx
dwt_setrxantennadelay(((dw1000local.antennaDly >> (16*prfIndex)) & 0xFFFF) >> 1);
dwt_settxantennadelay(((dw1000local.antennaDly >> (16*prfIndex)) & 0xFFFF) >> 1);
}
*/
return 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 DW1000_RET_TX_BUFFER_OVERFLOW;
}
// write tx data to data buffer
// this buffer only contains the payload, PHR is generated by the chip
// the chip automatically appends two FCS (CRC) bytes to this payload
dw1000Hal_writeRegister(TX_BUFFER_ID, payload, len);
// configure tx parameters
uint32_t tx_fctrl_low = 0;
uint8_t tx_fctrl_high = 0;
// configure low 32 bits
tx_fctrl_low |= ( (len+2) & TX_FCTRL_FLE_MASK); // set frame length
// this is two bytes more than the desired payload due to addition of the FCS/CRC
tx_fctrl_low |= TX_FCTRL_TXBR_110k; // transmit bit rate
// transmit ranging disabled
tx_fctrl_low |= TX_FCTRL_TXPRF_64M; // transmit pulse repetition frequency
// 64 MHz gives more accuracy on first path timestamp and slightly improved operating range but needs more power
tx_fctrl_low |= TX_FCTRL_TXPSR_PE_4096; // 4096 preamble length for maximum range
// this also configures the PE bits
// TXBOFFS is not used (0)
// configure high 8 bits
// IFSDELAY is not used
// write to TX_FCTRL
dw1000Hal_writeSubRegister(TX_FCTRL_ID, 0, &tx_fctrl_low, 4);
dw1000Hal_writeSubRegister(TX_FCTRL_ID, 4, &tx_fctrl_high, 1);
// start tx
// set up a complete config for the register
// the bits are cleared automatically after the transmission and need to be set up for the next transmission again!
uint32_t sys_ctrl = 0;
dw1000Hal_readRegister(SYS_CTRL_ID, &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, &sys_ctrl, 4);
sys_ctrl = 0;
// SFCST not set -> automatic CRC calculation
sys_ctrl |= SYS_CTRL_TXSTRT; // start transmission
// TXDLYS not set -> no delayed transmission
// CANSFCS not set (only useful when starting transmission before uploading payload)
// TRXOFF not set (this would turn off the transmitter immediately)
//sys_ctrl |= SYS_CTRL_WAIT4RESP; // turn on receiver after transmission to receive a response (ACK)
// RXENAB not set (this would enter receive mode)
// RXDLYE not set (used for delayed reception)
// HRBPT not set (chooses receive buffer)
// write to SYS_CTRL
dw1000Hal_writeRegister(SYS_CTRL_ID, &sys_ctrl, 4);
// wait for completion
// read SYS_STATUS
// check for TXFRS bit set
uint32_t sys_status = 0;
//do {
// dw1000Hal_readRegister(SYS_STATUS_ID, &sys_status, 4);
//} while (!(sys_status & SYS_STATUS_TXFRS));
// return status
//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);
/* 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;
}
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();
}
int dw_1000_receiveFrameFromIsr(uint8_t * buffer, uint32_t length) {
dw1000Hal_readRegisterFromIsr(RX_BUFFER_ID, buffer, length); //FromIsr important!
trace_printf("%d\n", buffer[0]);
return 0;
}
int dw1000_setPanAddr(uint16_t addr) {
return dw1000Hal_writeSubRegister(PANADR_ID, PANADR_SHORT_ADDR_OFFSET,
(uint8_t*) &addr, PANADR_SHORT_ADDR_LEN);
}
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;
}
......@@ -16,38 +16,31 @@ static void (*spiCallback)(int state, void *data, uint16_t len);
static void *spiCallbackData;
static SemaphoreHandle_t spiSema = NULL; //semaphore for SPI access
void dw1000Hal_reset(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/*Configure GPIO pin : PD7 */
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
void dw1000Hal_init(){
hspi = &hspi1;
spiSema = xSemaphoreCreateMutex(); //creating semaphore for SPI access
}
void dw1000Hal_chipSelect(void)
{
/**********************************************
* Read/Write Register/Subregister
*/
void dw1000Hal_chipSelect(void) {
HAL_GPIO_WritePin(DW1000HAL_SS_GPIO, DW1000HAL_SS_PIN, GPIO_PIN_RESET);
}
void dw1000Hal_chipDeselect(void)
{
void dw1000Hal_chipDeselect(void) {
HAL_GPIO_WritePin(DW1000HAL_SS_GPIO, DW1000HAL_SS_PIN, GPIO_PIN_SET);
}
int dw1000Hal_readSubRegister(uint8_t regID, uint16_t offset, uint8_t *dest, uint16_t len)
{
int dw1000Hal_readSubRegister(uint8_t regID, uint16_t offset, uint8_t *dest,
uint16_t len) {
uint8_t dummy[3];
int ret;
portENTER_CRITICAL();
if ((spiSema != NULL) && (xSemaphoreTake(spiSema, ( TickType_t ) DW1000HAL_SPI_TIMEOUT) == pdTRUE)) {
if ((spiSema != NULL)
&& (xSemaphoreTake(spiSema, ( TickType_t ) DW1000HAL_SPI_TIMEOUT)
== pdTRUE)) {
if (len <= 127) {
dummy[0] = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
dummy[0] |= 0x40; // subregister offset follows in second byte
......@@ -66,7 +59,8 @@ int dw1000Hal_readSubRegister(uint8_t regID, uint16_t offset, uint8_t *dest, uin
ret = HAL_SPI_Receive(hspi, dest, len, DW1000HAL_SPI_TIMEOUT);
}
dw1000Hal_chipDeselect();
while (hspi->State != HAL_SPI_STATE_READY);
while (hspi->State != HAL_SPI_STATE_READY)
;
xSemaphoreGive(spiSema);
} else {
ret = HAL_LOCKED;
......@@ -75,12 +69,49 @@ int dw1000Hal_readSubRegister(uint8_t regID, uint16_t offset, uint8_t *dest, uin
return ret;
}
int dw1000Hal_writeSubRegister(uint8_t regID, uint16_t offset, uint8_t *src, uint16_t len)
{
int dw1000Hal_readSubRegisterFromIsr(uint8_t regID, uint16_t offset,
uint8_t *dest, uint16_t len) {
uint8_t dummy[3];
int ret;
//portENTER_CRITICAL();
if ((spiSema != NULL)
&& (xSemaphoreTakeFromISR(spiSema, pdFALSE)
== pdTRUE)) {
if (len <= 127) {
dummy[0] = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
dummy[0] |= 0x40; // subregister offset follows in second byte
dummy[1] = offset & 0x7f; // set first bit 0 ( no third byte present)
dw1000Hal_chipSelect();
ret = HAL_SPI_Transmit(hspi, dummy, 2, DW1000HAL_SPI_TIMEOUT);
} else {
dummy[0] = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
dummy[0] |= 0x40; // subregister offset follows in second byte
dummy[1] = 0x80 | (offset & 0x7f); // set first bit 1 ( third byte present)
dummy[2] = offset >> 7;
dw1000Hal_chipSelect();
ret = HAL_SPI_Transmit(hspi, dummy, 3, DW1000HAL_SPI_TIMEOUT);
}
if (ret == HAL_OK) {
ret = HAL_SPI_Receive(hspi, dest, len, DW1000HAL_SPI_TIMEOUT);
}
dw1000Hal_chipDeselect();
while (hspi->State != HAL_SPI_STATE_READY)
;
xSemaphoreGiveFromISR(spiSema, pdFALSE);
} else {
ret = HAL_LOCKED;
}
//portEXIT_CRITICAL();
return ret;
}
int dw1000Hal_writeSubRegister(uint8_t regID, uint16_t offset, uint8_t *src,
uint16_t len) {
uint8_t dummy[3];
int ret;
portENTER_CRITICAL();
if ((spiSema != NULL) && (xSemaphoreTake(spiSema, ( TickType_t ) DW1000HAL_SPI_TIMEOUT) == pdTRUE)) {
if ((spiSema != NULL)
&& (xSemaphoreTakeFromISR(spiSema, pdFALSE) == pdTRUE)) {
if (len <= 127) {
dummy[0] = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
dummy[0] |= 0xC0; //write access, subregister offset follows in second byte
......@@ -100,8 +131,9 @@ int dw1000Hal_writeSubRegister(uint8_t regID, uint16_t offset, uint8_t *src, uin
ret = HAL_SPI_Transmit(hspi, src, len, DW1000HAL_SPI_TIMEOUT);
}
dw1000Hal_chipDeselect();
while (hspi->State != HAL_SPI_STATE_READY);
xSemaphoreGive(spiSema);
while (hspi->State != HAL_SPI_STATE_READY)
;
xSemaphoreGiveFromISR(spiSema, pdFALSE);
} else {
ret = HAL_LOCKED;
}
......@@ -109,8 +141,43 @@ int dw1000Hal_writeSubRegister(uint8_t regID, uint16_t offset, uint8_t *src, uin
return ret;
}
int dw1000Hal_readRegister(uint8_t regID, uint8_t *dest, uint16_t len)
{
int dw1000Hal_writeSubRegisterFromIsr(uint8_t regID, uint16_t offset,
uint8_t *src, uint16_t len) {
uint8_t dummy[3];
int ret;
//portENTER_CRITICAL();
if ((spiSema != NULL)
&& (xSemaphoreTakeFromISR(spiSema, pdFALSE) == pdTRUE)) {
if (len <= 127) {
dummy[0] = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
dummy[0] |= 0xC0; //write access, subregister offset follows in second byte
dummy[1] = offset & 0x7f; // set first bit 0 ( no third byte present)
dw1000Hal_chipSelect();
ret = HAL_SPI_Transmit(hspi, dummy, 2, DW1000HAL_SPI_TIMEOUT);
} else {
dummy[0] = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
dummy[0] |= 0xC0; //write access, subregister offset follows in second byte
dummy[1] = 0x80 | (offset & 0x7f); // set first bit 1 ( third byte present)
dummy[2] = offset >> 7;
dw1000Hal_chipSelect();
ret = HAL_SPI_Transmit(hspi, dummy, 3, DW1000HAL_SPI_TIMEOUT);
}
if (ret == HAL_OK) {
ret = HAL_SPI_Transmit(hspi, src, len, DW1000HAL_SPI_TIMEOUT);
}
dw1000Hal_chipDeselect();
while (hspi->State != HAL_SPI_STATE_READY)
;
xSemaphoreGiveFromISR(spiSema, pdFALSE);
} else {
ret = HAL_LOCKED;
}
//portEXIT_CRITICAL();
return ret;
}
int dw1000Hal_readRegister(uint8_t regID, uint8_t *dest, uint16_t len) {
uint8_t dummy;
dummy = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
int ret;
......@@ -127,18 +194,18 @@ int dw1000Hal_readRegister(uint8_t regID, uint8_t *dest, uint16_t len)
xSemaphoreGive(spiSema);
} else {
ret = HAL_LOCKED;
trace_printf("nb");
//trace_printf("nb");
}
portEXIT_CRITICAL();
return ret;
}
int dw1000Hal_readRegisterFromIsr(uint8_t regID, uint8_t *dest, uint16_t len)
{
int dw1000Hal_readRegisterFromIsr(uint8_t regID, uint8_t *dest, uint16_t len) {
uint8_t dummy;
dummy = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
int ret;
if ((spiSema != NULL) && (xSemaphoreTakeFromISR(spiSema, pdFALSE) == pdTRUE)) {
if ((spiSema != NULL)
&& (xSemaphoreTakeFromISR(spiSema, pdFALSE) == pdTRUE)) {
dw1000Hal_chipSelect();
ret = HAL_SPI_Transmit(hspi, &dummy, 1, DW1000HAL_SPI_TIMEOUT);
if (ret == HAL_OK) {
......@@ -147,15 +214,14 @@ int dw1000Hal_readRegisterFromIsr(uint8_t regID, uint8_t *dest, uint16_t len)
dw1000Hal_chipDeselect();
while (hspi->State != HAL_SPI_STATE_READY) {
}
xSemaphoreGiveFromISR(spiSema,pdFALSE);
xSemaphoreGiveFromISR(spiSema, pdFALSE);
} else {
ret = HAL_LOCKED;
trace_printf("ib");
//trace_printf("ib");
}
return ret;
}
int dw1000Hal_writeRegister(uint8_t regID, uint8_t *src, uint16_t len)
{
int dw1000Hal_writeRegister(uint8_t regID, uint8_t *src, uint16_t len) {
uint8_t dummy;
dummy = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
dummy |= 0x80; //set first byte 1 (write access)
......@@ -173,18 +239,18 @@ int dw1000Hal_writeRegister(uint8_t regID, uint8_t *src, uint16_t len)
xSemaphoreGive(spiSema);
} else {
ret = HAL_LOCKED;
trace_printf("na");
//trace_printf("na");
}
portEXIT_CRITICAL();
return ret;
}
int dw1000Hal_writeRegisterFromIsr(uint8_t regID, uint8_t *src, uint16_t len)
{
int dw1000Hal_writeRegisterFromIsr(uint8_t regID, uint8_t *src, uint16_t len) {
uint8_t dummy;
dummy = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
dummy |= 0x80; //set first byte 1 (write access)
int ret;
if ((spiSema != NULL) && (xSemaphoreTakeFromISR(spiSema, pdFALSE) == pdTRUE)) {
if ((spiSema != NULL)
&& (xSemaphoreTakeFromISR(spiSema, pdFALSE) == pdTRUE)) {
dw1000Hal_chipSelect();
ret = HAL_SPI_Transmit(hspi, &dummy, 1, DW1000HAL_SPI_TIMEOUT);
if (ret == HAL_OK) {
......@@ -193,21 +259,22 @@ int dw1000Hal_writeRegisterFromIsr(uint8_t regID, uint8_t *src, uint16_t len)
dw1000Hal_chipDeselect();
while (hspi->State != HAL_SPI_STATE_READY) {
}
xSemaphoreGiveFromISR(spiSema,pdFALSE);
xSemaphoreGiveFromISR(spiSema, pdFALSE);
} else {
ret = HAL_LOCKED;
trace_printf("ia");
}
return ret;
}
int dw1000Hal_readDmaRegister(uint8_t regID, uint8_t *dest, uint16_t len, void (*callback)(int state, void *data, uint16_t len))
{
int dw1000Hal_readDmaRegister(uint8_t regID, uint8_t *dest, uint16_t len,
void (*callback)(int state, void *data, uint16_t len)) {
uint8_t dummy;
dummy = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
spiCallback = callback;
spiCallbackData = dest;
int ret;
if ((spiSema != NULL) && (xSemaphoreTake(spiSema, ( TickType_t ) DW1000HAL_SPI_TIMEOUT) == pdTRUE)) {
if ((spiSema != NULL)
&& (xSemaphoreTake(spiSema, ( TickType_t ) DW1000HAL_SPI_TIMEOUT)
== pdTRUE)) {
dw1000Hal_chipSelect();
ret = HAL_SPI_Transmit(hspi, &dummy, 1, DW1000HAL_SPI_TIMEOUT);
if (ret == HAL_OK) {
......@@ -222,15 +289,17 @@ int dw1000Hal_readDmaRegister(uint8_t regID, uint8_t *dest, uint16_t len, void (
return ret;
}
int dw1000Hal_writeDmaRegister(uint8_t regID, uint8_t *src, 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)) {
uint8_t dummy;
dummy = regID & 0x3f; //set the first two bit 0 (read access, no subregister)
dummy |= 0x80; //set first byte 1 (write access)
spiCallback = callback;
spiCallbackData = src;
int ret;
if ((spiSema != NULL) && (xSemaphoreTake(spiSema, ( TickType_t ) DW1000HAL_SPI_TIMEOUT) == pdTRUE)) {
if ((spiSema != NULL)
&& (xSemaphoreTake(spiSema, ( TickType_t ) DW1000HAL_SPI_TIMEOUT)
== pdTRUE)) {
dw1000Hal_chipSelect();
ret = HAL_SPI_Transmit(hspi, &dummy, 1, DW1000HAL_SPI_TIMEOUT);
if (ret == HAL_OK) {
......@@ -246,104 +315,38 @@ int dw1000Hal_writeDmaRegister(uint8_t regID, uint8_t *src, uint16_t len, void (
}
void vTaskDW1000HAL(void *pvParameters)
{
hspi = &hspi1;
spiSema = xSemaphoreCreateMutex(); //creating semaphore for SPI access
TickType_t xNextWakeTime;
xNextWakeTime = xTaskGetTickCount();
//Configure the dw1000
dw1000Hal_reset();
uint32_t sys_mask = 0;
dw1000Hal_readRegister(SYS_MASK_ID,&sys_mask,SYS_MASK_LEN);
sys_mask |= ( SYS_MASK_MTXFRS | SYS_MASK_MRXDFR | SYS_MASK_MCPLLLL); /* Mask transmit frame sent event *//* Mask receiver data frame ready event */
//trace_printf("sys_mask %x\n",sys_mask);
dw1000Hal_writeRegister(SYS_MASK_ID,&sys_mask,SYS_MASK_LEN);
//set TX LED
uint32_t gpio = 0x00001000UL;
dw1000Hal_writeSubRegister(GPIO_CTRL_ID,GPIO_MODE_OFFSET,(uint8_t*)&gpio,GPIO_MODE_LEN);
uint32_t led = 0;
dw1000Hal_readSubRegister(PMSC_ID,PMSC_LEDC_OFFSET,(uint8_t*)&led,PMSC_LEDC_LEN);
led |= PMSC_LEDC_BLNKEN;
dw1000Hal_writeSubRegister(PMSC_ID,PMSC_LEDC_OFFSET,(uint8_t*)&led,PMSC_LEDC_LEN);
//uint8_t event_clear[SYS_STATUS_LEN];
//memset(event_clear, 0xff, SYS_STATUS_LEN);
//dw1000Hal_writeRegister(SYS_STATUS_ID, &event_clear, SYS_STATUS_LEN);
uint8_t led_values = 0;
while(1){
vTaskDelayUntil(&xNextWakeTime, 1000/portTICK_PERIOD_MS);
}
vTaskDelete( NULL );
}
/***********************************************************
* Callback functions
*/
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) {
dw1000Hal_chipDeselect();
xSemaphoreGiveFromISR(spiSema, pdFALSE);
if (spiCallback != NULL){
if (spiCallback != NULL) {
spiCallback(HAL_ERROR, 0, hspi->TxXferSize);
}
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
dw1000Hal_chipDeselect();
xSemaphoreGiveFromISR(spiSema, pdFALSE);
if (spiCallback != NULL){
if (spiCallback != NULL) {
spiCallback(HAL_ERROR, 0, hspi->TxXferSize);
}
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) {
dw1000Hal_chipDeselect();
xSemaphoreGiveFromISR(spiSema, pdFALSE);
if (spiCallback != NULL){
if (spiCallback != NULL) {
spiCallback(HAL_ERROR, 0, hspi->TxXferSize);
}
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) {
dw1000Hal_chipDeselect();
xSemaphoreGiveFromISR(spiSema, pdFALSE);
if (spiCallback != NULL){
if (spiCallback != NULL) {
spiCallback(HAL_ERROR, 0, hspi->TxXferSize);
}
}
void dw1000Hal_extiCallback(void)
{
uint64_t event = 0;
uint64_t event_clear = 0;
dw1000Hal_readRegisterFromIsr(SYS_STATUS_ID, (uint8_t*)&event, SYS_STATUS_LEN);
if (event & SYS_STATUS_TXFRS){ // Frame sent
event_clear |= SYS_STATUS_TXFRS ; //clear interrupt
}
if (event & SYS_STATUS_RXDFR){ // Frame sent
event_clear |= SYS_STATUS_RXDFR; //clear interrupt
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_CLKPLL_LL){ // Frame sent
event_clear |= SYS_STATUS_CLKPLL_LL;
if (event & SYS_STATUS_CPLOCK){
event_clear |= SYS_STATUS_CPLOCK;
//trace_printf("fuu\n");
}
}
dw1000Hal_writeRegisterFromIsr(SYS_STATUS_ID, (uint8_t*)&event_clear, SYS_STATUS_LEN);
}
#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 xHigherPriorityTaskWoken = pdFALSE;
dw1000Util_enableRX();
if (dw1000local.sendCB != NULL) {
xHigherPriorityTaskWoken |= dw1000local.sendCB();
}
return xHigherPriorityTaskWoken;
}
BaseType_t dw1000Hal_handleRx(uint64_t * event, uint64_t * event_clear) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
//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;
uint64_t event = 0;
uint64_t event_clear = 0;
dw1000Hal_readRegisterFromIsr(SYS_STATUS_ID, (uint8_t*) &event,
SYS_STATUS_LEN);
// 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) {
event_clear |= SYS_STATUS_CPLOCK;
trace_printf("dw1000Hal_extiCallback:Clock PLL Losing Lock\n");
event &= ~(SYS_STATUS_CPLOCK);
}
event &= ~(SYS_STATUS_CLKPLL_LL);
}
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;
dw1000Util_enableRX();
#endif
} else {
dw1000Hal_handleRx(&event, &event_clear);
}
//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);
}
#include "deca_regs.h"
#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
//-----------------------------------------
// map the channel number to the index in the configuration arrays below
// 0th element is chan 1, 1st is chan 2, 2nd is chan 3, 3rd is chan 4, 4th is chan 5, 5th is chan 7
const uint8_t chan_idx[NUM_CH_SUPPORTED] = {0, 0, 1, 2, 3, 4, 0, 5};
//-----------------------------------------
const uint32_t tx_config[NUM_CH] =
{
RF_TXCTRL_CH1, /* Tx value match UM */
RF_TXCTRL_CH2,
RF_TXCTRL_CH3,
RF_TXCTRL_CH4,
RF_TXCTRL_CH5,
RF_TXCTRL_CH7,
};
//RF -> Channel_Specific_Cfg -> Channel_Cfg -> RF_PLL -> RF PLL2
const uint8_t pll2_config[NUM_CH][5] =
{
{ 0x07, 0x04, 0x00, 0x09, 0x1E}, //3.5Ghz
{ 0x08, 0x05, 0x40, 0x08, 0x26}, //4Ghz
{ 0x09, 0x10, 0x40, 0x08, 0x56}, //4.5Ghz
{ 0x08, 0x05, 0x40, 0x08, 0x26}, //4Ghz WBW
{ 0x1D, 0x04, 0x00, 0x08, 0xA6}, //6.5Ghz
{ 0x1D, 0x04, 0x00, 0x08, 0xA6} //6.5Ghz WBW
};
const uint8_t pll2calcfg = (0x60 | 0x10) ; /* Bits 7:5 must always be set to binary “011”. Failure to maintain this value will result in DW1000 malfunction. */
//bandwidth configuration
const uint8_t rx_config[NUM_BW] =
{
0xD8, //NBW
0xBC //WBW
};
//FIXME
//const agc_cfg_struct agc_config =
//{
// AGC_TUNE2_VAL,
//
// { AGC_TUNE1_16M , AGC_TUNE1_64M } //adc target
//}
const uint8_t dwnsSFDlen[NUM_BR] = { 0x40, 0x10, 0x08 }; //DW non-standard SFD length for 110k, 850k and 6.81M
// SFD Threshold
const uint16_t sftsh[NUM_BR][NUM_SFD] =
{
//110k
{
(0x0a), //RX_SFTSH_LONG - standard
(0x16) //RX_SFTSH_USR_LONG - non-standard (DW - length specified above dwnsSFDlen)
},
//850k
{
(0x01), //RX_SFTSH_SHORT
(0x06), //RX_SFTSH_USR_SHORT - non-standard (DW - length specified above dwnsSFDlen)
},
//6.81Mb
{
(0x01), //RX_SFTSH_SHORT
(0x02), //RX_SFTSH_USR_SHORT - non-standard (DW - length specified above dwnsSFDlen)
}
};
const uint16_t dtune1[NUM_PRF] =
{
0x0087, // 16 MHz PRF
0x008D // 64 MHz PRF
};
const uint32_t digital_bb_config[NUM_PRF][NUM_PACS] =
{
//16 PRF
{
//PAC 8
0x311A002D,
//PAC 16
0x331A0052,
//PAC 32
0x351A009A,
//PAC 64
0x371A011D
},
//64 PRF
{
//PAC 8
0x313B006B,
//PAC 16
0x333B00BE,
//PAC 32
0x353B015E,
//PAC 64
0x373B0296
}
};
const uint16_t lde_replicaCoeff[PCODES] = {
// 0
(int)(0.0 * 65536),
// 1
(int)(0.35 * 65536),
// 2
(int)(0.35 * 65536),
// 3
(int)(0.32 * 65536),
// 4
(int)(0.26 * 65536),
// 5
(int)(0.27 * 65536),
// 6
(int)(0.18 * 65536),
// 7
(int)(0.50 * 65536),
// 8
(int)(0.32 * 65536),
// 9
(int)(0.16 * 65536),
// 10
(int)(0.20 * 65536),
// 11
(int)(0.23 * 65536),
// 12
(int)(0.24 * 65536),
// 13
(int)(0.23 * 65536),
// 14
(int)(0.21 * 65536),
// 15
(int)(0.17 * 65536),
// 16
(int)(0.21 * 65536),
// 17
(int)(0.20 * 65536),
// 18
(int)(0.21 * 65536),
// 19
(int)(0.21 * 65536),
// 20
(int)(0.28 * 65536),
// 21
(int)(0.23 * 65536),
// 22
(int)(0.22 * 65536),
// 23
(int)(0.19 * 65536),
// 24
(int)(0.22 * 65536)
};
void dw1000Util_enableclocks(int clocks)
{
uint8_t reg[2];
dw1000Hal_readSubRegister(PMSC_ID,PMSC_CTRL0_OFFSET, reg, 2);
switch(clocks)
{
case ENABLE_ALL_SEQ:
{
reg[0] = 0x00 ;
reg[1] = reg[1] & 0xfe;
}
break;
case FORCE_SYS_XTI:
{
//system and rx
reg[0] = 0x01 | (reg[0] & 0xfc);
}
break;
case FORCE_SYS_PLL:
{
//system
reg[0] = 0x02 | (reg[0] & 0xfc);
}
break;
case READ_ACC_ON:
{
reg[0] = 0x48 | (reg[0] & 0xb3);
reg[1] = 0x80 | reg[1];
}
break;
case READ_ACC_OFF:
{
reg[0] = reg[0] & 0xb3;
reg[1] = 0x7f & reg[1];
}
break;
case FORCE_OTP_ON:
{
reg[1] = 0x02 | reg[1];
}
break;
case FORCE_OTP_OFF:
{
reg[1] = reg[1] & 0xfd;
}
break;
case FORCE_TX_PLL:
{
reg[0] = 0x20| (reg[0] & 0xcf);
}
break;
default:
break;
}
//DECA: Need to write lower byte separately before setting the higher byte(s)
dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, &reg[0], 1);
dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET + 1, &reg[0], 1);
}
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
sys_ctrl |= SYS_CTRL_RXENAB;
dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t*) &sys_ctrl,
SYS_CTRL_LEN);
}
uint32_t dw1000Util_otpread(uint32_t address)
{
uint8_t buf[4];
uint32_t ret_data;
//TODO Wieso buf? Und nicht gleich von address?
buf[1] = (address>>8) & 0xff;
buf[0] = address & 0xff;
// Write the address
dw1000Hal_writeSubRegister(OTP_IF_ID, OTP_ADDR, buf, OTP_ADDR_LEN);
// Assert OTP Read (self clearing)
buf[0] = 0x03; // 0x03 for manual drive of OTP_READ and OTP_READ
dw1000Hal_writeSubRegister(OTP_IF_ID, OTP_CTRL, buf, 1);
buf[0] = 0x00; // Bit0 is not autoclearing, so clear it (Bit 1 is but we clear it anyway).
dw1000Hal_writeSubRegister(OTP_IF_ID, OTP_CTRL, buf, 1);
// Read read data, available 40ns after rising edge of OTP_READ
dw1000Hal_readSubRegister(OTP_IF_ID,OTP_RDAT, &ret_data, OTP_RDAT_LEN);
// Return the 32bit of read data
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_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
// we can disable the radio, but before the status is cleared an interrupt can be set (e.g. the
// event has just happened before the radio was disabled)
// thus we need to disable interrupt during this operation
/// stat = decamutexon() ; DECA: ???:" -->
portDISABLE_INTERRUPTS(); //FIXME Eigentlich eher EXTI
uint32_t tmp_mask = 0;
// No interrupts
dw1000Hal_writeRegisterFromIsr(SYS_MASK_ID, (uint8_t *) &tmp_mask, SYS_MASK_LEN);
//Disable radio
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_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t *) &sys_ctrl, 4);
uint32_t tmp = (CLEAR_ALLTX_EVENTS | CLEAR_ALLRXERROR_EVENTS | CLEAR_ALLRXGOOD_EVENTS);
dw1000Hal_writeRegisterFromIsr(SYS_STATUS_ID,(uint8_t *) &tmp, 4) ;
//TODO dwt_syncrxbufptrs();
dw1000Hal_writeRegisterFromIsr(SYS_MASK_ID, (uint8_t *) &sys_mask, SYS_MASK_LEN);
portENABLE_INTERRUPTS();
}
void dw1000Util_reset(void) {
uint32_t subreg;
dw1000Hal_readSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg,
PMSC_CTRL0_LEN);
subreg |= (1 << 0); // SOFTRESET - Set SYSCLKS to 01
subreg &= ~(1 << 1); // SOFTRESET - Zero everything else
dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg,
PMSC_CTRL0_LEN);
dw1000Hal_readSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg,
PMSC_CTRL0_LEN);
subreg &= ~(15 << 28); // SOFTRESET - Set all to ZERO
dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg,
PMSC_CTRL0_LEN);
dw1000Hal_readSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg,
PMSC_CTRL0_LEN);
subreg |= (15 << 28); // SOFTRESET - Set all to ONE
dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg,
PMSC_CTRL0_LEN);
}
void dw1000Util_resetRxOnly(void) {
uint32_t subreg;
dw1000Hal_readSubRegisterFromIsr(PMSC_ID, PMSC_CTRL0_OFFSET,
(uint8_t*) &subreg, PMSC_CTRL0_LEN);
subreg &= ~(1 << 28); // SOFTRESET - Set all to ZERO
subreg |= (0xe << 28);
dw1000Hal_writeSubRegisterFromIsr(PMSC_ID, PMSC_CTRL0_OFFSET,
(uint8_t*) &subreg, PMSC_CTRL0_LEN);
// dw1000Hal_readSubRegisterFromIsr(PMSC_ID, PMSC_CTRL0_OFFSET,
// (uint8_t*) &subreg, PMSC_CTRL0_LEN);
subreg |= (0xf << 28);
dw1000Hal_writeSubRegisterFromIsr(PMSC_ID, PMSC_CTRL0_OFFSET,
(uint8_t*) &subreg, PMSC_CTRL0_LEN);
}
#ifdef DEBUG
void hexdump(uint8_t * buffer, uint8_t len){
char string [2*len +1];
char * string_ptr = string;
for (uint8_t i = 0; i < len; i++)
{
string_ptr += sprintf(string_ptr, "%02X", (unsigned int)*(buffer+i));
}
string[2*len] = '\0';
trace_printf("Ev: %s\n", string);
}
#endif
CFLAGS+=-I"Inc" -I"dw1000/Inc/"
SRC+=$(wildcard dw1000/Src/*.c)
\ No newline at end of file