[FL-2060] FuriHal: SPI refactoring, flexible bus reconfiguration on fly, same design as i2c. (#853)
* FuriHal: SPI refactoring, flexible bus reconfigration on fly, same desiag as i2c. * Lib: update CC1101 driver documentation * FuriHal: update spi symbol names to match naming convention.
This commit is contained in:
		| @@ -19,4 +19,6 @@ void hal_sd_detect_set_low(void) { | ||||
| bool hal_sd_detect(void) { | ||||
|     bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin)); | ||||
|     return result; | ||||
| } | ||||
| } | ||||
|  | ||||
| FuriHalSpiBusHandle* furi_hal_sd_spi_handle = NULL; | ||||
|   | ||||
| @@ -1,10 +1,9 @@ | ||||
| #include <furi-hal-spi-config.h> | ||||
| #include <furi-hal-resources.h> | ||||
|  | ||||
| #define SPI_R SPI1 | ||||
| #define SPI_D SPI2 | ||||
| /* SPI Presets */ | ||||
|  | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @@ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
|  | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @@ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
|  | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @@ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * SD Card in fast mode (after init) | ||||
|  */ | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @@ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * SD Card in slow mode (before init) | ||||
|  */ | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @@ -75,29 +68,187 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
|  | ||||
| osMutexId_t spi_mutex_d = NULL; | ||||
| osMutexId_t spi_mutex_r = NULL; | ||||
| /* SPI Buses */ | ||||
|  | ||||
| const FuriHalSpiBus spi_r = { | ||||
|     .spi=SPI_R, | ||||
|     .mutex=&spi_mutex_r, | ||||
| osMutexId_t furi_hal_spi_bus_r_mutex = NULL; | ||||
|  | ||||
| static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||
|     if (event == FuriHalSpiBusEventInit) { | ||||
|         furi_hal_spi_bus_r_mutex = osMutexNew(NULL); | ||||
|         LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|         bus->current_handle = NULL; | ||||
|     } else if (event == FuriHalSpiBusEventDeinit) { | ||||
|         furi_check(osMutexDelete(furi_hal_spi_bus_r_mutex)); | ||||
|     } else if (event == FuriHalSpiBusEventLock) { | ||||
|         furi_check(osMutexAcquire(furi_hal_spi_bus_r_mutex, osWaitForever) == osOK); | ||||
|     } else if (event == FuriHalSpiBusEventUnlock) { | ||||
|         furi_check(osMutexRelease(furi_hal_spi_bus_r_mutex) == osOK); | ||||
|     } else if (event == FuriHalSpiBusEventActivate) { | ||||
|         LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|     } else if (event == FuriHalSpiBusEventDeactivate) { | ||||
|         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|     } | ||||
| } | ||||
|  | ||||
| FuriHalSpiBus furi_hal_spi_bus_r = { | ||||
|     .spi=SPI1, | ||||
|     .callback = furi_hal_spi_bus_r_event_callback, | ||||
| }; | ||||
|  | ||||
| osMutexId_t furi_hal_spi_bus_d_mutex = NULL; | ||||
|  | ||||
| static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||
|     if (event == FuriHalSpiBusEventInit) { | ||||
|         furi_hal_spi_bus_d_mutex = osMutexNew(NULL); | ||||
|         LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|         bus->current_handle = NULL; | ||||
|     } else if (event == FuriHalSpiBusEventDeinit) { | ||||
|         furi_check(osMutexDelete(furi_hal_spi_bus_d_mutex)); | ||||
|     } else if (event == FuriHalSpiBusEventLock) { | ||||
|         furi_check(osMutexAcquire(furi_hal_spi_bus_d_mutex, osWaitForever) == osOK); | ||||
|     } else if (event == FuriHalSpiBusEventUnlock) { | ||||
|         furi_check(osMutexRelease(furi_hal_spi_bus_d_mutex) == osOK); | ||||
|     } else if (event == FuriHalSpiBusEventActivate) { | ||||
|         LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|     } else if (event == FuriHalSpiBusEventDeactivate) { | ||||
|         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|     } | ||||
| } | ||||
|  | ||||
| FuriHalSpiBus furi_hal_spi_bus_d = { | ||||
|     .spi=SPI2, | ||||
|     .callback = furi_hal_spi_bus_d_event_callback, | ||||
| }; | ||||
|  | ||||
| /* SPI Bus Handles */ | ||||
|  | ||||
| inline static void furi_hal_spi_bus_r_handle_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event, const LL_SPI_InitTypeDef* preset) { | ||||
|     if (event == FuriHalSpiBusHandleEventInit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); | ||||
|     } else if (event == FuriHalSpiBusHandleEventDeinit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|     } else if (event == FuriHalSpiBusHandleEventActivate) { | ||||
|         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||
|         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|         LL_SPI_Enable(handle->bus->spi); | ||||
|  | ||||
|         hal_gpio_init_ex(handle->miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
|         hal_gpio_init_ex(handle->mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
|         hal_gpio_init_ex(handle->sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
|  | ||||
|         hal_gpio_write(handle->cs, false); | ||||
|     } else if (event == FuriHalSpiBusHandleEventDeactivate) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|  | ||||
|         hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|         hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|         hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|  | ||||
|         LL_SPI_Disable(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void furi_hal_spi_bus_handle_subghz_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m); | ||||
| } | ||||
|  | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = { | ||||
|     .bus=&furi_hal_spi_bus_r, | ||||
|     .callback=furi_hal_spi_bus_handle_subghz_event_callback, | ||||
|     .miso=&gpio_spi_r_miso, | ||||
|     .mosi=&gpio_spi_r_mosi, | ||||
|     .clk=&gpio_spi_r_sck, | ||||
|     .sck=&gpio_spi_r_sck, | ||||
|     .cs=&gpio_subghz_cs, | ||||
| }; | ||||
|  | ||||
| const FuriHalSpiBus spi_d = { | ||||
|     .spi=SPI_D, | ||||
|     .mutex=&spi_mutex_d, | ||||
| static void furi_hal_spi_bus_handle_nfc_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m); | ||||
| } | ||||
|  | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = { | ||||
|     .bus=&furi_hal_spi_bus_r, | ||||
|     .callback=furi_hal_spi_bus_handle_nfc_event_callback, | ||||
|     .miso=&gpio_spi_r_miso, | ||||
|     .mosi=&gpio_spi_r_mosi, | ||||
|     .sck=&gpio_spi_r_sck, | ||||
|     .cs=&gpio_nfc_cs, | ||||
| }; | ||||
|  | ||||
| static void furi_hal_spi_bus_handle_external_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||
| } | ||||
|  | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = { | ||||
|     .bus=&furi_hal_spi_bus_r, | ||||
|     .callback=furi_hal_spi_bus_handle_external_event_callback, | ||||
|     .miso=&gpio_ext_pa6, | ||||
|     .mosi=&gpio_ext_pa7, | ||||
|     .sck=&gpio_ext_pb3, | ||||
|     .cs=&gpio_ext_pa4, | ||||
| }; | ||||
|  | ||||
| inline static void furi_hal_spi_bus_d_handle_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event, const LL_SPI_InitTypeDef* preset) { | ||||
|     if (event == FuriHalSpiBusHandleEventInit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); | ||||
|  | ||||
|         hal_gpio_init_ex(handle->miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|         hal_gpio_init_ex(handle->mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|         hal_gpio_init_ex(handle->sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|  | ||||
|     } else if (event == FuriHalSpiBusHandleEventDeinit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); | ||||
|     } else if (event == FuriHalSpiBusHandleEventActivate) { | ||||
|         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||
|         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|         LL_SPI_Enable(handle->bus->spi); | ||||
|         hal_gpio_write(handle->cs, false); | ||||
|     } else if (event == FuriHalSpiBusHandleEventDeactivate) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         LL_SPI_Disable(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void furi_hal_spi_bus_handle_display_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m); | ||||
| } | ||||
|  | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = { | ||||
|     .bus=&furi_hal_spi_bus_d, | ||||
|     .callback=furi_hal_spi_bus_handle_display_event_callback, | ||||
|     .miso=&gpio_spi_d_miso, | ||||
|     .mosi=&gpio_spi_d_mosi, | ||||
|     .clk=&gpio_spi_d_sck, | ||||
|     .sck=&gpio_spi_d_sck, | ||||
|     .cs=&gpio_display_cs, | ||||
| }; | ||||
|  | ||||
| const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax] = { | ||||
|     { .bus=&spi_r, .config=&furi_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, }, | ||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_display, .chip_select=&gpio_display_cs, }, | ||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_sd_fast, .chip_select=&gpio_sdcard_cs, }, | ||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_sd_slow, .chip_select=&gpio_sdcard_cs, }, | ||||
|     { .bus=&spi_r, .config=&furi_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs }, | ||||
| static void furi_hal_spi_bus_handle_sd_fast_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m); | ||||
| } | ||||
|  | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = { | ||||
|     .bus=&furi_hal_spi_bus_d, | ||||
|     .callback=furi_hal_spi_bus_handle_sd_fast_event_callback, | ||||
|     .miso=&gpio_spi_d_miso, | ||||
|     .mosi=&gpio_spi_d_mosi, | ||||
|     .sck=&gpio_spi_d_sck, | ||||
|     .cs=&gpio_sdcard_cs, | ||||
| }; | ||||
|  | ||||
| static void furi_hal_spi_bus_handle_sd_slow_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||
| } | ||||
|  | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = { | ||||
|     .bus=&furi_hal_spi_bus_d, | ||||
|     .callback=furi_hal_spi_bus_handle_sd_slow_event_callback, | ||||
|     .miso=&gpio_spi_d_miso, | ||||
|     .mosi=&gpio_spi_d_mosi, | ||||
|     .sck=&gpio_spi_d_sck, | ||||
|     .cs=&gpio_sdcard_cs, | ||||
| }; | ||||
|   | ||||
| @@ -1,62 +1,60 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <furi-hal-gpio.h> | ||||
| #include <stm32wbxx_ll_spi.h> | ||||
| #include <cmsis_os2.h> | ||||
| #include <furi-hal-spi-types.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_display; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow; | ||||
| /** Preset for ST25R916 */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m; | ||||
|  | ||||
| /** FURI HAL SPI BUS handler | ||||
|  * Structure content may change at some point | ||||
| /** Preset for CC1101 */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m; | ||||
|  | ||||
| /** Preset for ST7567 (Display) */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m; | ||||
|  | ||||
| /** Preset for SdCard in fast mode */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m; | ||||
|  | ||||
| /** Preset for SdCard in slow mode */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m; | ||||
|  | ||||
| /** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/ | ||||
| extern FuriHalSpiBus furi_hal_spi_bus_r; | ||||
|  | ||||
| /** Furi Hal Spi Bus D (Display, SdCard) */ | ||||
| extern FuriHalSpiBus furi_hal_spi_bus_d; | ||||
|  | ||||
| /** CC1101 on `furi_hal_spi_bus_r` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz; | ||||
|  | ||||
| /** ST25R3916 on `furi_hal_spi_bus_r` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc; | ||||
|  | ||||
| /** External on `furi_hal_spi_bus_r` | ||||
|  * Preset: `furi_hal_spi_preset_1edge_low_2m` | ||||
|  *  | ||||
|  * miso: pa6 | ||||
|  * mosi: pa7 | ||||
|  * sck: pb3 | ||||
|  * cs:  pa4 (software controlled) | ||||
|  *  | ||||
|  * @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize | ||||
|  * Bus pins are floating on inactive state, CS high after initialization | ||||
|  *  | ||||
|  */ | ||||
| typedef struct { | ||||
|     const SPI_TypeDef* spi; | ||||
|     const osMutexId_t* mutex; | ||||
|     const GpioPin* miso; | ||||
|     const GpioPin* mosi; | ||||
|     const GpioPin* clk; | ||||
| } FuriHalSpiBus; | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external; | ||||
|  | ||||
| /** FURI HAL SPI Device handler | ||||
|  * Structure content may change at some point | ||||
|  */ | ||||
| typedef struct { | ||||
|     const FuriHalSpiBus* bus; | ||||
|     const LL_SPI_InitTypeDef* config; | ||||
|     const GpioPin* chip_select; | ||||
| } FuriHalSpiDevice; | ||||
| /** ST7567(Display) on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display; | ||||
|  | ||||
| /** FURI HAL SPI Standard Device IDs */ | ||||
| typedef enum { | ||||
|     FuriHalSpiDeviceIdSubGhz,        /** SubGhz: CC1101, non-standard SPI usage */ | ||||
|     FuriHalSpiDeviceIdDisplay,       /** Display: ERC12864, only have MOSI */ | ||||
|     FuriHalSpiDeviceIdSdCardFast,    /** SDCARD: fast mode, after initialization */ | ||||
|     FuriHalSpiDeviceIdSdCardSlow,    /** SDCARD: slow mode, before initialization */ | ||||
|     FuriHalSpiDeviceIdNfc,           /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */ | ||||
| /** SdCard in fast mode on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast; | ||||
|  | ||||
|     FuriHalSpiDeviceIdMax,           /** Service Value, do not use */ | ||||
| } FuriHalSpiDeviceId; | ||||
|  | ||||
| /** Furi Hal Spi Bus R | ||||
|  * CC1101, Nfc | ||||
|  */ | ||||
| extern const FuriHalSpiBus spi_r; | ||||
|  | ||||
| /** Furi Hal Spi Bus D | ||||
|  * Display, SdCard | ||||
|  */ | ||||
| extern const FuriHalSpiBus spi_d; | ||||
|  | ||||
| /** Furi Hal Spi devices */ | ||||
| extern const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax]; | ||||
| /** SdCard in slow mode on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|   | ||||
							
								
								
									
										62
									
								
								firmware/targets/f6/furi-hal/furi-hal-spi-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								firmware/targets/f6/furi-hal/furi-hal-spi-types.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <stddef.h> | ||||
|  | ||||
| #include <furi-hal-gpio.h> | ||||
|  | ||||
| #include <stm32wbxx_ll_spi.h> | ||||
| #include <stm32wbxx_ll_rcc.h> | ||||
| #include <stm32wbxx_ll_bus.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| typedef struct FuriHalSpiBus FuriHalSpiBus; | ||||
| typedef struct FuriHalSpiBusHandle FuriHalSpiBusHandle; | ||||
|  | ||||
| /** FuriHal spi bus states */ | ||||
| typedef enum { | ||||
|     FuriHalSpiBusEventInit, /**< Bus initialization event, called on system start */ | ||||
|     FuriHalSpiBusEventDeinit, /**< Bus deinitialization event, called on system stop */ | ||||
|     FuriHalSpiBusEventLock, /**< Bus lock event, called before activation */ | ||||
|     FuriHalSpiBusEventUnlock, /**< Bus unlock event, called after deactivation */ | ||||
|     FuriHalSpiBusEventActivate, /**< Bus activation event, called before handle activation */ | ||||
|     FuriHalSpiBusEventDeactivate, /**< Bus deactivation event, called after handle deactivation  */ | ||||
| } FuriHalSpiBusEvent; | ||||
|  | ||||
| /** FuriHal spi bus event callback */ | ||||
| typedef void (*FuriHalSpiBusEventCallback)(FuriHalSpiBus* bus, FuriHalSpiBusEvent event); | ||||
|  | ||||
| /** FuriHal spi bus */ | ||||
| struct FuriHalSpiBus { | ||||
|     SPI_TypeDef* spi; | ||||
|     FuriHalSpiBusEventCallback callback; | ||||
|     FuriHalSpiBusHandle* current_handle; | ||||
| }; | ||||
|  | ||||
| /** FuriHal spi handle states */ | ||||
| typedef enum { | ||||
|     FuriHalSpiBusHandleEventInit, /**< Handle init, called on system start, initialize gpio for idle state */ | ||||
|     FuriHalSpiBusHandleEventDeinit, /**< Handle deinit, called on system stop, deinitialize gpio for default state */ | ||||
|     FuriHalSpiBusHandleEventActivate, /**< Handle activate: connect gpio and apply bus config */ | ||||
|     FuriHalSpiBusHandleEventDeactivate, /**< Handle deactivate: disconnect gpio and reset bus config */ | ||||
| } FuriHalSpiBusHandleEvent; | ||||
|  | ||||
| /** FuriHal spi handle event callback */ | ||||
| typedef void (*FuriHalSpiBusHandleEventCallback)(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event); | ||||
|  | ||||
| /** FuriHal spi handle */ | ||||
| struct FuriHalSpiBusHandle { | ||||
|     FuriHalSpiBus* bus; | ||||
|     FuriHalSpiBusHandleEventCallback callback; | ||||
|     const GpioPin* miso; | ||||
|     const GpioPin* mosi; | ||||
|     const GpioPin* sck; | ||||
|     const GpioPin* cs; | ||||
| }; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| @@ -12,89 +12,104 @@ | ||||
| #define TAG "FuriHalSpi" | ||||
|  | ||||
| void furi_hal_spi_init() { | ||||
|     // 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<FuriHalSpiDeviceIdMax; ++i) { | ||||
|         hal_gpio_write(furi_hal_spi_devices[i].chip_select, true); | ||||
|         hal_gpio_init( | ||||
|             furi_hal_spi_devices[i].chip_select, | ||||
|             GpioModeOutputPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh | ||||
|         ); | ||||
|     } | ||||
|     furi_hal_spi_bus_init(&furi_hal_spi_bus_r); | ||||
|     furi_hal_spi_bus_init(&furi_hal_spi_bus_d); | ||||
|  | ||||
|     hal_gpio_init_ex(&gpio_spi_r_miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
|     hal_gpio_init_ex(&gpio_spi_r_mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
|     hal_gpio_init_ex(&gpio_spi_r_sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
|  | ||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow); | ||||
|  | ||||
|     FURI_LOG_I(TAG, "Init OK"); | ||||
| } | ||||
|  | ||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { | ||||
| void furi_hal_spi_bus_init(FuriHalSpiBus* bus) { | ||||
|     furi_assert(bus); | ||||
|     furi_check(osMutexAcquire(*bus->mutex, osWaitForever) == osOK); | ||||
|     bus->callback(bus, FuriHalSpiBusEventInit); | ||||
| } | ||||
|  | ||||
| void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) { | ||||
| void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) { | ||||
|     furi_assert(bus); | ||||
|     furi_check(osMutexRelease(*bus->mutex) == osOK); | ||||
|     bus->callback(bus, FuriHalSpiBusEventDeinit); | ||||
| } | ||||
|  | ||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { | ||||
|     furi_assert(bus); | ||||
|  | ||||
|     LL_SPI_DeInit((SPI_TypeDef*)bus->spi); | ||||
|     LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config); | ||||
|     LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|     LL_SPI_Enable((SPI_TypeDef*)bus->spi); | ||||
| void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) { | ||||
|     furi_assert(handle); | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventInit); | ||||
| } | ||||
|  | ||||
| void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { | ||||
|     while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_TX_FIFO_EMPTY); | ||||
|     while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef *)bus->spi)); | ||||
|     while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||
|         LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); | ||||
| void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { | ||||
|     furi_assert(handle); | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventDeinit); | ||||
| } | ||||
|  | ||||
| void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { | ||||
|     furi_assert(handle); | ||||
|  | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); | ||||
|  | ||||
|     furi_assert(handle->bus->current_handle == NULL); | ||||
|  | ||||
|     handle->bus->current_handle = handle; | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventActivate); | ||||
| } | ||||
|  | ||||
| void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { | ||||
|     furi_assert(handle); | ||||
|     furi_assert(handle->bus->current_handle == handle); | ||||
|  | ||||
|     // Handle event and unset handle | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventDeactivate); | ||||
|     handle->bus->current_handle = NULL; | ||||
|  | ||||
|     // Bus events | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate); | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock); | ||||
| } | ||||
|  | ||||
| static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { | ||||
|     while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY); | ||||
|     while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi)); | ||||
|     while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||
|         LL_SPI_ReceiveData8(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(bus); | ||||
| bool furi_hal_spi_bus_rx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(handle); | ||||
|     furi_assert(handle->bus->current_handle == handle); | ||||
|     furi_assert(buffer); | ||||
|     furi_assert(size > 0); | ||||
|  | ||||
|     return furi_hal_spi_bus_trx(bus, buffer, buffer, size, timeout); | ||||
|     return furi_hal_spi_bus_trx(handle, buffer, buffer, size, timeout); | ||||
| } | ||||
|  | ||||
| bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(bus); | ||||
| bool furi_hal_spi_bus_tx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(handle); | ||||
|     furi_assert(handle->bus->current_handle == handle); | ||||
|     furi_assert(buffer); | ||||
|     furi_assert(size > 0); | ||||
|     bool ret = true; | ||||
|  | ||||
|     while(size > 0) { | ||||
|         if (LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi)) { | ||||
|             LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *buffer); | ||||
|         if (LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) { | ||||
|             LL_SPI_TransmitData8(handle->bus->spi, *buffer); | ||||
|             buffer++; | ||||
|             size--; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); | ||||
|     LL_SPI_ClearFlag_OVR((SPI_TypeDef *)bus->spi); | ||||
|     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||
|     LL_SPI_ClearFlag_OVR(handle->bus->spi); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(bus); | ||||
| bool furi_hal_spi_bus_trx(FuriHalSpiBusHandle* handle, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(handle); | ||||
|     furi_assert(handle->bus->current_handle == handle); | ||||
|     furi_assert(tx_buffer); | ||||
|     furi_assert(rx_buffer); | ||||
|     furi_assert(size > 0); | ||||
| @@ -104,99 +119,22 @@ bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* | ||||
|     bool tx_allowed = true; | ||||
|  | ||||
|     while(size > 0) { | ||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi) && tx_allowed) { | ||||
|             LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *tx_buffer); | ||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) { | ||||
|             LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer); | ||||
|             tx_buffer++; | ||||
|             tx_size--; | ||||
|             tx_allowed = false; | ||||
|         } | ||||
|          | ||||
|         if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef *)bus->spi)) { | ||||
|             *rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); | ||||
|         if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) { | ||||
|             *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi); | ||||
|             rx_buffer++; | ||||
|             size--; | ||||
|             tx_allowed = true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) { | ||||
|     furi_assert(device); | ||||
|     furi_assert(device->config); | ||||
|  | ||||
|     furi_hal_spi_bus_configure(device->bus, device->config); | ||||
| } | ||||
|  | ||||
| const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) { | ||||
|     furi_assert(device_id < FuriHalSpiDeviceIdMax); | ||||
|  | ||||
|     const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id]; | ||||
|     furi_assert(device); | ||||
|     furi_hal_spi_bus_lock(device->bus); | ||||
|     furi_hal_spi_device_configure(device); | ||||
|  | ||||
|     return device; | ||||
| } | ||||
|  | ||||
| void furi_hal_spi_device_return(const FuriHalSpiDevice* device) { | ||||
|     furi_hal_spi_bus_unlock(device->bus); | ||||
| } | ||||
|  | ||||
| bool furi_hal_spi_device_rx(const FuriHalSpiDevice* 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 = furi_hal_spi_bus_rx(device->bus, buffer, size, timeout); | ||||
|  | ||||
|     if (device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, true); | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| bool furi_hal_spi_device_tx(const FuriHalSpiDevice* 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 = furi_hal_spi_bus_tx(device->bus, buffer, size, timeout); | ||||
|  | ||||
|     if (device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, true); | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| bool furi_hal_spi_device_trx(const FuriHalSpiDevice* 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 = furi_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, timeout); | ||||
|  | ||||
|     if (device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, true); | ||||
|     } | ||||
|     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|   | ||||
| @@ -269,7 +269,7 @@ void furi_hal_subghz_init() { | ||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||
|     furi_hal_subghz_state = SubGhzStateIdle; | ||||
|  | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|  | ||||
| #ifdef FURI_HAL_SUBGHZ_TX_GPIO | ||||
|     hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||
| @@ -277,58 +277,58 @@ void furi_hal_subghz_init() { | ||||
|  | ||||
|     // Reset | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|     cc1101_reset(device); | ||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|  | ||||
|     // Prepare GD0 for power on self test | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||
|  | ||||
|     // GD0 low | ||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW); | ||||
|     while(hal_gpio_read(&gpio_cc1101_g0) != false) | ||||
|         ; | ||||
|  | ||||
|     // GD0 high | ||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|     while(hal_gpio_read(&gpio_cc1101_g0) != true) | ||||
|         ; | ||||
|  | ||||
|     // Reset GD0 to floating state | ||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|  | ||||
|     // RF switches | ||||
|     hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||
|     cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||
|  | ||||
|     // Go to sleep | ||||
|     cc1101_shutdown(device); | ||||
|     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||
|  | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
|     FURI_LOG_I(TAG, "Init OK"); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_sleep() { | ||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateIdle); | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|  | ||||
|     cc1101_switch_to_idle(device); | ||||
|     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||
|  | ||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|  | ||||
|     cc1101_shutdown(device); | ||||
|     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||
|  | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_dump_state() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     printf( | ||||
|         "[furi_hal_subghz] cc1101 chip %d, version %d\r\n", | ||||
|         cc1101_get_partnumber(device), | ||||
|         cc1101_get_version(device)); | ||||
|     furi_hal_spi_device_return(device); | ||||
|         cc1101_get_partnumber(&furi_hal_spi_bus_handle_subghz), | ||||
|         cc1101_get_version(&furi_hal_spi_bus_handle_subghz)); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | ||||
| @@ -350,81 +350,81 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_load_registers(const uint8_t data[][2]) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_reset(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||
|     uint32_t i = 0; | ||||
|     while(data[i][0]) { | ||||
|         cc1101_write_reg(device, data[i][0], data[i][1]); | ||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i][0], data[i][1]); | ||||
|         i++; | ||||
|     } | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_load_patable(const uint8_t data[8]) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_set_pa_table(device, data); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_set_pa_table(&furi_hal_spi_bus_handle_subghz, data); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_flush_tx(device); | ||||
|     cc1101_write_fifo(device, data, size); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_flush_rx() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_flush_rx(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_read_fifo(device, data, size); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_shutdown() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     // Reset and shutdown | ||||
|     cc1101_shutdown(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_reset() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|     cc1101_switch_to_idle(device); | ||||
|     cc1101_reset(device); | ||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_idle() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_switch_to_idle(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_rx() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_switch_to_rx(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| bool furi_hal_subghz_tx() { | ||||
|     if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false; | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_switch_to_tx(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_switch_to_tx(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| float furi_hal_subghz_get_rssi() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     int32_t rssi_dec = cc1101_get_rssi(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     int32_t rssi_dec = cc1101_get_rssi(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
|  | ||||
|     float rssi = rssi_dec; | ||||
|     if(rssi_dec >= 128) { | ||||
| @@ -461,7 +461,7 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { | ||||
| } | ||||
|  | ||||
| uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|  | ||||
|     //checking regional settings | ||||
|     bool txrx = false; | ||||
| @@ -503,37 +503,37 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | ||||
|         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; | ||||
|     } | ||||
|  | ||||
|     uint32_t real_frequency = cc1101_set_frequency(device, value); | ||||
|     cc1101_calibrate(device); | ||||
|     uint32_t real_frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, value); | ||||
|     cc1101_calibrate(&furi_hal_spi_bus_handle_subghz); | ||||
|  | ||||
|     while(true) { | ||||
|         CC1101Status status = cc1101_get_status(device); | ||||
|         CC1101Status status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz); | ||||
|         if(status.STATE == CC1101StateIDLE) break; | ||||
|     } | ||||
|  | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
|  | ||||
|     return real_frequency; | ||||
| } | ||||
|  | ||||
| void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     if(path == FuriHalSubGhzPath433) { | ||||
|         hal_gpio_write(&gpio_rf_sw_0, 0); | ||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|     } else if(path == FuriHalSubGhzPath315) { | ||||
|         hal_gpio_write(&gpio_rf_sw_0, 1); | ||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); | ||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||
|     } else if(path == FuriHalSubGhzPath868) { | ||||
|         hal_gpio_write(&gpio_rf_sw_0, 1); | ||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||
|     } else if(path == FuriHalSubGhzPathIsolate) { | ||||
|         hal_gpio_write(&gpio_rf_sw_0, 0); | ||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); | ||||
|         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||
|     } else { | ||||
|         furi_crash(NULL); | ||||
|     } | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
|  | ||||
| volatile uint32_t furi_hal_subghz_capture_delta_duration = 0; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user