[FL-950] CC1101 Stage1, SPI Refactoring, Drivers layer (#386)
* API HAL SPI: refactoring, split into layers, prepare ST HAL separation. API HAL SubGhz: initialize on start. Drivers: add basic cc1101 driver. Update API usage. Debug: increase max debugger port speed. Remove subghz apps. * CC1101: chip status handling. ApiHalSpi: increase SubGhz bus speed to 8mhz. F4: backport subghz initialization. * Api Hal SubGhz: rx path and frequency. CC1101: frequency control. * SubGhz Application: basic tests * SubGhz app: tone and packet test. API HAL SUBGHZ: update configs, add missing bits and pieces.
This commit is contained in:
@@ -23,5 +23,6 @@ void delay_us(float microseconds) {
|
||||
void delay(float milliseconds) {
|
||||
uint32_t ticks = milliseconds / (1000.0f / osKernelGetTickFreq());
|
||||
osStatus_t result = osDelay(ticks);
|
||||
(void)result;
|
||||
assert(result == osOK);
|
||||
}
|
@@ -20,11 +20,6 @@ void hal_gpio_init(
|
||||
HAL_GPIO_Init(gpio->port, &GPIO_InitStruct);
|
||||
}
|
||||
|
||||
void enable_cc1101_irq() {
|
||||
HAL_NVIC_SetPriority(EXTI4_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(EXTI4_IRQn);
|
||||
}
|
||||
|
||||
extern COMP_HandleTypeDef hcomp1;
|
||||
|
||||
bool get_rfid_in_level() {
|
||||
|
@@ -24,6 +24,12 @@ typedef enum {
|
||||
GpioModeEventRiseFall = GPIO_MODE_EVT_RISING_FALLING,
|
||||
} GpioMode;
|
||||
|
||||
typedef enum {
|
||||
GpioPullNo = GPIO_NOPULL,
|
||||
GpioPullUp = GPIO_PULLUP,
|
||||
GpioPullDown = GPIO_PULLDOWN,
|
||||
} GpioPull;
|
||||
|
||||
typedef enum {
|
||||
GpioSpeedLow = GPIO_SPEED_FREQ_LOW,
|
||||
GpioSpeedMedium = GPIO_SPEED_FREQ_MEDIUM,
|
||||
@@ -31,12 +37,6 @@ typedef enum {
|
||||
GpioSpeedVeryHigh = GPIO_SPEED_FREQ_VERY_HIGH,
|
||||
} GpioSpeed;
|
||||
|
||||
typedef enum {
|
||||
GpioPullNo = GPIO_NOPULL,
|
||||
GpioPullUp = GPIO_PULLUP,
|
||||
GpioPullDown = GPIO_PULLDOWN,
|
||||
} GpioPull;
|
||||
|
||||
typedef struct {
|
||||
GPIO_TypeDef* port;
|
||||
uint16_t pin;
|
||||
|
@@ -28,3 +28,17 @@ const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin);
|
||||
const GpioPin vibro_gpio = {VIBRO_GPIO_Port, VIBRO_Pin};
|
||||
const GpioPin ibutton_gpio = {iBTN_GPIO_Port, iBTN_Pin};
|
||||
const GpioPin cc1101_g0_gpio = {CC1101_G0_GPIO_Port, CC1101_G0_Pin};
|
||||
|
||||
const GpioPin gpio_subghz_cs = { .port=CC1101_CS_GPIO_Port, .pin=CC1101_CS_Pin };
|
||||
const GpioPin gpio_display_cs = { .port=DISPLAY_CS_GPIO_Port, .pin=DISPLAY_CS_Pin };
|
||||
const GpioPin gpio_display_rst = { .port=DISPLAY_RST_GPIO_Port, .pin=DISPLAY_RST_Pin };
|
||||
const GpioPin gpio_display_di = { .port=DISPLAY_DI_GPIO_Port, .pin=DISPLAY_DI_Pin };
|
||||
const GpioPin gpio_sdcard_cs = { .port=SD_CS_GPIO_Port, .pin=SD_CS_Pin };
|
||||
const GpioPin gpio_nfc_cs = { .port=NFC_CS_GPIO_Port, .pin=NFC_CS_Pin };
|
||||
|
||||
const GpioPin gpio_spi_d_miso = { .port=SPI_D_MISO_GPIO_Port, .pin=SPI_D_MISO_Pin };
|
||||
const GpioPin gpio_spi_d_mosi = { .port=SPI_D_MOSI_GPIO_Port, .pin=SPI_D_MOSI_Pin };
|
||||
const GpioPin gpio_spi_d_sck = { .port=SPI_D_SCK_GPIO_Port, .pin=SPI_D_SCK_Pin };
|
||||
const GpioPin gpio_spi_r_miso = { .port=SPI_R_MISO_GPIO_Port, .pin=SPI_R_MISO_Pin };
|
||||
const GpioPin gpio_spi_r_mosi = { .port=SPI_R_MOSI_GPIO_Port, .pin=SPI_R_MOSI_Pin };
|
||||
const GpioPin gpio_spi_r_sck = { .port=SPI_R_SCK_GPIO_Port, .pin=SPI_R_SCK_Pin };
|
||||
|
@@ -16,7 +16,7 @@ extern "C" {
|
||||
#define POWER_I2C_SDA_GPIO_Port GPIOA
|
||||
|
||||
#define POWER_I2C I2C1
|
||||
/* Timing register value is computed with the STM32CubeMX Tool,
|
||||
/** Timing register value is computed with the STM32CubeMX Tool,
|
||||
* Fast Mode @100kHz with I2CCLK = 64 MHz,
|
||||
* rise time = 0ns, fall time = 0ns
|
||||
*/
|
||||
@@ -57,6 +57,24 @@ extern const GpioPin vibro_gpio;
|
||||
extern const GpioPin ibutton_gpio;
|
||||
extern const GpioPin cc1101_g0_gpio;
|
||||
|
||||
extern const GpioPin gpio_subghz_cs;
|
||||
extern const GpioPin gpio_display_cs;
|
||||
|
||||
extern const GpioPin gpio_subghz_cs;
|
||||
extern const GpioPin gpio_display_cs;
|
||||
extern const GpioPin gpio_display_rst;
|
||||
extern const GpioPin gpio_display_di;
|
||||
extern const GpioPin gpio_sdcard_cs;
|
||||
extern const GpioPin gpio_nfc_cs;
|
||||
|
||||
extern const GpioPin gpio_spi_d_miso;
|
||||
extern const GpioPin gpio_spi_d_mosi;
|
||||
extern const GpioPin gpio_spi_d_sck;
|
||||
extern const GpioPin gpio_spi_r_miso;
|
||||
extern const GpioPin gpio_spi_r_mosi;
|
||||
extern const GpioPin gpio_spi_r_sck;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,14 +1,89 @@
|
||||
#include "main.h"
|
||||
#include "api-hal-spi-config.h"
|
||||
#include <api-hal-spi-config.h>
|
||||
#include <api-hal-resources.h>
|
||||
|
||||
extern SPI_HandleTypeDef SPI_R;
|
||||
extern SPI_HandleTypeDef SPI_D;
|
||||
|
||||
const SPI_InitTypeDef api_hal_spi_config_nfc = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_2EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_DISABLE,
|
||||
};
|
||||
|
||||
const SPI_InitTypeDef api_hal_spi_config_subghz = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_DISABLE,
|
||||
};
|
||||
|
||||
const SPI_InitTypeDef api_hal_spi_config_display = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_ENABLE,
|
||||
};
|
||||
|
||||
osMutexId_t spi_mutex_d = NULL;
|
||||
osMutexId_t spi_mutex_r = NULL;
|
||||
|
||||
const ApiHalSpiBus spi_r = {
|
||||
.spi=&SPI_R,
|
||||
.mutex=&spi_mutex_r,
|
||||
.miso=&gpio_spi_r_miso,
|
||||
.mosi=&gpio_spi_r_mosi,
|
||||
.clk=&gpio_spi_r_sck,
|
||||
};
|
||||
|
||||
const ApiHalSpiBus spi_d = {
|
||||
.spi=&SPI_D,
|
||||
.mutex=&spi_mutex_d,
|
||||
.miso=&gpio_spi_d_miso,
|
||||
.mosi=&gpio_spi_d_mosi,
|
||||
.clk=&gpio_spi_d_sck,
|
||||
};
|
||||
|
||||
const ApiHalSpiDevice api_hal_spi_devices[ApiHalSpiDeviceIdMax] = {
|
||||
{ .bus=&spi_r, .config=&api_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, },
|
||||
{ .bus=&spi_d, .config=&api_hal_spi_config_display, .chip_select=&gpio_display_cs, },
|
||||
{ .bus=&spi_d, .config=NULL, .chip_select=&gpio_sdcard_cs, },
|
||||
{ .bus=&spi_r, .config=&api_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs },
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* SD Card in fast mode (after init)
|
||||
*/
|
||||
const SPIDevice sd_fast_spi = {
|
||||
.spi = &SPI_D,
|
||||
.bus= &spi_d,
|
||||
.config = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
@@ -29,7 +104,7 @@ const SPIDevice sd_fast_spi = {
|
||||
* SD Card in slow mode (before init)
|
||||
*/
|
||||
const SPIDevice sd_slow_spi = {
|
||||
.spi = &SPI_D,
|
||||
.bus= &spi_d,
|
||||
.config = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
@@ -45,24 +120,3 @@ const SPIDevice sd_slow_spi = {
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_ENABLE,
|
||||
}};
|
||||
|
||||
/**
|
||||
* Display
|
||||
*/
|
||||
const SPIDevice display_spi = {
|
||||
.spi = &SPI_D,
|
||||
.config = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_ENABLE,
|
||||
}};
|
||||
|
@@ -1,17 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <api-hal-gpio.h>
|
||||
#include <cmsis_os2.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const SPI_InitTypeDef api_hal_spi_config_nfc;
|
||||
extern const SPI_InitTypeDef api_hal_spi_config_subghz;
|
||||
extern const SPI_InitTypeDef api_hal_spi_config_display;
|
||||
|
||||
/** API HAL SPI BUS handler
|
||||
* Structure content may change at some point
|
||||
*/
|
||||
typedef struct {
|
||||
SPI_HandleTypeDef* spi;
|
||||
const SPI_HandleTypeDef* spi;
|
||||
const osMutexId_t* mutex;
|
||||
const GpioPin* miso;
|
||||
const GpioPin* mosi;
|
||||
const GpioPin* clk;
|
||||
} ApiHalSpiBus;
|
||||
|
||||
/** API HAL SPI Device handler
|
||||
* Structure content may change at some point
|
||||
*/
|
||||
typedef struct {
|
||||
const ApiHalSpiBus* bus;
|
||||
const SPI_InitTypeDef* config;
|
||||
const GpioPin* chip_select;
|
||||
} ApiHalSpiDevice;
|
||||
|
||||
/** API HAL SPI Standard Device IDs */
|
||||
typedef enum {
|
||||
ApiHalSpiDeviceIdSubGhz, /** SubGhz: CC1101, non-standard SPI usage */
|
||||
ApiHalSpiDeviceIdDisplay, /** Display: ERC12864, only have MOSI */
|
||||
ApiHalSpiDeviceIdSdCard, /** SDCARD: no default bus config, bus must explicitly be configured */
|
||||
ApiHalSpiDeviceIdNfc, /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */
|
||||
|
||||
ApiHalSpiDeviceIdMax, /** Service Value, do not use */
|
||||
} ApiHalSpiDeviceId;
|
||||
|
||||
/** Api Hal Spi Bus R
|
||||
* CC1101, Nfc
|
||||
*/
|
||||
extern const ApiHalSpiBus spi_r;
|
||||
|
||||
/** Api Hal Spi Bus D
|
||||
* Display, SdCard
|
||||
*/
|
||||
extern const ApiHalSpiBus spi_d;
|
||||
|
||||
/** Api Hal Spi devices */
|
||||
extern const ApiHalSpiDevice api_hal_spi_devices[ApiHalSpiDeviceIdMax];
|
||||
|
||||
typedef struct {
|
||||
const ApiHalSpiBus* bus;
|
||||
const SPI_InitTypeDef config;
|
||||
} SPIDevice;
|
||||
|
||||
extern const SPIDevice sd_fast_spi;
|
||||
extern const SPIDevice sd_slow_spi;
|
||||
extern const SPIDevice display_spi;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -1,36 +1,167 @@
|
||||
#include "api-hal-spi.h"
|
||||
#include <cmsis_os2.h>
|
||||
#include <api-hal-resources.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <spi.h>
|
||||
#include <furi.h>
|
||||
|
||||
osMutexId_t spi_mutex_r;
|
||||
osMutexId_t spi_mutex_d;
|
||||
|
||||
extern SPI_HandleTypeDef SPI_R;
|
||||
extern SPI_HandleTypeDef SPI_D;
|
||||
extern void Enable_SPI(SPI_HandleTypeDef* spi);
|
||||
|
||||
void api_hal_spi_init() {
|
||||
spi_mutex_r = osMutexNew(NULL);
|
||||
spi_mutex_d = osMutexNew(NULL);
|
||||
// Spi structure is const, but mutex is not
|
||||
// Need some hell-ish casting to make it work
|
||||
*(osMutexId_t*)spi_r.mutex = osMutexNew(NULL);
|
||||
*(osMutexId_t*)spi_d.mutex = osMutexNew(NULL);
|
||||
//
|
||||
for (size_t i=0; i<ApiHalSpiDeviceIdMax; ++i) {
|
||||
hal_gpio_init(
|
||||
api_hal_spi_devices[i].chip_select,
|
||||
GpioModeOutputPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_bus_lock(const ApiHalSpiBus* bus) {
|
||||
furi_assert(bus);
|
||||
if (bus->mutex) {
|
||||
osMutexAcquire(*bus->mutex, osWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus) {
|
||||
furi_assert(bus);
|
||||
if (bus->mutex) {
|
||||
osMutexRelease(*bus->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
bool api_hal_spi_bus_rx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(bus);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
HAL_StatusTypeDef ret = HAL_SPI_Receive((SPI_HandleTypeDef *)bus->spi, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
return ret == HAL_OK;
|
||||
}
|
||||
|
||||
bool api_hal_spi_bus_tx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(bus);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
HAL_StatusTypeDef ret = HAL_SPI_Transmit((SPI_HandleTypeDef *)bus->spi, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
return ret == HAL_OK;
|
||||
}
|
||||
|
||||
bool api_hal_spi_bus_trx(const ApiHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(bus);
|
||||
furi_assert(tx_buffer);
|
||||
furi_assert(rx_buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
HAL_StatusTypeDef ret = HAL_SPI_TransmitReceive((SPI_HandleTypeDef *)bus->spi, tx_buffer, rx_buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
return ret == HAL_OK;
|
||||
}
|
||||
|
||||
const ApiHalSpiDevice* api_hal_spi_device_get(ApiHalSpiDeviceId device_id) {
|
||||
furi_assert(device_id < ApiHalSpiDeviceIdMax);
|
||||
|
||||
const ApiHalSpiDevice* device = &api_hal_spi_devices[device_id];
|
||||
assert(device);
|
||||
api_hal_spi_bus_lock(device->bus);
|
||||
|
||||
if (device->config) {
|
||||
memcpy((SPI_InitTypeDef*)&device->bus->spi->Init, device->config, sizeof(SPI_InitTypeDef));
|
||||
if(HAL_SPI_Init((SPI_HandleTypeDef *)device->bus->spi) != HAL_OK) {
|
||||
Error_Handler();
|
||||
}
|
||||
Enable_SPI((SPI_HandleTypeDef *)device->bus->spi);
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
void api_hal_spi_device_return(const ApiHalSpiDevice* device) {
|
||||
api_hal_spi_bus_unlock(device->bus);
|
||||
}
|
||||
|
||||
bool api_hal_spi_device_rx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(device);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = api_hal_spi_bus_rx(device->bus, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool api_hal_spi_device_tx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(device);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = api_hal_spi_bus_tx(device->bus, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool api_hal_spi_device_trx(const ApiHalSpiDevice* device, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(device);
|
||||
furi_assert(tx_buffer);
|
||||
furi_assert(rx_buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = api_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void api_hal_spi_apply_config(const SPIDevice* device) {
|
||||
osKernelLock();
|
||||
|
||||
memcpy(&device->spi->Init, &device->config, sizeof(SPI_InitTypeDef));
|
||||
memcpy((SPI_InitTypeDef*)&device->bus->spi->Init, &device->config, sizeof(SPI_InitTypeDef));
|
||||
|
||||
if(HAL_SPI_Init(device->spi) != HAL_OK) {
|
||||
if(HAL_SPI_Init((SPI_HandleTypeDef*)device->bus->spi) != HAL_OK) {
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
Enable_SPI(device->spi);
|
||||
Enable_SPI((SPI_HandleTypeDef*)device->bus->spi);
|
||||
|
||||
osKernelUnlock();
|
||||
}
|
||||
|
||||
bool api_hal_spi_config_are_actual(const SPIDevice* device) {
|
||||
return (memcmp(&device->config, &device->spi->Init, sizeof(SPI_InitTypeDef)) == 0);
|
||||
return (memcmp(&device->config, &device->bus->spi->Init, sizeof(SPI_InitTypeDef)) == 0);
|
||||
}
|
||||
|
||||
void api_hal_spi_config_device(const SPIDevice* device) {
|
||||
@@ -39,31 +170,11 @@ void api_hal_spi_config_device(const SPIDevice* device) {
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_lock(SPI_HandleTypeDef* spi) {
|
||||
if(spi == &SPI_D) {
|
||||
osMutexAcquire(spi_mutex_d, osWaitForever);
|
||||
} else if(spi == &SPI_R) {
|
||||
osMutexAcquire(spi_mutex_r, osWaitForever);
|
||||
} else {
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_unlock(SPI_HandleTypeDef* spi) {
|
||||
if(spi == &SPI_D) {
|
||||
osMutexRelease(spi_mutex_d);
|
||||
} else if(spi == &SPI_R) {
|
||||
osMutexRelease(spi_mutex_r);
|
||||
} else {
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_lock_device(const SPIDevice* device) {
|
||||
api_hal_spi_lock(device->spi);
|
||||
api_hal_spi_bus_lock(device->bus);
|
||||
api_hal_spi_config_device(device);
|
||||
}
|
||||
|
||||
void api_hal_spi_unlock_device(const SPIDevice* device) {
|
||||
api_hal_spi_unlock(device->spi);
|
||||
}
|
||||
api_hal_spi_bus_unlock(device->bus);
|
||||
}
|
||||
|
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include "main.h"
|
||||
#include "api-hal-spi-config.h"
|
||||
#include <api-hal-gpio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -11,15 +13,83 @@ extern "C" {
|
||||
*/
|
||||
void api_hal_spi_init();
|
||||
|
||||
/**
|
||||
* Lock SPI bus
|
||||
*/
|
||||
void api_hal_spi_lock(SPI_HandleTypeDef* spi);
|
||||
/* Bus Level API */
|
||||
|
||||
/**
|
||||
* Unlock SPI bus
|
||||
/** Lock SPI bus
|
||||
* Takes bus mutex, if used
|
||||
*/
|
||||
void api_hal_spi_unlock(SPI_HandleTypeDef* spi);
|
||||
void api_hal_spi_bus_lock(const ApiHalSpiBus* bus);
|
||||
|
||||
/** Unlock SPI bus
|
||||
* Releases BUS mutex, if used
|
||||
*/
|
||||
void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus);
|
||||
|
||||
/** SPI Receive
|
||||
* @param bus - spi bus handler
|
||||
* @param buffer - receive buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_bus_rx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit
|
||||
* @param bus - spi bus handler
|
||||
* @param buffer - transmit buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_bus_tx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit and Receive
|
||||
* @param bus - spi bus handlere
|
||||
* @param tx_buffer - device handle
|
||||
* @param rx_buffer - device handle
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_bus_trx(const ApiHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/* Device Level API */
|
||||
|
||||
/** Get Device handle
|
||||
* And lock access to the corresponding SPI BUS
|
||||
* @param device_id - device identifier
|
||||
* @return device handle
|
||||
*/
|
||||
const ApiHalSpiDevice* api_hal_spi_device_get(ApiHalSpiDeviceId device_id);
|
||||
|
||||
/** Return Device handle
|
||||
* And unlock access to the corresponding SPI BUS
|
||||
* @param device - device handle
|
||||
*/
|
||||
void api_hal_spi_device_return(const ApiHalSpiDevice* device);
|
||||
|
||||
/** SPI Recieve
|
||||
* @param device - device handle
|
||||
* @param buffer - receive buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_device_rx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit
|
||||
* @param device - device handle
|
||||
* @param buffer - transmit buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_device_tx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit and Receive
|
||||
* @param device - device handle
|
||||
* @param tx_buffer - device handle
|
||||
* @param rx_buffer - device handle
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_device_trx(const ApiHalSpiDevice* device, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout);
|
||||
|
||||
|
||||
/**
|
||||
* Lock SPI device bus and apply config if needed
|
||||
|
@@ -1,19 +1,181 @@
|
||||
#include "api-hal-subghz.h"
|
||||
#include <stm32wbxx_ll_gpio.h>
|
||||
#include <api-hal-gpio.h>
|
||||
#include <api-hal-spi.h>
|
||||
#include <cc1101.h>
|
||||
#include <stdio.h>
|
||||
#include "main.h"
|
||||
|
||||
void api_hal_rf_band_set(RfBand band) {
|
||||
if (band == RfBand1) {
|
||||
LL_GPIO_ResetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_SetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (band == RfBand2) {
|
||||
LL_GPIO_SetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_ResetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (band == RfBand3) {
|
||||
LL_GPIO_SetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_SetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (band == RfBandIsolation) {
|
||||
LL_GPIO_ResetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_ResetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
static const uint8_t api_hal_subghz_preset_ook_async_regs[][2] = {
|
||||
/* Base setting */
|
||||
{ CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input
|
||||
{ CC1101_FSCTRL1, 0x06 }, // Set IF 26m/2^10*2=2.2MHz
|
||||
{ CC1101_MCSM0, 0x18 }, // Autocalibrate on idle to TRX, ~150us OSC guard time
|
||||
/* Async OOK Specific things */
|
||||
{ CC1101_MDMCFG2, 0x30 }, // ASK/OOK, No preamble/sync
|
||||
{ CC1101_PKTCTRL0, 0x32 }, // Async, no CRC, Infinite
|
||||
{ CC1101_FREND0, 0x01 }, // OOK/ASK PATABLE
|
||||
/* End */
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const uint8_t api_hal_subghz_preset_ook_async_patable[8] = {
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const uint8_t api_hal_subghz_preset_2fsk_packet_regs[][2] = {
|
||||
/* Base setting */
|
||||
{ CC1101_IOCFG0, 0x06 }, // GD0 as async serial data output/input
|
||||
{ CC1101_FSCTRL1, 0x06 }, // Set IF 26m/2^10*2=2.2MHz
|
||||
{ CC1101_MCSM0, 0x18 }, // Autocalibrate on idle to TRX, ~150us OSC guard time
|
||||
/* End */
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const uint8_t api_hal_subghz_preset_2fsk_packet_patable[8] = {
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void api_hal_subghz_init() {
|
||||
LL_GPIO_SetPinMode(RF_SW_0_GPIO_Port, RF_SW_0_Pin, LL_GPIO_MODE_OUTPUT);
|
||||
LL_GPIO_SetPinSpeed(RF_SW_0_GPIO_Port, RF_SW_0_Pin, LL_GPIO_SPEED_FREQ_LOW);
|
||||
LL_GPIO_SetPinOutputType(RF_SW_0_GPIO_Port, RF_SW_0_Pin, LL_GPIO_OUTPUT_PUSHPULL);
|
||||
LL_GPIO_SetPinMode(RF_SW_1_GPIO_Port, RF_SW_1_Pin, LL_GPIO_MODE_OUTPUT);
|
||||
LL_GPIO_SetPinSpeed(RF_SW_1_GPIO_Port, RF_SW_1_Pin, LL_GPIO_SPEED_FREQ_LOW);
|
||||
LL_GPIO_SetPinOutputType(RF_SW_1_GPIO_Port, RF_SW_1_Pin, LL_GPIO_OUTPUT_PUSHPULL);
|
||||
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
// Reset and shutdown
|
||||
cc1101_reset(device);
|
||||
cc1101_write_reg(device, CC1101_IOCFG0, 0x2E); // High impedance 3-state
|
||||
cc1101_shutdown(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_dump_state() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
printf(
|
||||
"[api_hal_subghz] cc1101 chip %d, version %d\r\n",
|
||||
cc1101_get_partnumber(device),
|
||||
cc1101_get_version(device)
|
||||
);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_load_preset(ApiHalSubGhzPreset preset) {
|
||||
if(preset == ApiHalSubGhzPresetOokAsync) {
|
||||
api_hal_subghz_load_registers(api_hal_subghz_preset_ook_async_regs);
|
||||
api_hal_subghz_load_patable(api_hal_subghz_preset_ook_async_patable);
|
||||
} else if(preset == ApiHalSubGhzPreset2FskPacket) {
|
||||
api_hal_subghz_load_registers(api_hal_subghz_preset_2fsk_packet_regs);
|
||||
api_hal_subghz_load_patable(api_hal_subghz_preset_2fsk_packet_patable);
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_subghz_load_registers(const uint8_t data[][2]) {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_reset(device);
|
||||
uint32_t i = 0;
|
||||
while (data[i][0]) {
|
||||
cc1101_write_reg(device, data[i][0], data[i][1]);
|
||||
i++;
|
||||
}
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_load_patable(const uint8_t data[8]) {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_set_pa_table(device, data);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_write_packet(const uint8_t* data, uint8_t size) {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_flush_tx(device);
|
||||
cc1101_write_fifo(device, data, size);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_read_packet(uint8_t* data, uint8_t size) {
|
||||
|
||||
}
|
||||
|
||||
void api_hal_subghz_shutdown() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
// Reset and shutdown
|
||||
cc1101_shutdown(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_reset() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_reset(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_idle() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_switch_to_idle(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_rx() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_switch_to_rx(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_tx() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_switch_to_tx(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
float api_hal_subghz_get_rssi() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
int32_t rssi_dec = cc1101_get_rssi(device);
|
||||
api_hal_spi_device_return(device);
|
||||
|
||||
float rssi = rssi_dec;
|
||||
if(rssi_dec >= 128) {
|
||||
rssi = ((rssi - 256.0f) / 2.0f) - 74.0f;
|
||||
} else {
|
||||
rssi = (rssi / 2.0f) - 74.0f;
|
||||
}
|
||||
|
||||
return rssi;
|
||||
}
|
||||
|
||||
uint32_t api_hal_subghz_set_frequency(uint32_t value) {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
|
||||
// Compensate rounding
|
||||
if (value % cc1101_get_frequency_step(device) > (cc1101_get_frequency_step(device) / 2)) {
|
||||
value += cc1101_get_frequency_step(device);
|
||||
}
|
||||
|
||||
uint32_t real_frequency = cc1101_set_frequency(device, value);
|
||||
cc1101_calibrate(device);
|
||||
|
||||
api_hal_spi_device_return(device);
|
||||
|
||||
return real_frequency;
|
||||
}
|
||||
|
||||
void api_hal_subghz_set_path(ApiHalSubGhzPath path) {
|
||||
if (path == ApiHalSubGhzPath1) {
|
||||
LL_GPIO_ResetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_SetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (path == ApiHalSubGhzPath2) {
|
||||
LL_GPIO_SetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_ResetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (path == ApiHalSubGhzPath3) {
|
||||
LL_GPIO_SetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_SetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (path == ApiHalSubGhzPathIsolate) {
|
||||
LL_GPIO_ResetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_ResetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -8,4 +8,5 @@ void api_hal_init() {
|
||||
api_hal_power_init();
|
||||
api_hal_light_init();
|
||||
api_hal_vibro_init();
|
||||
api_hal_subghz_init();
|
||||
}
|
||||
|
Reference in New Issue
Block a user