diff --git a/Core/Src/acc_hal_integration_a111.c b/Core/Src/acc_hal_integration_a111.c new file mode 100644 index 0000000..38dd51e --- /dev/null +++ b/Core/Src/acc_hal_integration_a111.c @@ -0,0 +1,225 @@ +// Copyright (c) Acconeer AB, 2018-2022 +// All rights reserved +// This file is subject to the terms and conditions defined in the file +// 'LICENSES/license_acconeer.txt', (BSD 3-Clause License) which is part +// of this source code package. + +#include +#include +#include +#include +#include + +#include "main.h" +#include "sys_app.h" + +#include "acc_definitions_common.h" +#include "acc_hal_definitions.h" +#include "acc_hal_integration.h" +#include "acc_integration.h" +#include "acc_integration_log.h" + +#include "acc_version.h" +#include "acc_rss.h" + +enum transfer_state { + TRANSFER_COMPLETE = (int) 0, + TRANSFER_ERROR, + TRANSFER_READY +}; + +/* spi handle */ +extern SPI_HandleTypeDef A111_SPI_HANDLE; + +/** + * @brief The number of sensors available on the board + */ +#define SENSOR_COUNT 1 + +/** + * @brief Size of SPI transfer buffer + */ +#ifndef A111_SPI_MAX_TRANSFER_SIZE +#define A111_SPI_MAX_TRANSFER_SIZE 65535 //4096 //65535 +#endif + +/** + * @brief The reference frequency used by this board + * + * This assumes 26 MHz on the Sparkfun A111 Board + */ +//#define ACC_BOARD_REF_FREQ 26000000 +#define ACC_BOARD_REF_FREQ 24000000 + +static inline void disable_interrupts(void) +{ + __disable_irq(); +} + + +static inline void enable_interrupts(void) +{ + __enable_irq(); + __ISB(); +} + +#ifdef A111_USE_SPI_DMA +static volatile bool spi_transfer_complete; + +void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) +{ + (void)hspi; + spi_transfer_complete = true; +} +#endif + + +//---------------------------------------- +// Implementation of RSS HAL handlers +//---------------------------------------- + + +static void acc_hal_integration_sensor_transfer(acc_sensor_id_t sensor_id, uint8_t *buffer, size_t buffer_size) +{ + (void)sensor_id; // Ignore parameter sensor_id + + const uint32_t SPI_TRANSMIT_RECEIVE_TIMEOUT = 5000; + + HAL_GPIO_WritePin(A111_CS_N_GPIO_Port, A111_CS_N_Pin, GPIO_PIN_RESET); + +#ifdef A111_USE_SPI_DMA + spi_transfer_complete = false; + HAL_StatusTypeDef status = HAL_SPI_TransmitReceive_DMA(&A111_SPI_HANDLE, buffer, buffer, buffer_size); + + if (status != HAL_OK) + { + return; + } + + uint32_t start = HAL_GetTick(); + + while (!spi_transfer_complete && (HAL_GetTick() - start) < SPI_TRANSMIT_RECEIVE_TIMEOUT) + { + // Turn off interrupts + disable_interrupts(); + // Check once more so that the interrupt have not occurred + if (!spi_transfer_complete) + { + __WFI(); + } + + // Enable interrupt again, the ISR will execute directly after this + enable_interrupts(); + } +#else + HAL_SPI_TransmitReceive(&A111_SPI_HANDLE, buffer, buffer, buffer_size, SPI_TRANSMIT_RECEIVE_TIMEOUT); +#endif + + HAL_GPIO_WritePin(A111_CS_N_GPIO_Port, A111_CS_N_Pin, GPIO_PIN_SET); +} + + +static void acc_hal_integration_sensor_power_on(acc_sensor_id_t sensor_id) +{ + (void)sensor_id; // Ignore parameter sensor_id + HAL_GPIO_WritePin(A111_ENABLE_GPIO_Port, A111_ENABLE_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(A111_CS_N_GPIO_Port, A111_CS_N_Pin, GPIO_PIN_SET); + + // Wait 2 ms to make sure that the sensor crystal have time to stabilize + HAL_Delay(2); +} + + +static void acc_hal_integration_sensor_power_off(acc_sensor_id_t sensor_id) +{ + (void)sensor_id; // Ignore parameter sensor_id + + HAL_GPIO_WritePin(A111_CS_N_GPIO_Port, A111_CS_N_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(A111_ENABLE_GPIO_Port, A111_ENABLE_Pin, GPIO_PIN_RESET); + + // Wait after power off to leave the sensor in a known state + // in case the application intends to enable the sensor directly + HAL_Delay(2); +} + + +static bool acc_hal_integration_wait_for_sensor_interrupt(acc_sensor_id_t sensor_id, uint32_t timeout_ms) +{ + (void)sensor_id; // Ignore parameter sensor_id + + const uint32_t wait_begin_ms = HAL_GetTick(); + while ((HAL_GPIO_ReadPin(A111_SENSOR_INTERRUPT_GPIO_Port, A111_SENSOR_INTERRUPT_Pin) != GPIO_PIN_SET) && + (HAL_GetTick() - wait_begin_ms < timeout_ms)) + { + // Wait for the GPIO interrupt + disable_interrupts(); + // Check again so that IRQ did not occur + if (HAL_GPIO_ReadPin(A111_SENSOR_INTERRUPT_GPIO_Port, A111_SENSOR_INTERRUPT_Pin) != GPIO_PIN_SET) + { + __WFI(); + } + + // Enable interrupts again to allow pending interrupt to be handled + enable_interrupts(); + } + + return HAL_GPIO_ReadPin(A111_SENSOR_INTERRUPT_GPIO_Port, A111_SENSOR_INTERRUPT_Pin) == GPIO_PIN_SET; +} + + +static float acc_hal_integration_get_reference_frequency(void) +{ + return ACC_BOARD_REF_FREQ; +} + + +static const acc_hal_t hal = +{ + .properties.sensor_count = SENSOR_COUNT, + .properties.max_spi_transfer_size = A111_SPI_MAX_TRANSFER_SIZE, + + .sensor_device.power_on = acc_hal_integration_sensor_power_on, + .sensor_device.power_off = acc_hal_integration_sensor_power_off, + .sensor_device.wait_for_interrupt = acc_hal_integration_wait_for_sensor_interrupt, + .sensor_device.transfer = acc_hal_integration_sensor_transfer, + .sensor_device.get_reference_frequency = acc_hal_integration_get_reference_frequency, + + .os.mem_alloc = malloc, + .os.mem_free = free, + .os.gettime = acc_integration_get_time, + + .log.log_level = ACC_LOG_LEVEL_INFO, + .log.log = acc_integration_log, + + .optimization.transfer16 = NULL, +}; + + +const acc_hal_t *acc_hal_integration_get_implementation(void) +{ + return &hal; +} + + +bool hal_test_spi_read_chipid(uint8_t chipid[2]) +{ + const uint32_t sensor = 1; + uint8_t buffer[6] = {0x30,0x0,0x0,0x0,0x0,0x0}; + const acc_hal_t *hal = acc_hal_integration_get_implementation(); + hal->sensor_device.power_on(sensor); + hal->sensor_device.transfer(sensor,buffer,sizeof(buffer)); + hal->sensor_device.power_off(sensor); + if (buffer[4] == 0x11 && buffer[5] == 0x12) { + chipid[0] = buffer[4]; + chipid[1] = buffer[5]; + return true; + } + else + { + chipid[0] = 0x0; + chipid[1] = 0x0; + return false; + } + +} +