Skip to content
Snippets Groups Projects
dw1000_hal.c 10.3 KiB
Newer Older
#include "dw1000_hal.h"

#include "FreeRTOS.h"
#include "task.h"
#include "cmsis_os.h"
#include "stm32f4xx_hal.h"
#include "Trace.h"
#include "deca_regs.h"

#include "spi.h"

SPI_HandleTypeDef *hspi;

uint8_t read3[7];
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_chipSelect(void)
{
	HAL_GPIO_WritePin(DW1000HAL_SS_GPIO, DW1000HAL_SS_PIN, GPIO_PIN_RESET);
}

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)
{
	uint8_t dummy[3];
	int ret;
	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
			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);
		xSemaphoreGive(spiSema);
	} else {
		ret = HAL_LOCKED;
	}
	return ret;
}

int dw1000Hal_writeSubRegister(uint8_t regID, uint16_t offset, uint8_t *src, uint16_t len)
{
	uint8_t dummy[3];
	int ret;
	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] |= 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);
		xSemaphoreGive(spiSema);
	} else {
		ret = HAL_LOCKED;
	}
	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;
	portENTER_CRITICAL();
	if ((spiSema != NULL) && (xSemaphoreTake(spiSema, 10) == pdTRUE)) {
		dw1000Hal_chipSelect();
		ret = HAL_SPI_Transmit(hspi, &dummy, 1, 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) {
		}
		xSemaphoreGive(spiSema);
	} else {
		ret = HAL_LOCKED;
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)) {
		dw1000Hal_chipSelect();
		ret = HAL_SPI_Transmit(hspi, &dummy, 1, 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;
		trace_printf("ib");
	}
	return ret;
}
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)
	int ret;
	portENTER_CRITICAL();
	if ((spiSema != NULL) && (xSemaphoreTake(spiSema, 10) == pdTRUE)) {
		dw1000Hal_chipSelect();
		ret = HAL_SPI_Transmit(hspi, &dummy, 1, 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) {
		}
		xSemaphoreGive(spiSema);
	} else {
		ret = HAL_LOCKED;
		trace_printf("na");
	}
	portEXIT_CRITICAL();
	return ret;
}
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)) {
		dw1000Hal_chipSelect();
		ret = HAL_SPI_Transmit(hspi, &dummy, 1, 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;
		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))
{
	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)) {
		dw1000Hal_chipSelect();
		ret = HAL_SPI_Transmit(hspi, &dummy, 1, DW1000HAL_SPI_TIMEOUT);
		if (ret == HAL_OK) {
			ret = HAL_SPI_Receive_DMA(hspi, dest, len);
		} else {
			xSemaphoreGive(spiSema);
			dw1000Hal_chipDeselect();
		}
	} else {
		ret = HAL_LOCKED;
	}
	return ret;
}

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)) {
		dw1000Hal_chipSelect();
		ret = HAL_SPI_Transmit(hspi, &dummy, 1, DW1000HAL_SPI_TIMEOUT);
		if (ret == HAL_OK) {
			ret = HAL_SPI_Transmit_DMA(hspi, src, len);
		} else {
			xSemaphoreGive(spiSema);
			dw1000Hal_chipDeselect();
		}
	} else {
		ret = HAL_LOCKED;
	}
	return ret;
}


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)
{
	dw1000Hal_chipDeselect();
	xSemaphoreGiveFromISR(spiSema, pdFALSE);
	if (spiCallback != NULL){
		spiCallback(HAL_ERROR, 0, hspi->TxXferSize);
	}

}

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
	dw1000Hal_chipDeselect();
	xSemaphoreGiveFromISR(spiSema, pdFALSE);
	if (spiCallback != NULL){
		spiCallback(HAL_ERROR, 0, hspi->TxXferSize);
	}
}

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
	dw1000Hal_chipDeselect();
	xSemaphoreGiveFromISR(spiSema, pdFALSE);
	if (spiCallback != NULL){
		spiCallback(HAL_ERROR, 0, hspi->TxXferSize);
	}
}

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
	dw1000Hal_chipDeselect();
	xSemaphoreGiveFromISR(spiSema, pdFALSE);
	if (spiCallback != NULL){
		spiCallback(HAL_ERROR, 0, hspi->TxXferSize);
	}
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if (GPIO_PIN_8 == GPIO_Pin){
		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

		}
		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);
	}