summaryrefslogtreecommitdiff
path: root/firmware/rf test/Core
diff options
context:
space:
mode:
authorAnson Bridges <bridges.anson@gmail.com>2026-02-17 11:37:50 -0800
committerAnson Bridges <bridges.anson@gmail.com>2026-02-17 11:37:50 -0800
commitfb1611c0ca99d9e609057c46507be2af8389bb7b (patch)
tree646ac568fdad1e6cf9e1f5767295b183bc5c5441 /firmware/rf test/Core
parent6e952fe110c2a48204c8cb0a836309ab97e5979a (diff)
firmware coadHEADmaster
Diffstat (limited to 'firmware/rf test/Core')
-rw-r--r--firmware/rf test/Core/Inc/fonts.h22
-rw-r--r--firmware/rf test/Core/Inc/libs.h27
-rw-r--r--firmware/rf test/Core/Inc/lis2dw12.h43
-rw-r--r--firmware/rf test/Core/Inc/main.h69
-rw-r--r--firmware/rf test/Core/Inc/sharpmem.h41
-rw-r--r--firmware/rf test/Core/Inc/stm32wbxx_hal_conf.h352
-rw-r--r--firmware/rf test/Core/Inc/stm32wbxx_it.h70
-rw-r--r--firmware/rf test/Core/Inc/w25q_mem.hrr218
-rw-r--r--firmware/rf test/Core/Src/fonts.c22
-rw-r--r--firmware/rf test/Core/Src/lis2dw12.c8
-rw-r--r--firmware/rf test/Core/Src/main.c612
-rw-r--r--firmware/rf test/Core/Src/sharpmem.c160
-rw-r--r--firmware/rf test/Core/Src/stm32wbxx_hal_msp.c348
-rw-r--r--firmware/rf test/Core/Src/stm32wbxx_it.c260
-rw-r--r--firmware/rf test/Core/Src/syscalls.c176
-rw-r--r--firmware/rf test/Core/Src/sysmem.c79
-rw-r--r--firmware/rf test/Core/Src/system_stm32wbxx.c378
-rw-r--r--firmware/rf test/Core/Src/w25q_mem.rrr1521
-rw-r--r--firmware/rf test/Core/Startup/startup_stm32wb55cgux.s447
19 files changed, 4853 insertions, 0 deletions
diff --git a/firmware/rf test/Core/Inc/fonts.h b/firmware/rf test/Core/Inc/fonts.h
new file mode 100644
index 0000000..3a4cbc6
--- /dev/null
+++ b/firmware/rf test/Core/Inc/fonts.h
@@ -0,0 +1,22 @@
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifndef _FONTS_H
+#define _FONTS_H
+
+#define NUMBER_OF_FONTS 1
+
+typedef struct {
+ uint8_t char_w;
+ uint8_t char_h;
+ uint8_t bytes_per_row;
+ uint8_t bytes_per_char;
+ uint8_t *font_bytes;
+ uint8_t *lookup;
+} bitmap_font_t;
+
+extern bitmap_font_t** fonts;
+
+void set_up_fonts();
+
+#endif
diff --git a/firmware/rf test/Core/Inc/libs.h b/firmware/rf test/Core/Inc/libs.h
new file mode 100644
index 0000000..d11de62
--- /dev/null
+++ b/firmware/rf test/Core/Inc/libs.h
@@ -0,0 +1,27 @@
+/**
+ *******************************************
+ * @file libs.h
+ * @author Dmitriy Semenov / Crazy_Geeks
+ * @brief Internal header for adding sys libs and defines
+ *******************************************
+*/
+
+#ifndef LIBS_H_
+#define LIBS_H_
+
+#include "main.h" ///< Main project file
+#include <stdint.h> ///< Std types
+#include <stdbool.h> ///< _Bool to bool
+#include <string.h> ///< Lib for sprintf, strlen, etc
+
+typedef uint8_t u8_t; ///< 8-bit unsigned
+typedef int8_t i8_t; ///< 8-bit signed
+typedef uint16_t u16_t; ///< 16-bit unsigned
+typedef int16_t i16_t; ///< 16-bit signed
+typedef uint32_t u32_t; ///< 32-bit unsigned
+typedef int32_t i32_t; ///< 32-bit signed
+typedef float fl_t; ///< float type
+
+#define delay(x) HAL_Delay(x) ///< arduino-supportable delay or RTOS support ability
+
+#endif /* LIBS_H_ */
diff --git a/firmware/rf test/Core/Inc/lis2dw12.h b/firmware/rf test/Core/Inc/lis2dw12.h
new file mode 100644
index 0000000..6430da6
--- /dev/null
+++ b/firmware/rf test/Core/Inc/lis2dw12.h
@@ -0,0 +1,43 @@
+/*
+ * lis2dw12.h
+ *
+ * Created on: Dec 30, 2025
+ * Author: Anson Bridges
+ */
+
+#ifndef INC_LIS2DW12_H_
+#define INC_LIS2DW12_H_
+
+#include <stdint.h>
+
+const uint8_t LIS2DW_ADDR = 0x32; //0x0011001_
+
+const uint8_t TAP_THS_Z = 0x32;
+const uint8_t TAP_THS_Y = 0x31;
+const uint8_t TAP_THS_X = 0x30;
+const uint8_t TAP_SRC = 0x39;
+const uint8_t OUT_X_L = 0x28;
+const uint8_t CTRL1 = 0x20;
+const uint8_t CTRL3 = 0x22;
+const uint8_t CTRL6 = 0x25;
+const uint8_t CTRL7 = 0x3F;
+const uint8_t INT_DUR = 0x33;
+
+const uint8_t INIT_CTRL1 = 0b01110111; // power mode
+const uint8_t INIT_CTRL3 = 0b00010000;
+const uint8_t INIT_CTRL6 = 0xC8;
+const uint8_t INIT_CTRL7 = 0b00100000; // enable interrupts
+const uint8_t INIT_INT_DUR = 0b00001100;
+const uint8_t INIT_TAP_Z = 0b11101100; //first 3 bits enable tap x/y/z, last 5 z threshold
+const uint8_t INIT_TAP_Y = 0b11101100; //first 3 bits tap priority, last 5 y threshold
+const uint8_t INIT_TAP_X = 0b00001100; // first 3 4D/6D, last 5 x threshold
+
+const uint8_t TAP_IA = 0b01000000;
+const uint8_t TAP_SINGLE = 0b00100000;
+const uint8_t TAP_DOUBLE = 0b00010000;
+const uint8_t TAP_SIGN = 0b00001000;
+const uint8_t TAP_X = 0b00000100;
+const uint8_t TAP_Y = 0b00000010;
+const uint8_t TAP_Z = 0b00000001;
+
+#endif /* INC_LIS2DW12_H_ */
diff --git a/firmware/rf test/Core/Inc/main.h b/firmware/rf test/Core/Inc/main.h
new file mode 100644
index 0000000..c4ad39b
--- /dev/null
+++ b/firmware/rf test/Core/Inc/main.h
@@ -0,0 +1,69 @@
+/* USER CODE BEGIN Header */
+/**
+ ******************************************************************************
+ * @file : main.h
+ * @brief : Header for main.c file.
+ * This file contains the common defines of the application.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2025 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+/* USER CODE END Header */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __MAIN_H
+#define __MAIN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32wbxx_hal.h"
+
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+/* Exported types ------------------------------------------------------------*/
+/* USER CODE BEGIN ET */
+
+/* USER CODE END ET */
+
+/* Exported constants --------------------------------------------------------*/
+/* USER CODE BEGIN EC */
+
+/* USER CODE END EC */
+
+/* Exported macro ------------------------------------------------------------*/
+/* USER CODE BEGIN EM */
+
+/* USER CODE END EM */
+
+/* Exported functions prototypes ---------------------------------------------*/
+void Error_Handler(void);
+
+/* USER CODE BEGIN EFP */
+
+/* USER CODE END EFP */
+
+/* Private defines -----------------------------------------------------------*/
+
+/* USER CODE BEGIN Private defines */
+void SharpMem_Init();
+/* USER CODE END Private defines */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MAIN_H */
diff --git a/firmware/rf test/Core/Inc/sharpmem.h b/firmware/rf test/Core/Inc/sharpmem.h
new file mode 100644
index 0000000..79f91aa
--- /dev/null
+++ b/firmware/rf test/Core/Inc/sharpmem.h
@@ -0,0 +1,41 @@
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "stm32wbxx_hal.h"
+
+#ifndef _STM32_SHARPMEM
+#define _STM32_SHARPMEM
+
+#define SHARPMEM_BIT_WRITECMD (0x01) // 0x80 in LSB format
+#define SHARPMEM_BIT_VCOM (0x02) // 0x40 in LSB format
+#define SHARPMEM_BIT_CLEAR (0x04) // 0x20 in LSB format
+
+typedef struct
+{
+ uint16_t width;
+ uint16_t height;
+ uint16_t cs_pin;
+ GPIO_TypeDef *cs_pin_bank;
+ uint16_t lcdmode_pin;
+ GPIO_TypeDef *lcdmode_pin_bank;
+ SPI_HandleTypeDef *spidev;
+
+ uint8_t *_buffer;
+ uint8_t _sharpmem_vcom;
+} SharpMemDisplay_t;
+
+void SHARPMEM_draw_pixel(SharpMemDisplay_t *display, uint16_t x, uint16_t y, bool black);
+void SHARPMEM_draw_line(SharpMemDisplay_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool black, uint8_t thickness);
+void SHARPMEM_draw_circle(SharpMemDisplay_t *display, uint16_t x, uint16_t y, uint8_t r, bool filled);
+void SHARPMEM_write(SharpMemDisplay_t *display, char *text, uint8_t font_index, uint16_t x, uint16_t y, bool inverse, bool force_bg);
+void SHARPMEM_draw_rect(SharpMemDisplay_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool filled);
+uint8_t SHARPMEM_get_pixel(SharpMemDisplay_t *display, uint16_t x, uint16_t y);
+void SHARPMEM_clear_display(SharpMemDisplay_t *display);
+void SHARPMEM_refresh_display(SharpMemDisplay_t *display);
+void SHARPMEM_clear_display_buffer(SharpMemDisplay_t *display);
+uint8_t *SHARPMEM_get_buffer(SharpMemDisplay_t *display);
+
+void SHARPMEM_TOGGLEVCOM(SharpMemDisplay_t *display);
+
+
+#endif
diff --git a/firmware/rf test/Core/Inc/stm32wbxx_hal_conf.h b/firmware/rf test/Core/Inc/stm32wbxx_hal_conf.h
new file mode 100644
index 0000000..a3dcf46
--- /dev/null
+++ b/firmware/rf test/Core/Inc/stm32wbxx_hal_conf.h
@@ -0,0 +1,352 @@
+/* USER CODE BEGIN Header */
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_conf.h
+ * @author MCD Application Team
+ * @brief HAL configuration file.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+/* USER CODE END Header */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32WBxx_HAL_CONF_H
+#define __STM32WBxx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* ########################## Module Selection ############################## */
+/**
+ * @brief This is the list of modules to be used in the HAL driver
+ */
+#define HAL_MODULE_ENABLED
+/*#define HAL_ADC_MODULE_ENABLED */
+/*#define HAL_CRYP_MODULE_ENABLED */
+/*#define HAL_COMP_MODULE_ENABLED */
+/*#define HAL_CRC_MODULE_ENABLED */
+#define HAL_HSEM_MODULE_ENABLED
+#define HAL_I2C_MODULE_ENABLED
+#define HAL_IPCC_MODULE_ENABLED
+/*#define HAL_IRDA_MODULE_ENABLED */
+/*#define HAL_IWDG_MODULE_ENABLED */
+/*#define HAL_LCD_MODULE_ENABLED */
+/*#define HAL_LPTIM_MODULE_ENABLED */
+/*#define HAL_PCD_MODULE_ENABLED */
+/*#define HAL_PKA_MODULE_ENABLED */
+/*#define HAL_QSPI_MODULE_ENABLED */
+/*#define HAL_RNG_MODULE_ENABLED */
+#define HAL_RTC_MODULE_ENABLED
+/*#define HAL_SAI_MODULE_ENABLED */
+/*#define HAL_SMBUS_MODULE_ENABLED */
+/*#define HAL_SMARTCARD_MODULE_ENABLED */
+#define HAL_SPI_MODULE_ENABLED
+/*#define HAL_TIM_MODULE_ENABLED */
+/*#define HAL_TSC_MODULE_ENABLED */
+/*#define HAL_UART_MODULE_ENABLED */
+/*#define HAL_USART_MODULE_ENABLED */
+/*#define HAL_WWDG_MODULE_ENABLED */
+#define HAL_EXTI_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+
+#define USE_HAL_ADC_REGISTER_CALLBACKS 0u
+#define USE_HAL_COMP_REGISTER_CALLBACKS 0u
+#define USE_HAL_CRYP_REGISTER_CALLBACKS 0u
+#define USE_HAL_I2C_REGISTER_CALLBACKS 0u
+#define USE_HAL_IRDA_REGISTER_CALLBACKS 0u
+#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0u
+#define USE_HAL_PCD_REGISTER_CALLBACKS 0u
+#define USE_HAL_PKA_REGISTER_CALLBACKS 0u
+#define USE_HAL_QSPI_REGISTER_CALLBACKS 0u
+#define USE_HAL_RNG_REGISTER_CALLBACKS 0u
+#define USE_HAL_RTC_REGISTER_CALLBACKS 0u
+#define USE_HAL_SAI_REGISTER_CALLBACKS 0u
+#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0u
+#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0u
+#define USE_HAL_SPI_REGISTER_CALLBACKS 0u
+#define USE_HAL_TIM_REGISTER_CALLBACKS 0u
+#define USE_HAL_TSC_REGISTER_CALLBACKS 0u
+#define USE_HAL_UART_REGISTER_CALLBACKS 0u
+#define USE_HAL_USART_REGISTER_CALLBACKS 0u
+#define USE_HAL_WWDG_REGISTER_CALLBACKS 0u
+
+/* ########################## Oscillator Values adaptation ####################*/
+/**
+ * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSE is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSE_VALUE)
+#define HSE_VALUE 32000000U /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined (HSE_STARTUP_TIMEOUT)
+ #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief Internal Multiple Speed oscillator (MSI) default value.
+ * This value is the default MSI range value after Reset.
+ */
+#if !defined (MSI_VALUE)
+ #define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* MSI_VALUE */
+
+/**
+ * @brief Internal High Speed oscillator (HSI) value.
+ * This value is used by the RCC HAL module to compute the system frequency
+ * (when HSI is used as system clock source, directly or through the PLL).
+ */
+#if !defined (HSI_VALUE)
+#define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+ * @brief Internal Low Speed oscillator (LSI1) value.
+ */
+#if !defined (LSI1_VALUE)
+ #define LSI1_VALUE ((uint32_t)32000) /*!< LSI1 Typical Value in Hz*/
+#endif /* LSI1_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
+ The real value may vary depending on the variations
+ in voltage and temperature.*/
+/**
+ * @brief Internal Low Speed oscillator (LSI2) value.
+ */
+#if !defined (LSI2_VALUE)
+ #define LSI2_VALUE ((uint32_t)32000) /*!< LSI2 Typical Value in Hz*/
+#endif /* LSI2_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
+ The real value may vary depending on the variations
+ in voltage and temperature.*/
+
+/**
+ * @brief External Low Speed oscillator (LSE) value.
+ * This value is used by the UART, RTC HAL module to compute the system frequency
+ */
+#if !defined (LSE_VALUE)
+#define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/
+#endif /* LSE_VALUE */
+
+/**
+ * @brief Internal Multiple Speed oscillator (HSI48) default value.
+ * This value is the default HSI48 range value after Reset.
+ */
+#if !defined (HSI48_VALUE)
+ #define HSI48_VALUE ((uint32_t)48000000) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI48_VALUE */
+
+#if !defined (LSE_STARTUP_TIMEOUT)
+#define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */
+#endif /* LSE_STARTUP_TIMEOUT */
+
+/**
+ * @brief External clock source for SAI1 peripheral
+ * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source
+ * frequency.
+ */
+#if !defined (EXTERNAL_SAI1_CLOCK_VALUE)
+ #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)2097000) /*!< Value of the SAI1 External clock source in Hz*/
+#endif /* EXTERNAL_SAI1_CLOCK_VALUE */
+
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+ === you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+ * @brief This is the HAL system configuration section
+ */
+
+#define VDD_VALUE 3300U /*!< Value of VDD in mv */
+#define TICK_INT_PRIORITY 15U /*!< tick interrupt priority */
+#define USE_RTOS 0U
+#define PREFETCH_ENABLE 1U
+#define INSTRUCTION_CACHE_ENABLE 1U
+#define DATA_CACHE_ENABLE 1U
+
+/* ########################## Assert Selection ############################## */
+/**
+ * @brief Uncomment the line below to expanse the "assert_param" macro in the
+ * HAL drivers code
+ */
+/* #define USE_FULL_ASSERT 1U */
+
+/* ################## SPI peripheral configuration ########################## */
+
+/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
+ * Activated: CRC code is present inside driver
+ * Deactivated: CRC code cleaned from driver
+ */
+
+#define USE_SPI_CRC 0U
+
+/* Includes ------------------------------------------------------------------*/
+/**
+ * @brief Include module's header file
+ */
+#ifdef HAL_DMA_MODULE_ENABLED
+ #include "stm32wbxx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+ #include "stm32wbxx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_COMP_MODULE_ENABLED
+ #include "stm32wbxx_hal_comp.h"
+#endif /* HAL_COMP_MODULE_ENABLED */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+ #include "stm32wbxx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+ #include "stm32wbxx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+ #include "stm32wbxx_hal_cryp.h"
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_EXTI_MODULE_ENABLED
+ #include "stm32wbxx_hal_exti.h"
+#endif /* HAL_EXTI_MODULE_ENABLED */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+ #include "stm32wbxx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+ #include "stm32wbxx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_HSEM_MODULE_ENABLED
+ #include "stm32wbxx_hal_hsem.h"
+#endif /* HAL_HSEM_MODULE_ENABLED */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32wbxx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_IPCC_MODULE_ENABLED
+ #include "stm32wbxx_hal_ipcc.h"
+#endif /* HAL_IPCC_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32wbxx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32wbxx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LCD_MODULE_ENABLED
+ #include "stm32wbxx_hal_lcd.h"
+#endif /* HAL_LCD_MODULE_ENABLED */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+ #include "stm32wbxx_hal_lptim.h"
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+ #include "stm32wbxx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+#ifdef HAL_PKA_MODULE_ENABLED
+ #include "stm32wbxx_hal_pka.h"
+#endif /* HAL_PKA_MODULE_ENABLED */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32wbxx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_QSPI_MODULE_ENABLED
+ #include "stm32wbxx_hal_qspi.h"
+#endif /* HAL_QSPI_MODULE_ENABLED */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+ #include "stm32wbxx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+ #include "stm32wbxx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32wbxx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+ #include "stm32wbxx_hal_sai.h"
+#endif /* HAL_SAI_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32wbxx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_SMBUS_MODULE_ENABLED
+ #include "stm32wbxx_hal_smbus.h"
+#endif /* HAL_SMBUS_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32wbxx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32wbxx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_TSC_MODULE_ENABLED
+ #include "stm32wbxx_hal_tsc.h"
+#endif /* HAL_TSC_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32wbxx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32wbxx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32wbxx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef USE_FULL_ASSERT
+/**
+ * @brief The assert_param macro is used for function's parameters check.
+ * @param expr If expr is false, it calls assert_failed function
+ * which reports the name of the source file and the source
+ * line number of the call that failed.
+ * If expr is true, it returns no value.
+ * @retval None
+ */
+ #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+ void assert_failed(uint8_t* file, uint32_t line);
+#else
+ #define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32WBxx_HAL_CONF_H */
diff --git a/firmware/rf test/Core/Inc/stm32wbxx_it.h b/firmware/rf test/Core/Inc/stm32wbxx_it.h
new file mode 100644
index 0000000..8a8788f
--- /dev/null
+++ b/firmware/rf test/Core/Inc/stm32wbxx_it.h
@@ -0,0 +1,70 @@
+/* USER CODE BEGIN Header */
+/**
+ ******************************************************************************
+ * @file stm32wbxx_it.h
+ * @brief This file contains the headers of the interrupt handlers.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2025 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+/* USER CODE END Header */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32WBxx_IT_H
+#define __STM32WBxx_IT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+/* Exported types ------------------------------------------------------------*/
+/* USER CODE BEGIN ET */
+
+/* USER CODE END ET */
+
+/* Exported constants --------------------------------------------------------*/
+/* USER CODE BEGIN EC */
+
+/* USER CODE END EC */
+
+/* Exported macro ------------------------------------------------------------*/
+/* USER CODE BEGIN EM */
+
+/* USER CODE END EM */
+
+/* Exported functions prototypes ---------------------------------------------*/
+void NMI_Handler(void);
+void HardFault_Handler(void);
+void MemManage_Handler(void);
+void BusFault_Handler(void);
+void UsageFault_Handler(void);
+void SVC_Handler(void);
+void DebugMon_Handler(void);
+void PendSV_Handler(void);
+void SysTick_Handler(void);
+void RTC_WKUP_IRQHandler(void);
+void IPCC_C1_RX_IRQHandler(void);
+void IPCC_C1_TX_IRQHandler(void);
+void HSEM_IRQHandler(void);
+/* USER CODE BEGIN EFP */
+
+/* USER CODE END EFP */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32WBxx_IT_H */
diff --git a/firmware/rf test/Core/Inc/w25q_mem.hrr b/firmware/rf test/Core/Inc/w25q_mem.hrr
new file mode 100644
index 0000000..fd80751
--- /dev/null
+++ b/firmware/rf test/Core/Inc/w25q_mem.hrr
@@ -0,0 +1,218 @@
+/**
+ *******************************************
+ * @file w25q_mem.h
+ * @author Dmitriy Semenov / Crazy_Geeks
+ * @version 0.1b
+ * @date 12-August-2021
+ * @brief Header for W25Qxxx lib
+ * @note https://github.com/Crazy-Geeks/STM32-W25Q-QSPI
+ *******************************************
+ *
+ * @note https://ru.mouser.com/datasheet/2/949/w25q256jv_spi_revg_08032017-1489574.pdf
+ * @note https://www.st.com/resource/en/application_note/DM00227538-.pdf
+*/
+
+#ifndef W25Q_QSPI_W25Q_MEM_H_
+#define W25Q_QSPI_W25Q_MEM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "libs.h"
+
+/**
+ * @addtogroup W25Q_Driver
+ * @brief W25Q QSPI Driver
+ * @{
+ */
+
+/**
+ * @defgroup W25Q_Param W25Q Chip's Parameters
+ * @brief User's chip parameters
+ * @{
+ */
+// YOUR CHIP'S SETTINGS
+/// Mem size in MB-bit
+#define MEM_FLASH_SIZE 128U // 128 MB-bit
+/// Mem big block size in KB
+#define MEM_BLOCK_SIZE 64U // 64 KB: 256 pages
+/// Mem small block size in KB
+#define MEM_SBLOCK_SIZE 32U // 32 KB: 128 pages
+/// Mem sector size in KB
+#define MEM_SECTOR_SIZE 4U // 4 KB : 16 pages
+/// Mem page size in bytes
+#define MEM_PAGE_SIZE 256U // 256 byte : 1 page
+/// Blocks count
+#define BLOCK_COUNT (MEM_FLASH_SIZE * 2) // 512 blocks
+/// Sector count
+#define SECTOR_COUNT (BLOCK_COUNT * 16) // 8192 sectors
+/// Pages count
+#define PAGE_COUNT (SECTOR_COUNT * 16) // 131'072 pages
+
+/**@}*/
+
+/**
+ * @enum W25Q_STATE
+ * @brief W25Q Return State
+ * Lib's functions status returns
+ * @{
+ */
+typedef enum{
+ W25Q_OK = 0, ///< Chip OK - Execution fine
+ W25Q_BUSY = 1, ///< Chip busy
+ W25Q_PARAM_ERR = 2, ///< Function parameters error
+ W25Q_CHIP_ERR = 3, ///< Chip error
+ W25Q_SPI_ERR = 4, ///< SPI Bus err
+ W25Q_CHIP_IGNORE = 5, ///< Chip ignore state
+}W25Q_STATE;
+/** @} */
+
+/**
+ * @struct W25Q_STATUS_REG
+ * @brief W25Q Status Registers
+ * @TODO: Mem protected recognition
+ *
+ * Structure to check chip's status registers
+ * @{
+ */
+typedef struct{
+ bool BUSY; ///< Erase/Write in progress
+ bool WEL; ///< Write enable latch (1 - write allowed)
+ bool QE; ///< Quad SPI mode
+ bool SUS; ///< Suspend Status
+ bool ADS; ///< Current addr mode (0-3 byte / 1-4 byte)
+ bool ADP; ///< Power-up addr mode
+ bool SLEEP; ///< Sleep Status
+}W25Q_STATUS_REG;
+/** @} */
+
+
+W25Q_STATE W25Q_Init(void); ///< Initalize function
+
+W25Q_STATE W25Q_EnableVolatileSR(void); ///< Make Status Register Volatile
+W25Q_STATE W25Q_ReadStatusReg(u8_t *reg_data, u8_t reg_num); ///< Read status register to variable
+W25Q_STATE W25Q_WriteStatusReg(u8_t reg_data, u8_t reg_num);///< Write status register from variable
+W25Q_STATE W25Q_ReadStatusStruct(W25Q_STATUS_REG *status); ///< Read all status registers to struct
+W25Q_STATE W25Q_IsBusy(void); ///< Check chip's busy status
+
+W25Q_STATE W25Q_ReadSByte(i8_t *buf, u8_t pageShift, u32_t pageNum); ///< Read signed 8-bit variable
+W25Q_STATE W25Q_ReadByte(u8_t *buf, u8_t pageShift, u32_t pageNum); ///< Read 8-bit variable
+W25Q_STATE W25Q_ReadSWord(i16_t *buf, u8_t pageShift, u32_t pageNum); ///< Read signed 16-bit variable
+W25Q_STATE W25Q_ReadWord(u16_t *buf, u8_t pageShift, u32_t pageNum); ///< Read 16-bit variable
+W25Q_STATE W25Q_ReadSLong(i32_t *buf, u8_t pageShift, u32_t pageNum); ///< Read signed 32-bit variable
+W25Q_STATE W25Q_ReadLong(u32_t *buf, u8_t pageShift, u32_t pageNum); ///< Read 32-bit variable
+W25Q_STATE W25Q_ReadData(u8_t *buf, u16_t len, u8_t pageShift, u32_t pageNum); ///< Read any 8-bit data
+W25Q_STATE W25Q_ReadRaw(u8_t *buf, u16_t data_len, u32_t rawAddr); ///< Read data from raw addr
+W25Q_STATE W25Q_SingleRead(u8_t *buf, u32_t len, u32_t Addr); ///< Read data from raw addr by single line
+
+W25Q_STATE W25Q_EraseSector(u32_t SectAddr); ///< Erase 4KB Sector
+W25Q_STATE W25Q_EraseBlock(u32_t BlockAddr, u8_t size); ///< Erase 32KB/64KB Sector
+W25Q_STATE W25Q_EraseChip(void); ///< Erase all chip
+
+W25Q_STATE W25Q_ProgramSByte(i8_t buf, u8_t pageShift, u32_t pageNum); ///< Program signed 8-bit variable
+W25Q_STATE W25Q_ProgramByte(u8_t buf, u8_t pageShift, u32_t pageNum); ///< Program 8-bit variable
+W25Q_STATE W25Q_ProgramSWord(i16_t buf, u8_t pageShift, u32_t pageNum); ///< Program signed 16-bit variable
+W25Q_STATE W25Q_ProgramWord(u16_t buf, u8_t pageShift, u32_t pageNum); ///< Program 16-bit variable
+W25Q_STATE W25Q_ProgramSLong(i32_t buf, u8_t pageShift, u32_t pageNum); ///< Program signed 32-bit variable
+W25Q_STATE W25Q_ProgramLong(u32_t buf, u8_t pageShift, u32_t pageNum); ///< Program 32-bit variable
+W25Q_STATE W25Q_ProgramData(u8_t *buf, u16_t len, u8_t pageShift, u32_t pageNum); ///< Program any 8-bit data
+W25Q_STATE W25Q_ProgramRaw(u8_t *buf, u16_t data_len, u32_t rawAddr); ///< Program data to raw addr
+
+W25Q_STATE W25Q_SetBurstWrap(u8_t WrapSize); ///< Set Burst with Wrap
+
+W25Q_STATE W25Q_ProgSuspend(void); ///< Pause Programm/Erase operation
+W25Q_STATE W25Q_ProgResume(void); ///< Resume Programm/Erase operation
+
+W25Q_STATE W25Q_Sleep(void); ///< Set low current consumption
+W25Q_STATE W25Q_WakeUP(void); ///< Wake the chip up from sleep mode
+
+W25Q_STATE W25Q_ReadID(u8_t *buf); ///< Read chip ID
+W25Q_STATE W25Q_ReadFullID(u8_t *buf); ///< Read full chip ID (Manufacturer ID + Device ID)
+W25Q_STATE W25Q_ReadUID(u8_t *buf); ///< Read unique chip ID
+W25Q_STATE W25Q_ReadJEDECID(u8_t *buf); ///< Read ID by JEDEC Standards
+W25Q_STATE W25Q_ReadSFDPRegister(u8_t *buf); ///< Read device descriptor (SFDP Standard)
+
+W25Q_STATE W25Q_EraseSecurityRegisters(u8_t numReg); ///< Erase security register
+W25Q_STATE W25Q_ProgSecurityRegisters(u8_t *buf, u8_t numReg, u8_t byteAddr); ///< Program security register
+W25Q_STATE W25Q_ReadSecurityRegisters(u8_t *buf, u8_t numReg, u8_t byteAddr); ///< Read security register
+
+W25Q_STATE W25Q_BlockReadOnly(u32_t Addr, bool enable); ///< Individual block/sector read-only lock
+W25Q_STATE W25Q_BlockReadOnlyCheck(bool *state, u32_t Addr); ///< Check block's/sector's read-only lock status
+W25Q_STATE W25Q_GlobalReadOnly(bool enable); ///< Set read-only param to all chip
+
+W25Q_STATE W25Q_SwReset(bool force); ///< Software reset
+
+
+/**
+ * @defgroup W25Q_Commands W25Q Chip's Commands
+ * @brief W25Q Chip commands from datasheet
+ * @{
+ */
+#define W25Q_WRITE_ENABLE 0x06U ///< sets WEL bit, must be set before any write/program/erase
+#define W25Q_WRITE_DISABLE 0x04U ///< resets WEL bit (state after power-up)
+#define W25Q_ENABLE_VOLATILE_SR 0x50U ///< check 7.1 in datasheet
+#define W25Q_READ_SR1 0x05U ///< read status-register 1
+#define W25Q_READ_SR2 0x35U ///< read status-register 2
+#define W25Q_READ_SR3 0x15U ///< read ststus-register 3
+#define W25Q_WRITE_SR1 0x01U ///< write status-register 1 (8.2.5)
+#define W25Q_WRITE_SR2 0x31U ///< write status-register 2 (8.2.5)
+#define W25Q_WRITE_SR3 0x11U ///< write status-register 3 (8.2.5)
+#define W25Q_READ_EXT_ADDR_REG 0xC8U ///< read extended addr reg (only in 3-byte mode)
+#define W25Q_WRITE_EXT_ADDR_REG 0xC8U ///< write extended addr reg (only in 3-byte mode)
+#define W25Q_ENABLE_4B_MODE 0xB7U ///< enable 4-byte mode (128+ MB address)
+#define W25Q_DISABLE_4B_MODE 0xE9U ///< disable 4-byte mode (<=128MB)
+#define W25Q_READ_DATA 0x03U ///< read data by standard SPI
+#define W25Q_READ_DATA_4B 0x13U ///< read data by standard SPI in 4-byte mode
+#define W25Q_FAST_READ 0x0BU ///< highest FR speed (8.2.12)
+#define W25Q_FAST_READ_4B 0x0CU ///< fast read in 4-byte mode
+#define W25Q_FAST_READ_DUAL_OUT 0x3BU ///< fast read in dual-SPI OUTPUT (8.2.14)
+#define W25Q_FAST_READ_DUAL_OUT_4B 0x3CU ///< fast read in dual-SPI OUTPUT in 4-byte mode
+#define W25Q_FAST_READ_QUAD_OUT 0x6BU ///< fast read in quad-SPI OUTPUT (8.2.16)
+#define W25Q_FAST_READ_QUAD_OUT_4B 0x6CU ///< fast read in quad-SPI OUTPUT in 4-byte mode
+#define W25Q_FAST_READ_DUAL_IO 0xBBU ///< fast read in dual-SPI I/O (address transmits by both lines)
+#define W25Q_FAST_READ_DUAL_IO_4B 0xBCU ///< fast read in dual-SPI I/O in 4-byte mode
+#define W25Q_FAST_READ_QUAD_IO 0xEBU ///< fast read in quad-SPI I/O (address transmits by quad lines)
+#define W25Q_FAST_READ_QUAD_IO_4B 0xECU ///< fast read in quad-SPI I/O in 4-byte mode
+#define W25Q_SET_BURST_WRAP 0x77U ///< use with quad-I/O (8.2.22)
+#define W25Q_PAGE_PROGRAM 0x02U ///< program page (256bytes) by single SPI line
+#define W25Q_PAGE_PROGRAM_4B 0x12U ///< program page by single SPI in 4-byte mode
+#define W25Q_PAGE_PROGRAM_QUAD_INP 0x32U ///< program page (256bytes) by quad SPI lines
+#define W25Q_PAGE_PROGRAM_QUAD_INP_4B 0x34U ///< program page by quad SPI in 4-byte mode
+#define W25Q_SECTOR_ERASE 0x20U ///< sets all 4Kbyte sector with 0xFF (erases it)
+#define W25Q_SECTOR_ERASE_4B 0x21U ///< sets all 4Kbyte sector with 0xFF in 4-byte mode
+#define W25Q_32KB_BLOCK_ERASE 0x52U ///< sets all 32Kbyte block with 0xFF
+#define W25Q_64KB_BLOCK_ERASE 0xD8U ///< sets all 64Kbyte block with 0xFF
+#define W25Q_64KB_BLOCK_ERASE_4B 0xDCU ///< sets all 64Kbyte sector with 0xFF in 4-byte mode
+#define W25Q_CHIP_ERASE 0xC7U ///< fill all the chip with 0xFF
+//#define W25Q_CHIP_ERASE 0x60U ///< another way to erase chip
+#define W25Q_ERASEPROG_SUSPEND 0x75U ///< suspend erase/program operation (can be applied only when SUS=0, BYSY=1)
+#define W25Q_ERASEPROG_RESUME 0x7AU ///< resume erase/program operation (if SUS=1, BUSY=0)
+#define W25Q_POWERDOWN 0xB9U ///< powers down the chip (power-up by reading ID)
+#define W25Q_POWERUP 0xABU ///< release power-down
+#define W25Q_DEVID 0xABU ///< read Device ID (same as powerup)
+#define W25Q_FULLID 0x90U ///< read Manufacturer ID & Device ID
+#define W25Q_FULLID_DUAL_IO 0x92U ///< read Manufacturer ID & Device ID by dual I/O
+#define W25Q_FULLID_QUAD_IO 0x94U ///< read Manufacturer ID & Device ID by quad I/O
+#define W25Q_READ_UID 0x4BU ///< read unique chip 64-bit ID
+#define W25Q_READ_JEDEC_ID 0x9FU ///< read JEDEC-standard ID
+#define W25Q_READ_SFDP 0x5AU ///< read SFDP register parameters
+#define W25Q_ERASE_SECURITY_REG 0x44U ///< erase security registers
+#define W25Q_PROG_SECURITY_REG 0x42U ///< program security registers
+#define W25Q_READ_SECURITY_REG 0x48U ///< read security registers
+#define W25Q_IND_BLOCK_LOCK 0x36U ///< make block/sector read-only
+#define W25Q_IND_BLOCK_UNLOCK 0x39U ///< disable block/sector protection
+#define W25Q_READ_BLOCK_LOCK 0x3DU ///< check block/sector protection
+#define W25Q_GLOBAL_LOCK 0x7EU ///< global read-only protection enable
+#define W25Q_GLOBAL_UNLOCK 0x98U ///< global read-only protection disable
+#define W25Q_ENABLE_RST 0x66U ///< enable software-reset ability
+#define W25Q_RESET 0x99U ///< make software reset
+/// @}
+
+/// @}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* W25Q_QSPI_W25Q_MEM_H_ */
diff --git a/firmware/rf test/Core/Src/fonts.c b/firmware/rf test/Core/Src/fonts.c
new file mode 100644
index 0000000..35ff8e4
--- /dev/null
+++ b/firmware/rf test/Core/Src/fonts.c
@@ -0,0 +1,22 @@
+#include "fonts.h"
+
+uint8_t jetbrains_mono_quarter_fb[1598] = {255,255,255,231,231,215,215,219,219,131,189,189,61,255,255,255,255,255,255,255,193,189,189,189,193,157,189,189,189,193,255,255,255,255,255,255,255,195,187,189,253,253,253,253,189,187,195,255,255,255,255,255,255,255,193,157,189,189,189,189,189,189,157,193,255,255,255,255,255,255,255,129,249,249,249,129,249,249,249,249,129,255,255,255,255,255,255,255,129,253,253,253,129,249,249,249,249,249,255,255,255,255,255,255,255,195,187,253,253,141,189,189,189,187,195,255,255,255,255,255,255,255,189,189,189,189,129,189,189,189,189,189,255,255,255,255,255,255,255,131,239,239,239,239,239,239,239,239,131,255,255,255,255,255,255,255,191,191,191,191,191,191,191,189,157,195,255,255,255,255,255,255,255,61,189,221,205,225,205,221,157,189,61,255,255,255,255,255,255,255,251,251,251,251,251,251,251,251,251,3,255,255,255,255,255,255,255,185,153,149,165,165,173,189,189,189,189,255,255,255,255,255,255,255,185,185,181,181,173,173,173,157,157,157,255,255,255,255,255,255,255,195,187,189,189,189,189,189,189,187,195,255,255,255,255,255,255,255,193,189,61,61,189,129,253,253,253,253,255,255,255,255,255,255,255,195,185,189,189,189,189,189,189,185,195,223,159,191,255,255,255,255,193,189,189,189,193,205,221,221,189,61,255,255,255,255,255,255,255,195,187,189,249,227,159,191,189,185,195,255,255,255,255,255,255,255,1,239,239,239,239,239,239,239,239,239,255,255,255,255,255,255,255,189,189,189,189,189,189,189,189,187,195,255,255,255,255,255,255,255,61,189,185,187,219,219,215,215,231,231,255,255,255,255,255,255,255,110,101,101,101,85,149,149,153,153,155,255,255,255,255,255,255,255,61,187,219,215,231,231,215,219,185,61,255,255,255,255,255,255,255,61,189,155,219,215,231,239,239,239,239,255,255,255,255,255,255,255,129,191,223,207,239,247,247,251,249,129,255,255,255,255,255,255,255,255,255,195,185,191,131,185,189,153,163,255,255,255,255,255,255,255,253,253,197,185,189,189,189,189,185,197,255,255,255,255,255,255,255,255,255,195,187,189,253,253,189,187,195,255,255,255,255,255,255,255,191,191,163,155,189,189,189,189,155,163,255,255,255,255,255,255,255,255,255,195,187,189,129,253,253,187,195,255,255,255,255,255,255,255,143,247,247,129,247,247,247,247,247,247,255,255,255,255,255,255,255,255,255,163,155,189,189,189,189,155,163,191,191,195,255,255,255,255,253,253,197,153,185,189,189,189,189,189,255,255,255,255,255,255,207,207,255,227,239,239,239,239,239,239,1,255,255,255,255,255,255,159,159,255,193,223,223,223,223,223,223,223,223,207,225,255,255,255,255,249,249,57,153,217,225,201,217,185,57,255,255,255,255,255,255,255,240,247,247,247,247,247,247,247,247,15,255,255,255,255,255,255,255,255,255,145,173,45,45,45,45,45,45,255,255,255,255,255,255,255,255,255,197,153,185,189,189,189,189,189,255,255,255,255,255,255,255,255,255,195,187,189,189,189,189,187,195,255,255,255,255,255,255,255,255,255,197,185,189,189,189,189,185,197,253,253,253,255,255,255,255,255,255,163,155,189,189,189,189,155,163,191,191,191,255,255,255,255,255,255,195,187,187,187,251,251,251,251,255,255,255,255,255,255,255,255,255,195,185,253,227,159,191,185,195,255,255,255,255,255,255,255,247,247,129,247,247,247,247,247,247,143,255,255,255,255,255,255,255,255,255,189,189,189,189,189,189,155,195,255,255,255,255,255,255,255,255,255,61,185,187,219,219,215,231,231,255,255,255,255,255,255,255,255,255,108,101,101,165,149,149,153,155,255,255,255,255,255,255,255,255,255,185,219,215,231,231,211,155,61,255,255,255,255,255,255,255,255,255,61,185,187,219,211,215,231,239,231,247,247,255,255,255,255,255,255,129,159,223,239,247,243,251,129,255,255,255,255,255,255,255,231,235,237,239,239,239,239,239,239,1,255,255,255,255,255,255,255,195,185,189,191,191,223,239,247,251,129,255,255,255,255,255,255,255,129,223,239,199,159,191,191,189,153,195,255,255,255,255,255,255,255,223,239,231,247,187,185,189,129,191,191,255,255,255,255,255,255,255,129,253,249,193,159,191,191,189,153,195,255,255,255,255,255,255,255,207,247,247,195,187,189,189,189,185,195,255,255,255,255,255,255,255,1,189,189,159,223,223,239,239,231,247,255,255,255,255,255,255,255,195,185,189,187,199,153,189,189,185,195,255,255,255,255,255,255,255,195,185,189,189,185,131,223,207,239,247,255,255,255,255,255,255,255,195,185,189,189,165,189,189,189,185,195,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,231,231,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,239,231,231,247,255,255,255,255,239,239,239,239,239,239,239,255,255,231,255,255,255,255,255,255,255,195,185,125,77,45,117,117,117,109,141,253,249,199,255,239,239,199,139,173,233,235,195,143,175,173,173,195,239,239,255,255,255,255,255,113,182,214,209,239,23,103,107,109,28,255,255,255,255,255,255,239,231,215,219,187,189,255,255,255,255,255,255,255,255,255,255,255,255,195,219,187,251,241,109,156,156,141,97,255,255,255,255,255,191,207,231,247,247,247,247,246,247,247,247,238,207,191,255,255,255,251,243,239,239,223,223,223,223,223,207,239,239,243,251,255,255,255,159,239,239,239,239,239,241,239,239,239,239,239,143,255,255,255,255,241,231,247,247,247,247,143,247,247,247,247,231,241,255,255,255,255,199,247,247,247,247,247,247,247,247,247,247,247,199,255,255,255,255,227,239,239,239,239,239,239,239,239,239,239,239,227,255,255,255,255,255,255,239,239,239,239,255,255,255,255,255,255,255,255,255,255,255,255,255,215,215,215,215,255,255,255,255,255,255,255,255,255,255,255,255,255,195,159,191,159,199,247,247,255,255,231,255,255,255,255,255,255,255,255,127,63,207,243,251,231,143,63,255,255,255,255,255,255,255,255,255,255,252,243,207,223,231,241,252,255,255,255,255,255,255,255,255,255,255,231,231,255,255,255,255,231,231,255,255,255,255,255,255,255,255,255,231,231,255,255,255,255,255,239,231,247,247,255,255,253,249,251,251,247,247,231,239,239,207,223,223,191,191,255,255,255,191,191,159,223,223,239,239,239,247,247,243,251,251,253,255,255,255,255,255,255,255,255,255,255,195,255,255,255,255,255,255,255,255,255,255,255,255,255,239,239,239,129,239,239,239,255,255,255,255,255,255,255,255,255,255,255,129,255,255,129,255,255,255,255,255,255,255,255,255,255,255,255,255,179,173,141,255,255,255,255,255,255,255,255,255,255,255,199,219,219,199,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,1,255,255,255,255,255,255,255,239,239,45,131,231,211,155,255,255,255,255,255,255,255,239,239,239,239,239,239,239,239,239,239,239,239,239,239,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255};
+uint8_t jetbrains_mono_quarter_lu[128] = {93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,64,77,93,66,67,69,76,70,71,91,86,63,85,62,84,61,52,53,54,55,56,57,58,59,60,81,82,79,87,80,78,65,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,74,83,75,68,90,89,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,72,92,73,88,93};
+
+
+bitmap_font_t** fonts;
+bitmap_font_t jetbrains_mono_quarter;
+
+void set_up_fonts() {
+ fonts = malloc(sizeof(bitmap_font_t *)*NUMBER_OF_FONTS);
+ fonts[0] = &jetbrains_mono_quarter;
+
+ jetbrains_mono_quarter.char_w = 8;
+ jetbrains_mono_quarter.char_h = 17;
+ jetbrains_mono_quarter.bytes_per_row = 1;
+ jetbrains_mono_quarter.bytes_per_char = 17;
+ jetbrains_mono_quarter.font_bytes = malloc(sizeof(uint8_t)*1598);
+ jetbrains_mono_quarter.lookup = malloc(sizeof(uint8_t)*128);
+ memcpy(jetbrains_mono_quarter.font_bytes, jetbrains_mono_quarter_fb, 1598);
+ memcpy(jetbrains_mono_quarter.lookup, jetbrains_mono_quarter_lu, 128);
+}
diff --git a/firmware/rf test/Core/Src/lis2dw12.c b/firmware/rf test/Core/Src/lis2dw12.c
new file mode 100644
index 0000000..15a8df4
--- /dev/null
+++ b/firmware/rf test/Core/Src/lis2dw12.c
@@ -0,0 +1,8 @@
+/*
+ * lis2dw12.c
+ *
+ * Created on: Dec 30, 2025
+ * Author: Anson Bridges
+ */
+#include "lis2dw12.h"
+
diff --git a/firmware/rf test/Core/Src/main.c b/firmware/rf test/Core/Src/main.c
new file mode 100644
index 0000000..6f4ae4e
--- /dev/null
+++ b/firmware/rf test/Core/Src/main.c
@@ -0,0 +1,612 @@
+/* USER CODE BEGIN Header */
+/**
+ ******************************************************************************
+ * @file : main.c
+ * @brief : Main program body
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2025 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+/* USER CODE END Header */
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+#include "sharpmem.h"
+//#include "w25q_mem.h"
+#include <stdio.h>
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+/* USER CODE BEGIN PTD */
+
+/* USER CODE END PTD */
+
+/* Private define ------------------------------------------------------------*/
+/* USER CODE BEGIN PD */
+uint8_t testimg[1360] = {255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,7,192,1,252,240,0,248,31,248,199,3,0,0,7,112,224,143,223,255,255,7,192,1,60,192,0,248,31,224,199,3,0,0,7,112,128,143,223,255,255,255,254,253,159,255,223,255,223,231,215,127,255,251,247,127,191,47,223,255,255,255,254,253,223,255,223,255,223,207,155,127,255,251,247,127,63,111,223,255,255,255,254,253,223,255,223,255,223,207,187,127,255,251,247,127,191,111,222,255,255,255,254,1,156,255,223,255,223,239,187,127,255,251,7,112,159,239,222,255,255,255,254,1,60,248,223,255,223,231,125,127,255,251,7,112,192,239,220,255,255,255,254,253,255,225,223,255,31,240,125,127,255,251,247,127,224,239,221,255,255,255,254,253,255,207,223,255,31,252,0,127,255,251,247,127,207,239,219,255,255,255,254,253,255,159,223,255,223,255,0,126,255,251,247,127,223,239,219,255,255,255,254,253,255,159,223,255,223,255,254,126,255,251,247,127,191,239,215,255,255,255,254,253,255,207,223,255,223,127,254,124,255,251,247,127,63,239,199,255,255,255,254,1,28,224,223,255,223,127,255,125,255,251,7,112,127,238,207,255,255,255,254,1,124,248,223,255,223,127,255,125,255,251,7,112,255,236,207,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,31,255,255,255,255,249,255,255,255,255,255,63,255,255,255,255,255,255,255,255,207,255,255,255,255,249,255,255,255,255,255,63,255,255,255,255,255,255,255,255,231,255,255,255,243,249,255,255,255,255,255,255,255,63,255,255,255,255,255,255,231,255,255,255,243,249,255,255,255,255,255,255,255,63,255,255,255,255,255,255,131,143,159,249,129,153,63,252,63,124,56,51,103,30,248,255,255,255,255,255,231,115,30,248,243,57,206,249,207,31,55,48,231,56,255,255,255,255,255,255,231,243,156,255,243,121,206,243,199,159,63,63,231,57,255,255,255,255,255,255,231,241,156,255,243,121,6,240,135,143,63,63,231,57,255,255,255,255,255,255,231,241,156,255,243,121,198,255,15,140,63,63,231,57,255,255,255,255,255,255,231,241,156,255,243,121,198,255,127,136,63,63,231,57,255,255,255,255,255,255,231,243,156,255,243,121,206,255,255,153,63,63,231,57,255,255,255,255,255,255,231,115,158,255,227,121,142,247,247,28,55,63,231,60,254,255,255,255,255,255,231,143,159,255,143,121,62,248,15,127,56,63,39,254,248,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,231,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,231,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,231,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255};
+SharpMemDisplay_t lcd;
+RTC_TimeTypeDef sTime;
+RTC_AlarmTypeDef sAlarm;
+RTC_DateTypeDef sDate;
+/* USER CODE END PD */
+
+/* Private macro -------------------------------------------------------------*/
+/* USER CODE BEGIN PM */
+int _write(int file, char *ptr, int len) {
+ int i = 0;
+ for(i = 0; i < len; i++)
+ ITM_SendChar((*ptr++));
+ return len;
+}
+/* USER CODE END PM */
+
+/* Private variables ---------------------------------------------------------*/
+I2C_HandleTypeDef hi2c1;
+
+IPCC_HandleTypeDef hipcc;
+
+RTC_HandleTypeDef hrtc;
+
+SPI_HandleTypeDef hspi1;
+
+/* USER CODE BEGIN PV */
+
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+void SystemClock_Config(void);
+void PeriphCommonClock_Config(void);
+static void MX_GPIO_Init(void);
+static void MX_RTC_Init(void);
+static void MX_SPI1_Init(void);
+static void MX_I2C1_Init(void);
+static void MX_IPCC_Init(void);
+static void MX_RF_Init(void);
+/* USER CODE BEGIN PFP */
+
+/* USER CODE END PFP */
+
+/* Private user code ---------------------------------------------------------*/
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/**
+ * @brief The application entry point.
+ * @retval int
+ */
+int main(void)
+{
+
+ /* USER CODE BEGIN 1 */
+
+ /* USER CODE END 1 */
+
+ /* MCU Configuration--------------------------------------------------------*/
+
+ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
+ HAL_Init();
+
+ /* USER CODE BEGIN Init */
+
+ /* USER CODE END Init */
+
+ /* Configure the system clock */
+ SystemClock_Config();
+
+ /* Configure the peripherals common clocks */
+ PeriphCommonClock_Config();
+
+ /* IPCC initialisation */
+ MX_IPCC_Init();
+
+ /* USER CODE BEGIN SysInit */
+
+ /* USER CODE END SysInit */
+
+ /* Initialize all configured peripherals */
+ MX_GPIO_Init();
+ MX_RTC_Init();
+ MX_SPI1_Init();
+ MX_I2C1_Init();
+ MX_RF_Init();
+ /* USER CODE BEGIN 2 */
+ set_up_fonts();
+ SharpMem_Init();
+ uint8_t started = 0;
+ //SHARPMEM_write(&lcd, "Boot", 0, 0,0, true, false);
+ //SHARPMEM_refresh_display(&lcd);
+
+ HAL_Delay(5000);
+ /* USER CODE END 2 */
+
+ /* Infinite loop */
+ /* USER CODE BEGIN WHILE */
+
+
+
+ while (1)
+ {
+ /* USER CODE END WHILE */
+
+ /* USER CODE BEGIN 3 */
+ if (!started){
+ // disable pullup resistors causing current draw
+ /*GPIO_InitTypeDef GPIO_InitStruct = {0};
+
+ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);*/
+
+ started = 1;
+ }
+ HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
+ HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
+ char timestr[15];
+ sprintf(timestr, "%i:%i:%i", sTime.Hours, sTime.Minutes, sTime.Seconds);
+ started++;
+
+ SHARPMEM_clear_display_buffer(&lcd);
+ SHARPMEM_write(&lcd, timestr, 0, 30, 20, true, false);
+ SHARPMEM_refresh_display(&lcd);
+ //HAL_Delay(900);
+
+ HAL_SuspendTick();
+
+ __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
+ HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
+ HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
+ __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
+ SystemClock_Config();
+ HAL_ResumeTick();
+
+ /*HAL_SuspendTick();
+ __HAL_RTC_ALARM_CLEAR_FLAG(&hrtc, RTC_FLAG_ALRAF);
+ __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
+ HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
+ //Custom_STM_App_Update_Char(0, (uint8_t *)(12));
+
+ sAlarm.AlarmTime.Seconds = (sTime.Seconds+10) % 60;
+ sAlarm.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM;
+ sAlarm.AlarmDateWeekDay = RTC_WEEKDAY_FRIDAY;
+ sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY | RTC_ALARMMASK_HOURS;
+ sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
+ sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
+ sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
+ sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
+ sAlarm.Alarm = RTC_ALARM_A;
+ if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+ if( (LL_PWR_IsActiveFlag_C1SB() == 0)
+ || (LL_PWR_IsActiveFlag_C2SB() == 0)
+ )
+ {
+ LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
+ }
+
+ HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
+ HAL_ResumeTick();
+
+ SystemClock_Config();*/
+
+ //SHARPMEM_write(&lcd, "TEST PROGRAM", 0, 0,0, true, false);
+
+ //printf("lcd params: %d, %d\n", i % lcd.width, i / lcd.width);
+ //memcpy(lcd._buffer, testimg, 1360);
+
+ //SHARPMEM_clear_display(&lcd);
+
+ }
+ /* USER CODE END 3 */
+}
+
+/**
+ * @brief System Clock Configuration
+ * @retval None
+ */
+void SystemClock_Config(void)
+{
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
+
+ /** Configure LSE Drive Capability
+ */
+ HAL_PWR_EnableBkUpAccess();
+ __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_MEDIUMHIGH);
+
+ /** Configure the main internal regulator output voltage
+ */
+ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
+
+ /** Initializes the RCC Oscillators according to the specified parameters
+ * in the RCC_OscInitTypeDef structure.
+ */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE
+ |RCC_OSCILLATORTYPE_LSE;
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+ RCC_OscInitStruct.LSEState = RCC_LSE_ON;
+ RCC_OscInitStruct.HSIState = RCC_HSI_ON;
+ RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
+ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+ /** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
+ */
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4|RCC_CLOCKTYPE_HCLK2
+ |RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
+ |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV16;
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+ RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
+
+ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+}
+
+/**
+ * @brief Peripherals Common Clock Configuration
+ * @retval None
+ */
+void PeriphCommonClock_Config(void)
+{
+ RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
+
+ /** Initializes the peripherals clock
+ */
+ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS|RCC_PERIPHCLK_RFWAKEUP;
+ PeriphClkInitStruct.RFWakeUpClockSelection = RCC_RFWKPCLKSOURCE_LSE;
+ PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSE;
+ PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE1;
+
+ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN Smps */
+
+ /* USER CODE END Smps */
+}
+
+/**
+ * @brief I2C1 Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_I2C1_Init(void)
+{
+
+ /* USER CODE BEGIN I2C1_Init 0 */
+
+ /* USER CODE END I2C1_Init 0 */
+
+ /* USER CODE BEGIN I2C1_Init 1 */
+
+ /* USER CODE END I2C1_Init 1 */
+ hi2c1.Instance = I2C1;
+ hi2c1.Init.Timing = 0x00000508;
+ hi2c1.Init.OwnAddress1 = 0;
+ hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
+ hi2c1.Init.OwnAddress2 = 0;
+ hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
+ hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
+ hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
+ if (HAL_I2C_Init(&hi2c1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+ /** Configure Analogue filter
+ */
+ if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+ /** Configure Digital filter
+ */
+ if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN I2C1_Init 2 */
+
+ /* USER CODE END I2C1_Init 2 */
+
+}
+
+/**
+ * @brief IPCC Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_IPCC_Init(void)
+{
+
+ /* USER CODE BEGIN IPCC_Init 0 */
+
+ /* USER CODE END IPCC_Init 0 */
+
+ /* USER CODE BEGIN IPCC_Init 1 */
+
+ /* USER CODE END IPCC_Init 1 */
+ hipcc.Instance = IPCC;
+ if (HAL_IPCC_Init(&hipcc) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN IPCC_Init 2 */
+
+ /* USER CODE END IPCC_Init 2 */
+
+}
+
+/**
+ * @brief RF Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_RF_Init(void)
+{
+
+ /* USER CODE BEGIN RF_Init 0 */
+
+ /* USER CODE END RF_Init 0 */
+
+ /* USER CODE BEGIN RF_Init 1 */
+
+ /* USER CODE END RF_Init 1 */
+ /* USER CODE BEGIN RF_Init 2 */
+
+ /* USER CODE END RF_Init 2 */
+
+}
+
+/**
+ * @brief RTC Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_RTC_Init(void)
+{
+
+ /* USER CODE BEGIN RTC_Init 0 */
+
+ /* USER CODE END RTC_Init 0 */
+
+ RTC_TimeTypeDef sTime = {0};
+ RTC_DateTypeDef sDate = {0};
+
+ /* USER CODE BEGIN RTC_Init 1 */
+
+ /* USER CODE END RTC_Init 1 */
+
+ /** Initialize RTC Only
+ */
+ hrtc.Instance = RTC;
+ hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
+ hrtc.Init.AsynchPrediv = 127;
+ hrtc.Init.SynchPrediv = 255;
+ hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
+ hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
+ hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
+ hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
+ if (HAL_RTC_Init(&hrtc) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+ /* USER CODE BEGIN Check_RTC_BKUP */
+
+ /* USER CODE END Check_RTC_BKUP */
+
+ /** Initialize RTC and set the Time and Date
+ */
+ sTime.Hours = 12;
+ sTime.Minutes = 50;
+ sTime.Seconds = 30;
+ sTime.SubSeconds = 0x0;
+ sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
+ sTime.StoreOperation = RTC_STOREOPERATION_RESET;
+ if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ sDate.WeekDay = RTC_WEEKDAY_MONDAY;
+ sDate.Month = RTC_MONTH_JANUARY;
+ sDate.Date = 1;
+ sDate.Year = 0;
+
+ if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+ /** Enable the WakeUp
+ */
+ if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN RTC_Init 2 */
+
+ /* USER CODE END RTC_Init 2 */
+
+}
+
+/**
+ * @brief SPI1 Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_SPI1_Init(void)
+{
+
+ /* USER CODE BEGIN SPI1_Init 0 */
+
+ /* USER CODE END SPI1_Init 0 */
+
+ /* USER CODE BEGIN SPI1_Init 1 */
+
+ /* USER CODE END SPI1_Init 1 */
+ /* SPI1 parameter configuration*/
+ hspi1.Instance = SPI1;
+ hspi1.Init.Mode = SPI_MODE_MASTER;
+ hspi1.Init.Direction = SPI_DIRECTION_2LINES;
+ hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
+ hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
+ hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
+ hspi1.Init.NSS = SPI_NSS_SOFT;
+ hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
+ hspi1.Init.FirstBit = SPI_FIRSTBIT_LSB;
+ hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
+ hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ hspi1.Init.CRCPolynomial = 7;
+ hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
+ hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
+ if (HAL_SPI_Init(&hspi1) != HAL_OK)
+ {
+ Error_Handler();
+ }
+ /* USER CODE BEGIN SPI1_Init 2 */
+
+ /* USER CODE END SPI1_Init 2 */
+
+}
+
+/**
+ * @brief GPIO Initialization Function
+ * @param None
+ * @retval None
+ */
+static void MX_GPIO_Init(void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ /* USER CODE BEGIN MX_GPIO_Init_1 */
+
+ /* USER CODE END MX_GPIO_Init_1 */
+
+ /* GPIO Ports Clock Enable */
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+
+ /*Configure GPIO pin Output Level */
+ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4|GPIO_PIN_6, GPIO_PIN_RESET);
+
+ /*Configure GPIO pin Output Level */
+ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
+
+ /*Configure GPIO pin Output Level */
+ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4|GPIO_PIN_5, GPIO_PIN_SET);
+
+ /*Configure GPIO pin : PA0 */
+ GPIO_InitStruct.Pin = GPIO_PIN_0;
+ GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ /*Configure GPIO pins : PA4 PA6 PA10 */
+ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_10;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ /*Configure GPIO pins : PA8 PA11 PA15 */
+ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_11|GPIO_PIN_15;
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ /*Configure GPIO pin : PB0 */
+ GPIO_InitStruct.Pin = GPIO_PIN_0;
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+ /*Configure GPIO pins : PB4 PB5 */
+ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+ /* USER CODE BEGIN MX_GPIO_Init_2 */
+
+ /* USER CODE END MX_GPIO_Init_2 */
+}
+
+/* USER CODE BEGIN 4 */
+
+void SharpMem_Init() {
+ lcd.width = 160;
+ lcd.height = 68;
+ lcd.spidev = &hspi1;
+ lcd.cs_pin_bank = GPIOA;
+ lcd.cs_pin = GPIO_PIN_4;
+ lcd.lcdmode_pin_bank = GPIOA;
+ lcd.lcdmode_pin = GPIO_PIN_6;
+
+ lcd._sharpmem_vcom = SHARPMEM_BIT_VCOM;
+ lcd._buffer = malloc(sizeof(uint8_t)*(lcd.width * lcd.height / 8));
+ SHARPMEM_clear_display(&lcd);
+}
+
+/* USER CODE END 4 */
+
+/**
+ * @brief This function is executed in case of error occurrence.
+ * @retval None
+ */
+void Error_Handler(void)
+{
+ /* USER CODE BEGIN Error_Handler_Debug */
+ /* User can add his own implementation to report the HAL error return state */
+ __disable_irq();
+ while (1)
+ {
+ }
+ /* USER CODE END Error_Handler_Debug */
+}
+#ifdef USE_FULL_ASSERT
+/**
+ * @brief Reports the name of the source file and the source line number
+ * where the assert_param error has occurred.
+ * @param file: pointer to the source file name
+ * @param line: assert_param error line source number
+ * @retval None
+ */
+void assert_failed(uint8_t *file, uint32_t line)
+{
+ /* USER CODE BEGIN 6 */
+ /* User can add his own implementation to report the file name and line number,
+ ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
+ /* USER CODE END 6 */
+}
+#endif /* USE_FULL_ASSERT */
diff --git a/firmware/rf test/Core/Src/sharpmem.c b/firmware/rf test/Core/Src/sharpmem.c
new file mode 100644
index 0000000..0117921
--- /dev/null
+++ b/firmware/rf test/Core/Src/sharpmem.c
@@ -0,0 +1,160 @@
+#include "sharpmem.h"
+#include "fonts.h"
+
+void SHARPMEM_TOGGLEVCOM(SharpMemDisplay_t *display) {
+ display->_sharpmem_vcom = display->_sharpmem_vcom ? 0x00 : SHARPMEM_BIT_VCOM;
+}
+
+void SHARPMEM_draw_pixel(SharpMemDisplay_t *display, uint16_t x, uint16_t y, bool black) {
+ if ((x >= display->width) || (y >= display->height))
+ return;
+
+ if (black) {
+ display->_buffer[(y * display->width + x) / 8] |= (0x1 << (x & 7)); //potentially expensive when run many times, use lookup from adafruit lib
+ } else {
+ display->_buffer[(y * display->width + x) / 8] &= ~(0x1 << (x & 7));
+ }
+}
+
+void SHARPMEM_draw_line(SharpMemDisplay_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool black, uint8_t thickness) {
+
+}
+
+void SHARPMEM_draw_circle(SharpMemDisplay_t *display, uint16_t x, uint16_t y, uint8_t r, bool filled) {
+
+}
+
+void SHARPMEM_draw_rect(SharpMemDisplay_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool filled) {
+
+}
+
+void SHARPMEM_write(SharpMemDisplay_t *display, char *text, uint8_t font_index, uint16_t x0, uint16_t y0, bool inverse, bool force_bg) {
+ /*uint8_t mask = 0xFF;
+ uint8_t a1, a2, b;
+ if(font_index > NUMBER_OF_FONTS) return;
+ bitmap_font_t *font = fonts[font_index];
+
+ for (uint8_t ci = 0; ci < strlen(text); ci++){
+ uint16_t base_index = font->lookup[(uint8_t)text[ci]];
+ uint8_t offset = (x0 + (ci)*font->char_w) % 8;
+
+ for (uint8_t y = 0; y < font->char_h; y++) {
+ if(y+y0 > display->height) return;
+
+ uint8_t start_byte = (x0 + ci*font->char_w)/8 + (y0+y)*display->width/8;
+
+ if((x0 + ci*font->char_w % 8))
+ memcpy(display->_buffer + ((y+y0)*(display->width)/8) + x0/8 + ci*font->char_w/8 , font->font_bytes + base_index*font->bytes_per_char + y*font->bytes_per_row , font->bytes_per_row);
+ else {
+ uint8_t charbase = base_index*font->bytes_per_char + y*font->bytes_per_row;
+ bool single_ended_last_byte = (offset + font->char_w - 1) / 8 > (bytes_per_row-1);
+ uint8_t buffer_bytes = font->bytes_per_row + ( single_ended_last_byte ? 1 : 0 );
+ for(uint8_t b_i = 0; b_i < buffer_bytes; b_i++) {
+ b = display->_buffer[start_byte + b_i];
+ a2 = font->font_bytes[ charbase + b_i ] >> offset;
+ if(b_i == 0) {
+ b = ((mask >> offset) & a2) + ( (mask << (8-offset)) & b );
+ } else if (b_i != (buffer_bytes-1 + !single_ended_last_byte)) {
+ a1 = font->font_bytes[ charbase + b_i - 1 ] << (8-offset);
+ if (!single_ended_last_byte) {
+ uint8_t remainder = (offset + font->char_w) % 8;
+ b = ( (a1 + a2) & (mask << (8-remainder)) ) + ((mask >> remainder) & b);
+ }
+ else b = a1 + a2;
+ } else {
+ a1 = font->font_bytes[ charbase + b_i - 1 ] << (8-offset);
+ uint8_t remainder = (offset + font->char_w) % 8;
+ b = ((mask << (8-remainder)) & a1) + ( (mask >> remainder) & b );
+ }
+ display->_buffer[start_byte + b_i] = b;
+ }
+ start_byte += font->bytes_per_char;
+ end_byte += font->bytes_per_char;
+ }
+ }
+ }*/
+
+ // potentially inefficient but simplest algorithm involving reading and writing every single pixel
+ if(font_index > NUMBER_OF_FONTS) return;
+ bitmap_font_t *font = fonts[font_index];
+
+ for (uint8_t ci = 0; ci < strlen(text); ci++){
+ uint16_t base_index = font->lookup[(uint8_t)text[ci]];
+
+ for (uint16_t y = 0; y < font->char_h; y++) {
+ uint16_t charbase = base_index*font->bytes_per_char + y*font->bytes_per_row;
+ for (uint16_t x = 0; x < font->char_w; x++) {
+ bool white = ( (font->font_bytes[charbase + x/8] & (0x1 << (x%8)) ) == 0 );
+ if (!force_bg && white) continue;
+ if (inverse) white = !white;
+ SHARPMEM_draw_pixel(display, x0+ci*font->char_w+x, y0+y, !white);
+ }
+ }
+ }
+}
+
+uint8_t SHARPMEM_get_pixel(SharpMemDisplay_t *display, uint16_t x, uint16_t y) {
+ if ((x >= display->width) || (y >= display->height))
+ return 1; //1 = empty
+
+}
+
+void SHARPMEM_clear_display(SharpMemDisplay_t *display) {
+ HAL_GPIO_WritePin(display->lcdmode_pin_bank, display->lcdmode_pin, GPIO_PIN_RESET); // set lcdmode pin to low for manual vcom control
+
+ memset(display->_buffer, 0xff, (display->width * display->height) / 8);
+
+ // Send the clear screen command rather than doing a HW refresh (quicker)
+
+ uint8_t clear_data[2] = {(uint8_t)(display->_sharpmem_vcom | SHARPMEM_BIT_CLEAR),
+ 0x00};
+
+ HAL_GPIO_WritePin(display->cs_pin_bank, display->cs_pin, GPIO_PIN_SET);
+ HAL_SPI_Transmit(display->spidev, clear_data, 2, 16);
+ HAL_GPIO_WritePin(display->cs_pin_bank, display->cs_pin, GPIO_PIN_RESET);
+
+ SHARPMEM_TOGGLEVCOM(display);
+ HAL_GPIO_WritePin(display->lcdmode_pin_bank, display->lcdmode_pin, GPIO_PIN_SET); // set lcdmode pin to high for 1Hz external vcom signal
+}
+
+void SHARPMEM_refresh_display(SharpMemDisplay_t *display) {
+ HAL_GPIO_WritePin(display->lcdmode_pin_bank, display->lcdmode_pin, GPIO_PIN_RESET); // set lcdmode pin to low for manual vcom control
+ uint16_t i, currentline;
+
+ //spidev->beginTransaction();
+ // Send the write command
+ HAL_GPIO_WritePin(display->cs_pin_bank, display->cs_pin, GPIO_PIN_SET);
+ uint8_t write_data[1] = {0x00 | SHARPMEM_BIT_WRITECMD};
+ HAL_SPI_Transmit(display->spidev, write_data, 1, 100);
+ SHARPMEM_TOGGLEVCOM(display);
+
+ uint8_t bytes_per_line = display->width / 8;
+ uint16_t totalbytes = (display->width * display->height) / 8;
+
+ for (i = 0; i < totalbytes; i += bytes_per_line) {
+ uint8_t line[bytes_per_line + 2];
+
+ // Send address byte
+ currentline = ((i + 1) / (display->width / 8)) + 1;
+ line[0] = currentline;
+ // copy over this line
+ memcpy(line + 1, display->_buffer + i, bytes_per_line);
+ // Send end of line
+ line[bytes_per_line + 1] = 0x00;
+ // send it!
+ HAL_SPI_Transmit(display->spidev, line, bytes_per_line + 2, 16);
+ }
+
+ // Send another trailing 8 bits for the last line
+ HAL_SPI_Transmit(display->spidev, (0x00), 1, 100);
+ HAL_GPIO_WritePin(display->cs_pin_bank, display->cs_pin, GPIO_PIN_RESET);
+ HAL_GPIO_WritePin(display->lcdmode_pin_bank, display->lcdmode_pin, GPIO_PIN_SET); // set lcdmode pin to high for 1Hz external vcom signal
+}
+
+void SHARPMEM_clear_display_buffer(SharpMemDisplay_t *display) {
+ memset(display->_buffer, 0xff, (display->width * display->height) / 8);
+}
+
+uint8_t *SHARPMEM_get_buffer(SharpMemDisplay_t *display) {
+
+}
diff --git a/firmware/rf test/Core/Src/stm32wbxx_hal_msp.c b/firmware/rf test/Core/Src/stm32wbxx_hal_msp.c
new file mode 100644
index 0000000..cb3fa8a
--- /dev/null
+++ b/firmware/rf test/Core/Src/stm32wbxx_hal_msp.c
@@ -0,0 +1,348 @@
+/* USER CODE BEGIN Header */
+/**
+ ******************************************************************************
+ * @file stm32wbxx_hal_msp.c
+ * @brief This file provides code for the MSP Initialization
+ * and de-Initialization codes.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2025 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+/* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+/* USER CODE BEGIN TD */
+
+/* USER CODE END TD */
+
+/* Private define ------------------------------------------------------------*/
+/* USER CODE BEGIN Define */
+
+/* USER CODE END Define */
+
+/* Private macro -------------------------------------------------------------*/
+/* USER CODE BEGIN Macro */
+
+/* USER CODE END Macro */
+
+/* Private variables ---------------------------------------------------------*/
+/* USER CODE BEGIN PV */
+
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+/* USER CODE BEGIN PFP */
+
+/* USER CODE END PFP */
+
+/* External functions --------------------------------------------------------*/
+/* USER CODE BEGIN ExternalFunctions */
+
+/* USER CODE END ExternalFunctions */
+
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+/**
+ * Initializes the Global MSP.
+ */
+void HAL_MspInit(void)
+{
+
+ /* USER CODE BEGIN MspInit 0 */
+
+ /* USER CODE END MspInit 0 */
+
+ __HAL_RCC_HSEM_CLK_ENABLE();
+
+ /* System interrupt init*/
+
+ /* Peripheral interrupt init */
+ /* HSEM_IRQn interrupt configuration */
+ HAL_NVIC_SetPriority(HSEM_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(HSEM_IRQn);
+
+ /* USER CODE BEGIN MspInit 1 */
+
+ /* USER CODE END MspInit 1 */
+}
+
+/**
+ * @brief I2C MSP Initialization
+ * This function configures the hardware resources used in this example
+ * @param hi2c: I2C handle pointer
+ * @retval None
+ */
+void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
+{
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
+ if(hi2c->Instance==I2C1)
+ {
+ /* USER CODE BEGIN I2C1_MspInit 0 */
+
+ /* USER CODE END I2C1_MspInit 0 */
+
+ /** Initializes the peripherals clock
+ */
+ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
+ PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
+ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+ /**I2C1 GPIO Configuration
+ PB6 ------> I2C1_SCL
+ PB7 ------> I2C1_SDA
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+ /* Peripheral clock enable */
+ __HAL_RCC_I2C1_CLK_ENABLE();
+ /* USER CODE BEGIN I2C1_MspInit 1 */
+
+ /* USER CODE END I2C1_MspInit 1 */
+
+ }
+
+}
+
+/**
+ * @brief I2C MSP De-Initialization
+ * This function freeze the hardware resources used in this example
+ * @param hi2c: I2C handle pointer
+ * @retval None
+ */
+void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
+{
+ if(hi2c->Instance==I2C1)
+ {
+ /* USER CODE BEGIN I2C1_MspDeInit 0 */
+
+ /* USER CODE END I2C1_MspDeInit 0 */
+ /* Peripheral clock disable */
+ __HAL_RCC_I2C1_CLK_DISABLE();
+
+ /**I2C1 GPIO Configuration
+ PB6 ------> I2C1_SCL
+ PB7 ------> I2C1_SDA
+ */
+ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6);
+
+ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7);
+
+ /* USER CODE BEGIN I2C1_MspDeInit 1 */
+
+ /* USER CODE END I2C1_MspDeInit 1 */
+ }
+
+}
+
+/**
+ * @brief IPCC MSP Initialization
+ * This function configures the hardware resources used in this example
+ * @param hipcc: IPCC handle pointer
+ * @retval None
+ */
+void HAL_IPCC_MspInit(IPCC_HandleTypeDef* hipcc)
+{
+ if(hipcc->Instance==IPCC)
+ {
+ /* USER CODE BEGIN IPCC_MspInit 0 */
+
+ /* USER CODE END IPCC_MspInit 0 */
+ /* Peripheral clock enable */
+ __HAL_RCC_IPCC_CLK_ENABLE();
+ /* IPCC interrupt Init */
+ HAL_NVIC_SetPriority(IPCC_C1_RX_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(IPCC_C1_RX_IRQn);
+ HAL_NVIC_SetPriority(IPCC_C1_TX_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(IPCC_C1_TX_IRQn);
+ /* USER CODE BEGIN IPCC_MspInit 1 */
+
+ /* USER CODE END IPCC_MspInit 1 */
+
+ }
+
+}
+
+/**
+ * @brief IPCC MSP De-Initialization
+ * This function freeze the hardware resources used in this example
+ * @param hipcc: IPCC handle pointer
+ * @retval None
+ */
+void HAL_IPCC_MspDeInit(IPCC_HandleTypeDef* hipcc)
+{
+ if(hipcc->Instance==IPCC)
+ {
+ /* USER CODE BEGIN IPCC_MspDeInit 0 */
+
+ /* USER CODE END IPCC_MspDeInit 0 */
+ /* Peripheral clock disable */
+ __HAL_RCC_IPCC_CLK_DISABLE();
+
+ /* IPCC interrupt DeInit */
+ HAL_NVIC_DisableIRQ(IPCC_C1_RX_IRQn);
+ HAL_NVIC_DisableIRQ(IPCC_C1_TX_IRQn);
+ /* USER CODE BEGIN IPCC_MspDeInit 1 */
+
+ /* USER CODE END IPCC_MspDeInit 1 */
+ }
+
+}
+
+/**
+ * @brief RTC MSP Initialization
+ * This function configures the hardware resources used in this example
+ * @param hrtc: RTC handle pointer
+ * @retval None
+ */
+void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)
+{
+ RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
+ if(hrtc->Instance==RTC)
+ {
+ /* USER CODE BEGIN RTC_MspInit 0 */
+
+ /* USER CODE END RTC_MspInit 0 */
+
+ /** Initializes the peripherals clock
+ */
+ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
+ PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
+ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+ /* Peripheral clock enable */
+ __HAL_RCC_RTC_ENABLE();
+ __HAL_RCC_RTCAPB_CLK_ENABLE();
+ /* RTC interrupt Init */
+ HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
+ /* USER CODE BEGIN RTC_MspInit 1 */
+
+ /* USER CODE END RTC_MspInit 1 */
+
+ }
+
+}
+
+/**
+ * @brief RTC MSP De-Initialization
+ * This function freeze the hardware resources used in this example
+ * @param hrtc: RTC handle pointer
+ * @retval None
+ */
+void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc)
+{
+ if(hrtc->Instance==RTC)
+ {
+ /* USER CODE BEGIN RTC_MspDeInit 0 */
+
+ /* USER CODE END RTC_MspDeInit 0 */
+ /* Peripheral clock disable */
+ __HAL_RCC_RTC_DISABLE();
+ __HAL_RCC_RTCAPB_CLK_DISABLE();
+
+ /* RTC interrupt DeInit */
+ HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn);
+ /* USER CODE BEGIN RTC_MspDeInit 1 */
+
+ /* USER CODE END RTC_MspDeInit 1 */
+ }
+
+}
+
+/**
+ * @brief SPI MSP Initialization
+ * This function configures the hardware resources used in this example
+ * @param hspi: SPI handle pointer
+ * @retval None
+ */
+void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
+{
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ if(hspi->Instance==SPI1)
+ {
+ /* USER CODE BEGIN SPI1_MspInit 0 */
+
+ /* USER CODE END SPI1_MspInit 0 */
+ /* Peripheral clock enable */
+ __HAL_RCC_SPI1_CLK_ENABLE();
+
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ /**SPI1 GPIO Configuration
+ PA5 ------> SPI1_SCK
+ PA7 ------> SPI1_MOSI
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ /* USER CODE BEGIN SPI1_MspInit 1 */
+
+ /* USER CODE END SPI1_MspInit 1 */
+
+ }
+
+}
+
+/**
+ * @brief SPI MSP De-Initialization
+ * This function freeze the hardware resources used in this example
+ * @param hspi: SPI handle pointer
+ * @retval None
+ */
+void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
+{
+ if(hspi->Instance==SPI1)
+ {
+ /* USER CODE BEGIN SPI1_MspDeInit 0 */
+
+ /* USER CODE END SPI1_MspDeInit 0 */
+ /* Peripheral clock disable */
+ __HAL_RCC_SPI1_CLK_DISABLE();
+
+ /**SPI1 GPIO Configuration
+ PA5 ------> SPI1_SCK
+ PA7 ------> SPI1_MOSI
+ */
+ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_7);
+
+ /* USER CODE BEGIN SPI1_MspDeInit 1 */
+
+ /* USER CODE END SPI1_MspDeInit 1 */
+ }
+
+}
+
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
diff --git a/firmware/rf test/Core/Src/stm32wbxx_it.c b/firmware/rf test/Core/Src/stm32wbxx_it.c
new file mode 100644
index 0000000..2759953
--- /dev/null
+++ b/firmware/rf test/Core/Src/stm32wbxx_it.c
@@ -0,0 +1,260 @@
+/* USER CODE BEGIN Header */
+/**
+ ******************************************************************************
+ * @file stm32wbxx_it.c
+ * @brief Interrupt Service Routines.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2025 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+/* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+#include "stm32wbxx_it.h"
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+/* USER CODE BEGIN TD */
+
+/* USER CODE END TD */
+
+/* Private define ------------------------------------------------------------*/
+/* USER CODE BEGIN PD */
+
+/* USER CODE END PD */
+
+/* Private macro -------------------------------------------------------------*/
+/* USER CODE BEGIN PM */
+
+/* USER CODE END PM */
+
+/* Private variables ---------------------------------------------------------*/
+/* USER CODE BEGIN PV */
+
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+/* USER CODE BEGIN PFP */
+
+/* USER CODE END PFP */
+
+/* Private user code ---------------------------------------------------------*/
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/* External variables --------------------------------------------------------*/
+extern IPCC_HandleTypeDef hipcc;
+extern RTC_HandleTypeDef hrtc;
+/* USER CODE BEGIN EV */
+
+/* USER CODE END EV */
+
+/******************************************************************************/
+/* Cortex Processor Interruption and Exception Handlers */
+/******************************************************************************/
+/**
+ * @brief This function handles Non maskable interrupt.
+ */
+void NMI_Handler(void)
+{
+ /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
+
+ /* USER CODE END NonMaskableInt_IRQn 0 */
+ /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
+ while (1)
+ {
+ }
+ /* USER CODE END NonMaskableInt_IRQn 1 */
+}
+
+/**
+ * @brief This function handles Hard fault interrupt.
+ */
+void HardFault_Handler(void)
+{
+ /* USER CODE BEGIN HardFault_IRQn 0 */
+
+ /* USER CODE END HardFault_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_HardFault_IRQn 0 */
+ /* USER CODE END W1_HardFault_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles Memory management fault.
+ */
+void MemManage_Handler(void)
+{
+ /* USER CODE BEGIN MemoryManagement_IRQn 0 */
+
+ /* USER CODE END MemoryManagement_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
+ /* USER CODE END W1_MemoryManagement_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles Prefetch fault, memory access fault.
+ */
+void BusFault_Handler(void)
+{
+ /* USER CODE BEGIN BusFault_IRQn 0 */
+
+ /* USER CODE END BusFault_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_BusFault_IRQn 0 */
+ /* USER CODE END W1_BusFault_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles Undefined instruction or illegal state.
+ */
+void UsageFault_Handler(void)
+{
+ /* USER CODE BEGIN UsageFault_IRQn 0 */
+
+ /* USER CODE END UsageFault_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
+ /* USER CODE END W1_UsageFault_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles System service call via SWI instruction.
+ */
+void SVC_Handler(void)
+{
+ /* USER CODE BEGIN SVCall_IRQn 0 */
+
+ /* USER CODE END SVCall_IRQn 0 */
+ /* USER CODE BEGIN SVCall_IRQn 1 */
+
+ /* USER CODE END SVCall_IRQn 1 */
+}
+
+/**
+ * @brief This function handles Debug monitor.
+ */
+void DebugMon_Handler(void)
+{
+ /* USER CODE BEGIN DebugMonitor_IRQn 0 */
+
+ /* USER CODE END DebugMonitor_IRQn 0 */
+ /* USER CODE BEGIN DebugMonitor_IRQn 1 */
+
+ /* USER CODE END DebugMonitor_IRQn 1 */
+}
+
+/**
+ * @brief This function handles Pendable request for system service.
+ */
+void PendSV_Handler(void)
+{
+ /* USER CODE BEGIN PendSV_IRQn 0 */
+
+ /* USER CODE END PendSV_IRQn 0 */
+ /* USER CODE BEGIN PendSV_IRQn 1 */
+
+ /* USER CODE END PendSV_IRQn 1 */
+}
+
+/**
+ * @brief This function handles System tick timer.
+ */
+void SysTick_Handler(void)
+{
+ /* USER CODE BEGIN SysTick_IRQn 0 */
+
+ /* USER CODE END SysTick_IRQn 0 */
+ HAL_IncTick();
+ /* USER CODE BEGIN SysTick_IRQn 1 */
+
+ /* USER CODE END SysTick_IRQn 1 */
+}
+
+/******************************************************************************/
+/* STM32WBxx Peripheral Interrupt Handlers */
+/* Add here the Interrupt Handlers for the used peripherals. */
+/* For the available peripheral interrupt handler names, */
+/* please refer to the startup file (startup_stm32wbxx.s). */
+/******************************************************************************/
+
+/**
+ * @brief This function handles RTC wake-up interrupt through EXTI line 19.
+ */
+void RTC_WKUP_IRQHandler(void)
+{
+ /* USER CODE BEGIN RTC_WKUP_IRQn 0 */
+
+ /* USER CODE END RTC_WKUP_IRQn 0 */
+ HAL_RTCEx_WakeUpTimerIRQHandler(&hrtc);
+ /* USER CODE BEGIN RTC_WKUP_IRQn 1 */
+
+ /* USER CODE END RTC_WKUP_IRQn 1 */
+}
+
+/**
+ * @brief This function handles IPCC RX occupied interrupt.
+ */
+void IPCC_C1_RX_IRQHandler(void)
+{
+ /* USER CODE BEGIN IPCC_C1_RX_IRQn 0 */
+
+ /* USER CODE END IPCC_C1_RX_IRQn 0 */
+ HAL_IPCC_RX_IRQHandler(&hipcc);
+ /* USER CODE BEGIN IPCC_C1_RX_IRQn 1 */
+
+ /* USER CODE END IPCC_C1_RX_IRQn 1 */
+}
+
+/**
+ * @brief This function handles IPCC TX free interrupt.
+ */
+void IPCC_C1_TX_IRQHandler(void)
+{
+ /* USER CODE BEGIN IPCC_C1_TX_IRQn 0 */
+
+ /* USER CODE END IPCC_C1_TX_IRQn 0 */
+ HAL_IPCC_TX_IRQHandler(&hipcc);
+ /* USER CODE BEGIN IPCC_C1_TX_IRQn 1 */
+
+ /* USER CODE END IPCC_C1_TX_IRQn 1 */
+}
+
+/**
+ * @brief This function handles HSEM global interrupt.
+ */
+void HSEM_IRQHandler(void)
+{
+ /* USER CODE BEGIN HSEM_IRQn 0 */
+
+ /* USER CODE END HSEM_IRQn 0 */
+ HAL_HSEM_IRQHandler();
+ /* USER CODE BEGIN HSEM_IRQn 1 */
+
+ /* USER CODE END HSEM_IRQn 1 */
+}
+
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
diff --git a/firmware/rf test/Core/Src/syscalls.c b/firmware/rf test/Core/Src/syscalls.c
new file mode 100644
index 0000000..8884b5a
--- /dev/null
+++ b/firmware/rf test/Core/Src/syscalls.c
@@ -0,0 +1,176 @@
+/**
+ ******************************************************************************
+ * @file syscalls.c
+ * @author Auto-generated by STM32CubeIDE
+ * @brief STM32CubeIDE Minimal System calls file
+ *
+ * For more information about which c-functions
+ * need which of these lowlevel functions
+ * please consult the Newlib libc-manual
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2020-2025 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Includes */
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/times.h>
+
+
+/* Variables */
+extern int __io_putchar(int ch) __attribute__((weak));
+extern int __io_getchar(void) __attribute__((weak));
+
+
+char *__env[1] = { 0 };
+char **environ = __env;
+
+
+/* Functions */
+void initialise_monitor_handles()
+{
+}
+
+int _getpid(void)
+{
+ return 1;
+}
+
+int _kill(int pid, int sig)
+{
+ (void)pid;
+ (void)sig;
+ errno = EINVAL;
+ return -1;
+}
+
+void _exit (int status)
+{
+ _kill(status, -1);
+ while (1) {} /* Make sure we hang here */
+}
+
+__attribute__((weak)) int _read(int file, char *ptr, int len)
+{
+ (void)file;
+ int DataIdx;
+
+ for (DataIdx = 0; DataIdx < len; DataIdx++)
+ {
+ *ptr++ = __io_getchar();
+ }
+
+ return len;
+}
+
+__attribute__((weak)) int _write(int file, char *ptr, int len)
+{
+ (void)file;
+ int DataIdx;
+
+ for (DataIdx = 0; DataIdx < len; DataIdx++)
+ {
+ __io_putchar(*ptr++);
+ }
+ return len;
+}
+
+int _close(int file)
+{
+ (void)file;
+ return -1;
+}
+
+
+int _fstat(int file, struct stat *st)
+{
+ (void)file;
+ st->st_mode = S_IFCHR;
+ return 0;
+}
+
+int _isatty(int file)
+{
+ (void)file;
+ return 1;
+}
+
+int _lseek(int file, int ptr, int dir)
+{
+ (void)file;
+ (void)ptr;
+ (void)dir;
+ return 0;
+}
+
+int _open(char *path, int flags, ...)
+{
+ (void)path;
+ (void)flags;
+ /* Pretend like we always fail */
+ return -1;
+}
+
+int _wait(int *status)
+{
+ (void)status;
+ errno = ECHILD;
+ return -1;
+}
+
+int _unlink(char *name)
+{
+ (void)name;
+ errno = ENOENT;
+ return -1;
+}
+
+int _times(struct tms *buf)
+{
+ (void)buf;
+ return -1;
+}
+
+int _stat(char *file, struct stat *st)
+{
+ (void)file;
+ st->st_mode = S_IFCHR;
+ return 0;
+}
+
+int _link(char *old, char *new)
+{
+ (void)old;
+ (void)new;
+ errno = EMLINK;
+ return -1;
+}
+
+int _fork(void)
+{
+ errno = EAGAIN;
+ return -1;
+}
+
+int _execve(char *name, char **argv, char **env)
+{
+ (void)name;
+ (void)argv;
+ (void)env;
+ errno = ENOMEM;
+ return -1;
+}
diff --git a/firmware/rf test/Core/Src/sysmem.c b/firmware/rf test/Core/Src/sysmem.c
new file mode 100644
index 0000000..5d9f7e6
--- /dev/null
+++ b/firmware/rf test/Core/Src/sysmem.c
@@ -0,0 +1,79 @@
+/**
+ ******************************************************************************
+ * @file sysmem.c
+ * @author Generated by STM32CubeIDE
+ * @brief STM32CubeIDE System Memory calls file
+ *
+ * For more information about which C functions
+ * need which of these lowlevel functions
+ * please consult the newlib libc manual
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2025 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Includes */
+#include <errno.h>
+#include <stdint.h>
+
+/**
+ * Pointer to the current high watermark of the heap usage
+ */
+static uint8_t *__sbrk_heap_end = NULL;
+
+/**
+ * @brief _sbrk() allocates memory to the newlib heap and is used by malloc
+ * and others from the C library
+ *
+ * @verbatim
+ * ############################################################################
+ * # .data # .bss # newlib heap # MSP stack #
+ * # # # # Reserved by _Min_Stack_Size #
+ * ############################################################################
+ * ^-- RAM start ^-- _end _estack, RAM end --^
+ * @endverbatim
+ *
+ * This implementation starts allocating at the '_end' linker symbol
+ * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack
+ * The implementation considers '_estack' linker symbol to be RAM end
+ * NOTE: If the MSP stack, at any point during execution, grows larger than the
+ * reserved size, please increase the '_Min_Stack_Size'.
+ *
+ * @param incr Memory size
+ * @return Pointer to allocated memory
+ */
+void *_sbrk(ptrdiff_t incr)
+{
+ extern uint8_t _end; /* Symbol defined in the linker script */
+ extern uint8_t _estack; /* Symbol defined in the linker script */
+ extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */
+ const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;
+ const uint8_t *max_heap = (uint8_t *)stack_limit;
+ uint8_t *prev_heap_end;
+
+ /* Initialize heap end at first call */
+ if (NULL == __sbrk_heap_end)
+ {
+ __sbrk_heap_end = &_end;
+ }
+
+ /* Protect heap from growing into the reserved MSP stack */
+ if (__sbrk_heap_end + incr > max_heap)
+ {
+ errno = ENOMEM;
+ return (void *)-1;
+ }
+
+ prev_heap_end = __sbrk_heap_end;
+ __sbrk_heap_end += incr;
+
+ return (void *)prev_heap_end;
+}
diff --git a/firmware/rf test/Core/Src/system_stm32wbxx.c b/firmware/rf test/Core/Src/system_stm32wbxx.c
new file mode 100644
index 0000000..57f6a4e
--- /dev/null
+++ b/firmware/rf test/Core/Src/system_stm32wbxx.c
@@ -0,0 +1,378 @@
+/**
+ ******************************************************************************
+ * @file system_stm32wbxx.c
+ * @author MCD Application Team
+ * @brief CMSIS Cortex Device Peripheral Access Layer System Source File
+ *
+ * This file provides two functions and one global variable to be called from
+ * user application:
+ * - SystemInit(): This function is called at startup just after reset and
+ * before branch to main program. This call is made inside
+ * the "startup_stm32wbxx.s" file.
+ *
+ * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
+ * by the user application to setup the SysTick
+ * timer or configure other parameters.
+ *
+ * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
+ * be called whenever the core clock is changed
+ * during program execution.
+ *
+ * After each device reset the MSI (4 MHz) is used as system clock source.
+ * Then SystemInit() function is called, in "startup_stm32wbxx.s" file, to
+ * configure the system clock before to branch to main program.
+ *
+ * This file configures the system clock as follows:
+ *=============================================================================
+ *-----------------------------------------------------------------------------
+ * System Clock source | MSI
+ *-----------------------------------------------------------------------------
+ * SYSCLK(Hz) | 4000000
+ *-----------------------------------------------------------------------------
+ * HCLK(Hz) | 4000000
+ *-----------------------------------------------------------------------------
+ * AHB Prescaler | 1
+ *-----------------------------------------------------------------------------
+ * APB1 Prescaler | 1
+ *-----------------------------------------------------------------------------
+ * APB2 Prescaler | 1
+ *-----------------------------------------------------------------------------
+ * PLL_M | 1
+ *-----------------------------------------------------------------------------
+ * PLL_N | 8
+ *-----------------------------------------------------------------------------
+ * PLL_P | 7
+ *-----------------------------------------------------------------------------
+ * PLL_Q | 2
+ *-----------------------------------------------------------------------------
+ * PLL_R | 2
+ *-----------------------------------------------------------------------------
+ * PLLSAI1_P | NA
+ *-----------------------------------------------------------------------------
+ * PLLSAI1_Q | NA
+ *-----------------------------------------------------------------------------
+ * PLLSAI1_R | NA
+ *-----------------------------------------------------------------------------
+ * Require 48MHz for USB OTG FS, | Disabled
+ * SDIO and RNG clock |
+ *-----------------------------------------------------------------------------
+ *=============================================================================
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019-2021 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32WBxx_system
+ * @{
+ */
+
+/** @addtogroup stm32WBxx_System_Private_Includes
+ * @{
+ */
+
+#include "stm32wbxx.h"
+
+#if !defined (HSE_VALUE)
+#define HSE_VALUE (32000000UL) /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined (MSI_VALUE)
+#define MSI_VALUE (4000000UL) /*!< Value of the Internal oscillator in Hz*/
+#endif /* MSI_VALUE */
+
+#if !defined (HSI_VALUE)
+#define HSI_VALUE (16000000UL) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+#if !defined (LSI_VALUE)
+#define LSI_VALUE (32000UL) /*!< Value of LSI in Hz*/
+#endif /* LSI_VALUE */
+
+#if !defined (LSE_VALUE)
+#if defined(STM32WB5Mxx)
+ #define LSE_VALUE 32774U /*!< Value of the LSE oscillator in Hz */
+#else
+ #define LSE_VALUE 32768U /*!< Value of the LSE oscillator in Hz */
+#endif /* STM32WB5Mxx */
+#endif /* LSE_VALUE */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32WBxx_System_Private_TypesDefinitions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32WBxx_System_Private_Defines
+ * @{
+ */
+
+/* Note: Following vector table addresses must be defined in line with linker
+ configuration. */
+/*!< Uncomment the following line if you need to relocate CPU1 CM4 and/or CPU2
+ CM0+ vector table anywhere in Sram or Flash. Else vector table will be kept
+ at address 0x00 which correspond to automatic remap of boot address selected */
+/* #define USER_VECT_TAB_ADDRESS */
+#if defined(USER_VECT_TAB_ADDRESS)
+/*!< Uncomment this line for user vector table remap in Sram else user remap
+ will be done in Flash. */
+/* #define VECT_TAB_SRAM */
+#if defined(VECT_TAB_SRAM)
+#define VECT_TAB_BASE_ADDRESS SRAM1_BASE /*!< Vector Table base address field.
+ This value must be a multiple of 0x200. */
+#if !defined(VECT_TAB_OFFSET)
+#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table offset field.
+ This value must be a multiple of 0x200. */
+#endif /* VECT_TAB_OFFSET */
+
+#else
+#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
+ This value must be a multiple of 0x200. */
+#if !defined(VECT_TAB_OFFSET)
+#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table offset field.
+ This value must be a multiple of 0x200. */
+#endif /* VECT_TAB_OFFSET */
+
+#endif /* VECT_TAB_SRAM */
+#endif /* USER_VECT_TAB_ADDRESS */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32WBxx_System_Private_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32WBxx_System_Private_Variables
+ * @{
+ */
+/* The SystemCoreClock variable is updated in three ways:
+ 1) by calling CMSIS function SystemCoreClockUpdate()
+ 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
+ 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
+ Note: If you use this function to configure the system clock; then there
+ is no need to call the 2 first functions listed above, since SystemCoreClock
+ variable is updated automatically.
+*/
+uint32_t SystemCoreClock = 4000000UL ; /*CPU1: M4 on MSI clock after startup (4MHz)*/
+
+const uint32_t AHBPrescTable[16UL] = {1UL, 3UL, 5UL, 1UL, 1UL, 6UL, 10UL, 32UL, 2UL, 4UL, 8UL, 16UL, 64UL, 128UL, 256UL, 512UL};
+
+const uint32_t APBPrescTable[8UL] = {0UL, 0UL, 0UL, 0UL, 1UL, 2UL, 3UL, 4UL};
+
+const uint32_t MSIRangeTable[16UL] = {100000UL, 200000UL, 400000UL, 800000UL, 1000000UL, 2000000UL, \
+ 4000000UL, 8000000UL, 16000000UL, 24000000UL, 32000000UL, 48000000UL, 0UL, 0UL, 0UL, 0UL
+ }; /* 0UL values are incorrect cases */
+
+#if defined(STM32WB55xx) || defined(STM32WB5Mxx) || defined(STM32WB35xx) || defined (STM32WB15xx) || defined (STM32WB1Mxx)
+const uint32_t SmpsPrescalerTable[4UL][6UL] = {{1UL, 3UL, 2UL, 2UL, 1UL, 2UL}, \
+ {2UL, 6UL, 4UL, 3UL, 2UL, 4UL}, \
+ {4UL, 12UL, 8UL, 6UL, 4UL, 8UL}, \
+ {4UL, 12UL, 8UL, 6UL, 4UL, 8UL}
+};
+#endif /* STM32WB55xx || STM32WB5Mxx || STM32WB35xx || STM32WB15xx || STM32WB1Mxx */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32WBxx_System_Private_FunctionPrototypes
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32WBxx_System_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Setup the microcontroller system.
+ * @param None
+ * @retval None
+ */
+void SystemInit(void)
+{
+#if defined(USER_VECT_TAB_ADDRESS)
+ /* Configure the Vector Table location add offset address ------------------*/
+ SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET;
+#endif /* USER_VECT_TAB_ADDRESS */
+
+ /* FPU settings ------------------------------------------------------------*/
+#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+ SCB->CPACR |= ((3UL << (10UL * 2UL)) | (3UL << (11UL * 2UL))); /* set CP10 and CP11 Full Access */
+#endif /* FPU */
+
+ /* Reset the RCC clock configuration to the default reset state ------------*/
+ /* Set MSION bit */
+ RCC->CR |= RCC_CR_MSION;
+
+ /* Reset CFGR register */
+ RCC->CFGR = 0x00070000U;
+
+ /* Reset PLLSAI1ON, PLLON, HSECSSON, HSEON, HSION, and MSIPLLON bits */
+ RCC->CR &= (uint32_t)0xFAF6FEFBU;
+
+ /*!< Reset LSI1 and LSI2 bits */
+ RCC->CSR &= (uint32_t)0xFFFFFFFAU;
+
+ /*!< Reset HSI48ON bit */
+ RCC->CRRCR &= (uint32_t)0xFFFFFFFEU;
+
+ /* Reset PLLCFGR register */
+ RCC->PLLCFGR = 0x22041000U;
+
+#if defined(STM32WB55xx) || defined(STM32WB5Mxx)
+ /* Reset PLLSAI1CFGR register */
+ RCC->PLLSAI1CFGR = 0x22041000U;
+#endif /* STM32WB55xx || STM32WB5Mxx */
+
+ /* Reset HSEBYP bit */
+ RCC->CR &= 0xFFFBFFFFU;
+
+ /* Disable all interrupts */
+ RCC->CIER = 0x00000000;
+}
+
+/**
+ * @brief Update SystemCoreClock variable according to Clock Register Values.
+ * The SystemCoreClock variable contains the core clock (HCLK), it can
+ * be used by the user application to setup the SysTick timer or configure
+ * other parameters.
+ *
+ * @note Each time the core clock (HCLK) changes, this function must be called
+ * to update SystemCoreClock variable value. Otherwise, any configuration
+ * based on this variable will be incorrect.
+ *
+ * @note - The system frequency computed by this function is not the real
+ * frequency in the chip. It is calculated based on the predefined
+ * constant and the selected clock source:
+ *
+ * - If SYSCLK source is MSI, SystemCoreClock will contain the MSI_VALUE(*)
+ *
+ * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
+ *
+ * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
+ *
+ * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(***)
+ * or HSI_VALUE(*) or MSI_VALUE(*) multiplied/divided by the PLL factors.
+ *
+ * (*) MSI_VALUE is a constant defined in stm32wbxx_hal.h file (default value
+ * 4 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ *
+ * (**) HSI_VALUE is a constant defined in stm32wbxx_hal_conf.h file (default value
+ * 16 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ *
+ * (***) HSE_VALUE is a constant defined in stm32wbxx_hal_conf.h file (default value
+ * 32 MHz), user has to ensure that HSE_VALUE is same as the real
+ * frequency of the crystal used. Otherwise, this function may
+ * have wrong result.
+ *
+ * - The result of this function could be not correct when using fractional
+ * value for HSE crystal.
+ *
+ * @param None
+ * @retval None
+ */
+void SystemCoreClockUpdate(void)
+{
+ uint32_t tmp, msirange, pllvco, pllr, pllsource, pllm;
+
+ /* Get MSI Range frequency--------------------------------------------------*/
+
+ /*MSI frequency range in Hz*/
+ msirange = MSIRangeTable[(RCC->CR & RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos];
+
+ /* Get SYSCLK source -------------------------------------------------------*/
+ switch (RCC->CFGR & RCC_CFGR_SWS)
+ {
+ case 0x00: /* MSI used as system clock source */
+ SystemCoreClock = msirange;
+ break;
+
+ case 0x04: /* HSI used as system clock source */
+ /* HSI used as system clock source */
+ SystemCoreClock = HSI_VALUE;
+ break;
+
+ case 0x08: /* HSE used as system clock source */
+ SystemCoreClock = HSE_VALUE;
+ break;
+
+ case 0x0C: /* PLL used as system clock source */
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
+ SYSCLK = PLL_VCO / PLLR
+ */
+ pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
+ pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1UL ;
+
+ if (pllsource == 0x02UL) /* HSI used as PLL clock source */
+ {
+ pllvco = (HSI_VALUE / pllm);
+ }
+ else if (pllsource == 0x03UL) /* HSE used as PLL clock source */
+ {
+ pllvco = (HSE_VALUE / pllm);
+ }
+ else /* MSI used as PLL clock source */
+ {
+ pllvco = (msirange / pllm);
+ }
+
+ pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
+ pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1UL);
+
+ SystemCoreClock = pllvco / pllr;
+ break;
+
+ default:
+ SystemCoreClock = msirange;
+ break;
+ }
+
+ /* Compute HCLK clock frequency --------------------------------------------*/
+ /* Get HCLK1 prescaler */
+ tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
+
+ /* HCLK clock frequency */
+ SystemCoreClock = SystemCoreClock / tmp;
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/firmware/rf test/Core/Src/w25q_mem.rrr b/firmware/rf test/Core/Src/w25q_mem.rrr
new file mode 100644
index 0000000..5f2581b
--- /dev/null
+++ b/firmware/rf test/Core/Src/w25q_mem.rrr
@@ -0,0 +1,1521 @@
+/**
+ *******************************************
+ * @file w25q_mem.c
+ * @author Dmitriy Semenov / Crazy_Geeks
+ * @version 0.1b
+ * @date 12-August-2021
+ * @brief Source file for W25Qxxx lib
+ * @note https://github.com/Crazy-Geeks/STM32-W25Q-QSPI
+ *******************************************
+ *
+ * @note https://ru.mouser.com/datasheet/2/949/w25q256jv_spi_revg_08032017-1489574.pdf
+ * @note https://www.st.com/resource/en/application_note/DM00227538-.pdf
+ */
+
+/**
+ * @addtogroup W25Q_Driver
+ * @{
+ */
+
+#include "w25q_mem.h"
+
+/**
+ * @addtogroup W25Q_Exp Exported types
+ * @brief External fields and data
+ * @{
+ */
+extern QSPI_HandleTypeDef hqspi; ///< Quad SPI HAL Instance
+/// @}
+
+/**
+ * @addtogroup W25Q_PrivFi Private fields
+ * @brief Private variables and defines
+ * @{
+ */
+#define w25q_delay(x) HAL_Delay(x) ///< Delay define to provide future support of RTOS
+W25Q_STATUS_REG w25q_status; ///< Internal status structure instance
+
+/// @}
+
+/**
+ * @addtogroup W25Q_PrivFu Private Methods
+ * @brief Internal lib's functions
+ * @{
+ */
+W25Q_STATE W25Q_WriteEnable(bool enable); ///< Toggle WOL bit
+W25Q_STATE W25Q_EnableQSPI(bool enable); ///< Toggle QE bit
+W25Q_STATE W25Q_Enter4ByteMode(bool enable); ///< Toggle ADS bit
+W25Q_STATE W25Q_SetExtendedAddr(u8_t Addr); ///< Set addr in 3-byte mode
+W25Q_STATE W25Q_GetExtendedAddr(u8_t *outAddr); ///< Get addr in 3-byte mode
+
+static inline u32_t page_to_addr(u32_t pageNum, u8_t pageShift); ///< Translate page addr to byte addr
+/// @}
+
+/**
+ * @addtogroup W25Q_Pub Public methods
+ * @brief Public Methods
+ * @{
+ */
+
+/**
+ * @addtogroup W25Q_Init Init methods
+ * @brief Initalization
+ * @{
+ */
+
+/**
+ * @brief W25Q Init function
+ *
+ * @param none
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_Init(void) {
+ W25Q_STATE state; // temp status variable
+
+ // read id
+ u8_t id = 0;
+ state = W25Q_ReadID(&id);
+ if (state != W25Q_OK)
+ return state;
+ // u can check id here
+
+ // read chip's state to private lib's struct
+ state = W25Q_ReadStatusStruct(NULL);
+ if (state != W25Q_OK)
+ return state;
+
+#if MEM_FLASH_SIZE > 128 // if 4-byte mode
+
+ /* If power-default 4-byte
+ mode disabled */
+ if (!w25q_status.ADP) {
+ u8_t buf_reg = 0;
+ state = W25Q_ReadStatusReg(&buf_reg, 3);
+ if (state != W25Q_OK)
+ return state;
+ buf_reg |= 0b10; // set ADP bit
+ state = W25Q_WriteStatusReg(buf_reg, 3);
+ if (state != W25Q_OK)
+ return state;
+ }
+
+ /* If current 4-byte
+ mode disabled */
+ if (!w25q_status.ADS) {
+ state = W25Q_Enter4ByteMode(1);
+ if (state != W25Q_OK)
+ return state;
+ }
+#endif
+
+ /* If Quad-SPI mode disabled */
+ if (!w25q_status.QE) {
+ u8_t buf_reg = 0;
+ state = W25Q_ReadStatusReg(&buf_reg, 2);
+ if (state != W25Q_OK)
+ return state;
+ buf_reg |= 0b10;
+ state = W25Q_WriteStatusReg(buf_reg, 2);
+ if (state != W25Q_OK)
+ return state;
+ }
+
+ // make another read
+ state = W25Q_ReadStatusStruct(NULL);
+ // return communication status
+ return state;
+}
+
+/**
+ * @}
+ * @addtogroup W25Q_Reg Register Functions
+ * @brief Operations with Status Registers
+ * @{
+ */
+
+/**
+ * @brief W25Q Enable Volatile SR
+ * Makes status register volatile (temporary)
+ *
+ * @attention Func in development
+ * @param none
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_EnableVolatileSR(void) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief W25Q Read Status Register
+ * Read one status register
+ *
+ * @param[out] reg_data 1 byte
+ * @param[in] reg_num Desired register 1..3
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadStatusReg(u8_t *reg_data, u8_t reg_num) {
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+
+ if (reg_num == 1)
+ com.Instruction = W25Q_READ_SR1;
+ else if (reg_num == 2)
+ com.Instruction = W25Q_READ_SR2;
+ else if (reg_num == 3)
+ com.Instruction = W25Q_READ_SR3;
+ else
+ return W25Q_PARAM_ERR;
+
+ com.AddressMode = QSPI_ADDRESS_NONE;
+ com.AddressSize = QSPI_ADDRESS_NONE;
+ com.Address = 0x0U;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_1_LINE;
+ com.NbData = 1;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+ if (HAL_QSPI_Receive(&hqspi, reg_data, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Write Status Register
+ * Write one status register
+ *
+ * @param[in] reg_data 1 byte
+ * @param[in] reg_num Desired register 1..3
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_WriteStatusReg(u8_t reg_data, u8_t reg_num) {
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ W25Q_STATE state = W25Q_WriteEnable(1);
+ if (state != W25Q_OK)
+ return state;
+
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+
+ if (reg_num == 1)
+ com.Instruction = W25Q_WRITE_SR1;
+ else if (reg_num == 2)
+ com.Instruction = W25Q_WRITE_SR2;
+ else if (reg_num == 3)
+ com.Instruction = W25Q_WRITE_SR3;
+ else
+ return W25Q_PARAM_ERR;
+
+ com.AddressMode = QSPI_ADDRESS_NONE;
+ com.AddressSize = QSPI_ADDRESS_NONE;
+ com.Address = 0x0U;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_1_LINE;
+ com.NbData = 1;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+ if (HAL_QSPI_Transmit(&hqspi, &reg_data, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Read Status Registers
+ * Read all status registers to struct
+ *
+ * @param[out] status W25Q_STATUS_REG Pointer
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadStatusStruct(W25Q_STATUS_REG *status) {
+ // buffer enum-variable
+ W25Q_STATE state;
+
+ // buffer register variables
+ u8_t SRs[3] = { 0, };
+
+ // first portion
+ state = W25Q_ReadStatusReg(&SRs[0], 1);
+ if (state != W25Q_OK)
+ return state;
+
+ // second portion
+ state = W25Q_ReadStatusReg(&SRs[1], 2);
+ if (state != W25Q_OK)
+ return state;
+
+ // third portion
+ state = W25Q_ReadStatusReg(&SRs[2], 3);
+ if (state != W25Q_OK)
+ return state;
+ if(status){
+ status->BUSY = w25q_status.BUSY = SRs[0] & 0b1;
+ status->WEL = w25q_status.WEL = (SRs[0] >> 1) & 0b1;
+ status->QE = w25q_status.QE = (SRs[1] >> 1) & 0b1;
+ status->SUS = w25q_status.SUS = (SRs[1] >> 7) & 0b1;
+ status->ADS = w25q_status.ADS = SRs[2] & 0b1;
+ status->ADP = w25q_status.ADP = (SRs[2] >> 1) & 0b1;
+ status->SLEEP = w25q_status.SLEEP; // возможно нужно вынести в начало (тестить)
+ }
+
+ return state;
+}
+
+/**
+ * @brief W25Q Check Busy flag
+ * Fast checking Busy flag
+ *
+ * @param none
+ * @return W25Q_STATE enum (W25Q_OK / W25Q_BUSY)
+ */
+W25Q_STATE W25Q_IsBusy(void) {
+ W25Q_STATE state;
+ u8_t sr = 0;
+
+ state = W25Q_ReadStatusReg(&sr, 1);
+ if (state != W25Q_OK)
+ return state;
+
+ w25q_status.BUSY = sr & 0b1;
+
+ return w25q_status.BUSY ? W25Q_BUSY : W25Q_OK;
+}
+
+/**
+ * @}
+ * @addtogroup W25Q_Read Read Functions
+ * @brief Read operations - single data type variables or raw 8-bit blocks
+ * @{
+ */
+
+/**
+ * @brief W25Q Read single Signed Byte
+ * Read signed 8-bit byte variable
+ *
+ * @param[out] buf Data to be read (single)
+ * @param[in] pageShift Byte shift inside page (0..255)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadSByte(i8_t *buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data;
+ W25Q_STATE state = W25Q_ReadRaw(&data, 1, rawAddr);
+ if (state != W25Q_OK)
+ return state;
+ memcpy(buf, &data, 1);
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Read single Unsigned Byte
+ * Read unsigned 8-bit byte variable
+ *
+ * @param[out] buf Data to be read (single)
+ * @param[in] pageShift Byte shift inside page (0..255)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadByte(u8_t *buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data;
+ W25Q_STATE state = W25Q_ReadRaw(&data, 1, rawAddr);
+ if (state != W25Q_OK)
+ return state;
+ buf[0] = data;
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Read single Signed Word
+ * Read signed 16-bit word variable
+ *
+ * @param[out] buf Data to be read (single)
+ * @param[in] pageShift Byte shift inside page (0..254)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadSWord(i16_t *buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT || pageShift > 256 - 2)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data[2];
+ W25Q_STATE state = W25Q_ReadRaw(data, 2, rawAddr);
+ if (state != W25Q_OK)
+ return state;
+ memcpy(buf, data, 2);
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Read single Unsigned Word
+ * Read unsigned 16-bit word variable
+ *
+ * @param[out] buf Data to be read (single)
+ * @param[in] pageShift Byte shift inside page (0..254)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadWord(u16_t *buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT || pageShift > 256 - 2)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data[2];
+ W25Q_STATE state = W25Q_ReadRaw(data, 2, rawAddr);
+ if (state != W25Q_OK)
+ return state;
+ memcpy(buf, data, 2);
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Read single Signed Long
+ * Read signed 32-bit long variable
+ *
+ * @param[out] buf Data to be read (single)
+ * @param[in] pageShift Byte shift inside page (0..252)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadSLong(i32_t *buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT || pageShift > 256 - 4)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data[4];
+ W25Q_STATE state = W25Q_ReadRaw(data, 4, rawAddr);
+ if (state != W25Q_OK)
+ return state;
+ memcpy(buf, data, 4);
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Read single Signed Long
+ * Read signed 32-bit long variable
+ *
+ * @param[out] buf Data to be read (single)
+ * @param[in] pageShift Byte shift inside page (0..252)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadLong(u32_t *buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT || pageShift > 256 - 4)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data[4];
+ W25Q_STATE state = W25Q_ReadRaw(data, 4, rawAddr);
+ if (state != W25Q_OK)
+ return state;
+ memcpy(buf, data, 4);
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Read any 8-bit data
+ * Read any 8-bit data from preffered page place
+ *
+ * @note Use memcpy to decode data
+ * @param[out] buf Pointer to data to be read (single or array)
+ * @param[in] len Length of data (1..256)
+ * @param[in] pageShift Byte shift inside page (0..256 - len)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadData(u8_t *buf, u16_t len, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT || len == 0 || len > 256 || pageShift > 256 - len)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ return W25Q_ReadRaw(buf, len, rawAddr);
+}
+
+/**
+ * @brief W25Q Read any 8-bit data from raw addr
+ * Read any 8-bit data from preffered chip address
+ *
+ * @note Address is in [byte] size
+ * @note Be carefull with page overrun
+ * @param[out] buf Pointer to data to be written (single or array)
+ * @param[in] data_len Length of data (1..256)
+ * @param[in] rawAddr Start address of chip's cell
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadRaw(u8_t *buf, u16_t data_len, u32_t rawAddr) {
+ if (data_len > 256 || data_len == 0)
+ return W25Q_PARAM_ERR;
+
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+#if MEM_FLASH_SIZE > 128U
+ com.Instruction = W25Q_FAST_READ_QUAD_IO_4B; // Command
+ com.AddressSize = QSPI_ADDRESS_32_BITS;
+#else
+ com.Instruction = W25Q_FAST_READ; // Command
+ com.AddressSize = QSPI_ADDRESS_24_BITS;
+ #endif
+ com.AddressMode = QSPI_ADDRESS_1_LINE;
+
+ com.Address = rawAddr;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 8;
+ com.DataMode = QSPI_DATA_1_LINE;
+ com.NbData = data_len;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ if (HAL_QSPI_Receive(&hqspi, buf, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Read any 8-bit data from raw addr
+ * Read any 8-bit data from preffered chip address by SINGLE SPI
+ *
+ * @note Works only with SINGLE SPI Line
+ * @param[out] buf Pointer to data array
+ * @param[in] len Length of array
+ * @param[in] Addr Address to data
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_SingleRead(u8_t *buf, u32_t len, u32_t Addr) {
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+#if MEM_FLASH_SIZE > 128U
+ com.Instruction = W25Q_READ_DATA_4B; // Command
+ com.AddressSize = QSPI_ADDRESS_32_BITS;
+#else
+ com.Instruction = W25Q_READ_DATA; // Command
+ com.AddressSize = QSPI_ADDRESS_24_BITS;
+#endif
+ com.AddressMode = QSPI_ADDRESS_1_LINE;
+
+ com.Address = Addr;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_1_LINE;
+ com.NbData = len;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ if (HAL_QSPI_Receive(&hqspi, buf, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ return W25Q_OK;
+}
+
+/**
+ * @}
+ * @addtogroup W25Q_Write Write functions
+ * @brief Program/write operations - single data type variables or raw 8-bit blocks
+ * @{
+ */
+
+/**
+ * @brief W25Q Burst Wrap settings
+ *
+ * @attention Func in development
+ *
+ * @param[in] WrapSize Wrap size: 8/16/32/64 / 0 - disable
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_SetBurstWrap(u8_t WrapSize) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief W25Q Program single Signed Byte
+ * Program signed 8-bit byte variable
+ *
+ * @param[in] buf Data to be written (single)
+ * @param[in] pageShift Byte shift inside page (0..255)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgramSByte(i8_t buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data;
+ memcpy(&data, &buf, 1);
+ return W25Q_ProgramRaw(&data, 1, rawAddr);
+}
+
+/**
+ * @brief W25Q Program single Unsigned Byte
+ * Program unsigned 8-bit byte vairable
+ *
+ * @param[in] buf Data to be written (single)
+ * @param[in] pageShift Byte shift inside page (0..255)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgramByte(u8_t buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data;
+ memcpy(&data, &buf, 1);
+ return W25Q_ProgramRaw(&data, 1, rawAddr);
+}
+
+/**
+ * @brief W25Q Program single Signed Word
+ * Program signed 16-bit word vairable
+ *
+ * @param[in] buf Data to be written (single)
+ * @param[in] pageShift Byte shift inside page (0..254)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgramSWord(i16_t buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT || pageShift > 256 - 2)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data[2];
+ memcpy(data, &buf, 2);
+ return W25Q_ProgramRaw(data, 2, rawAddr);
+}
+
+/**
+ * @brief W25Q Program single Unsigned Word
+ * Program unsigned 16-bit word vairable
+ *
+ * @param[in] buf Data to be written (single)
+ * @param[in] pageShift Byte shift inside page (0..254)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgramWord(u16_t buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT || pageShift > 256 - 2)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data[2];
+ memcpy(data, &buf, 2);
+ return W25Q_ProgramRaw(data, 2, rawAddr);
+}
+
+/**
+ * @brief W25Q Program single Signed Long
+ * Program signed 32-bit long vairable
+ *
+ * @param[in] buf Data to be written (single)
+ * @param[in] pageShift Byte shift inside page (0..252)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgramSLong(i32_t buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT || pageShift > 256 - 4)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data[4];
+ memcpy(data, &buf, 4);
+ return W25Q_ProgramRaw(data, 4, rawAddr);
+}
+
+/**
+ * @brief W25Q Program single Unigned Long
+ * Program unsigned 32-bit long vairable
+ *
+ * @param[in] buf Data to be written (single)
+ * @param[in] pageShift Byte shift inside page (0..252)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgramLong(u32_t buf, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT || pageShift > 256 - 4)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ u8_t data[4];
+ memcpy(data, &buf, 4);
+ return W25Q_ProgramRaw(data, 4, rawAddr);
+}
+
+/**
+ * @brief W25Q Program any 8-bit data
+ * Program any 8-bit data to preffered page place
+ *
+ * @note Use memcpy to prepare data
+ * @param[in] buf Pointer to data to be written (single or array)
+ * @param[in] len Length of data (1..256)
+ * @param[in] pageShift Byte shift inside page (0..256 - len)
+ * @param[in] pageNum Page number (0..PAGE_COUNT-1)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgramData(u8_t *buf, u16_t len, u8_t pageShift, u32_t pageNum) {
+ if (pageNum >= PAGE_COUNT || len == 0 || len > 256 || pageShift > 256 - len)
+ return W25Q_PARAM_ERR;
+ u32_t rawAddr = page_to_addr(pageNum, pageShift);
+ return W25Q_ProgramRaw(buf, len, rawAddr);
+}
+
+/**
+ * @brief W25Q Program any 8-bit data to raw addr
+ * Program any 8-bit data to preffered chip address
+ *
+ * @note Address is in [byte] size
+ * @note Be carefull with page overrun
+ * @param[in] buf Pointer to data to be written (single or array)
+ * @param[in] data_len Length of data (1..256)
+ * @param[in] rawAddr Start address of chip's cell
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgramRaw(u8_t *buf, u16_t data_len, u32_t rawAddr) {
+ if (data_len > 256 || data_len == 0)
+ return W25Q_PARAM_ERR;
+
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ W25Q_STATE state = W25Q_WriteEnable(1);
+ if (state != W25Q_OK)
+ return state;
+
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+#if MEM_FLASH_SIZE > 128U
+ com.Instruction = W25Q_PAGE_PROGRAM_QUAD_INP_4B; // Command
+ com.AddressSize = QSPI_ADDRESS_32_BITS;
+#else
+ com.Instruction = W25Q_PAGE_PROGRAM; // Command
+ com.AddressSize = QSPI_ADDRESS_24_BITS;
+ #endif
+ com.AddressMode = QSPI_ADDRESS_1_LINE;
+
+ com.Address = rawAddr;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_1_LINE;
+ com.NbData = data_len;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ if (HAL_QSPI_Transmit(&hqspi, buf, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ return W25Q_OK;
+}
+
+/**
+ * @}
+ * @addtogroup W25Q_Erase Erase functions
+ * @brief Erase sector, blocks or whole chip
+ * @{
+ */
+
+/**
+ * @brief W25Q Sector erase (4KB)
+ * Minimal size operation to erase data
+ *
+ * @note Should be executed before writing
+ * @param[in] SectAddr Sector start address
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_EraseSector(u32_t SectAddr) {
+ if (SectAddr >= SECTOR_COUNT)
+ return W25Q_PARAM_ERR;
+
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ u32_t rawAddr = SectAddr * MEM_SECTOR_SIZE * 1024U;
+
+ W25Q_STATE state = W25Q_WriteEnable(1);
+ if (state != W25Q_OK)
+ return state;
+
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+#if MEM_FLASH_SIZE > 128U
+ com.Instruction = W25Q_SECTOR_ERASE_4B; // Command
+ com.AddressSize = QSPI_ADDRESS_32_BITS;
+#else
+ com.Instruction = W25Q_SECTOR_ERASE; // Command
+ com.AddressSize = QSPI_ADDRESS_24_BITS;
+#endif
+ com.AddressMode = QSPI_ADDRESS_1_LINE;
+
+ com.Address = rawAddr;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_NONE;
+ com.NbData = 0;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Block erase (32/64 KB)
+ * Func to erase big block
+ *
+ * @note Should be executed before writing
+ * @param[in] BlockAddr Block start address
+ * @param[in] size Size of block: 32KB or 64KB
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_EraseBlock(u32_t BlockAddr, u8_t size) {
+ if (size != 32 && size != 64)
+ return W25Q_PARAM_ERR;
+ if ((size == 64 && BlockAddr >= BLOCK_COUNT)
+ || (size == 32 && BlockAddr >= BLOCK_COUNT * 2))
+ return W25Q_PARAM_ERR;
+
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ u32_t rawAddr = BlockAddr * MEM_SECTOR_SIZE * 1024U * 16;
+ if (size == 32)
+ rawAddr /= 2;
+
+ W25Q_STATE state = W25Q_WriteEnable(1);
+ if (state != W25Q_OK)
+ return state;
+
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+
+ if (size == 32) {
+ com.Instruction = W25Q_32KB_BLOCK_ERASE; // Command
+#if MEM_FLASH_SIZE > 128U
+ com.AddressSize = QSPI_ADDRESS_32_BITS;
+#else
+ com.AddressSize = QSPI_ADDRESS_24_BITS;
+#endif
+ } else if (size == 64) {
+#if MEM_FLASH_SIZE > 128U
+ com.Instruction = W25Q_64KB_BLOCK_ERASE_4B; // Command
+ com.AddressSize = QSPI_ADDRESS_32_BITS;
+#else
+ com.Instruction = W25Q_64KB_BLOCK_ERASE; // Command
+ com.AddressSize = QSPI_ADDRESS_24_BITS;
+#endif
+ }
+
+ com.AddressMode = QSPI_ADDRESS_1_LINE;
+
+ com.Address = rawAddr;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_NONE;
+ com.NbData = 0;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Chip erase
+ * Func to erase all the data on chip
+ *
+ * @note Should be executed before writing
+ * @param none
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_EraseChip(void) {
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ W25Q_STATE state = W25Q_WriteEnable(1);
+ if (state != W25Q_OK)
+ return state;
+
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+ com.Instruction = W25Q_CHIP_ERASE; // Command
+
+ com.AddressSize = QSPI_ADDRESS_NONE;
+ com.AddressMode = QSPI_ADDRESS_NONE;
+ com.Address = 0;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_NONE;
+ com.NbData = 0;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ return W25Q_OK;
+}
+
+/**
+ * @}
+ * @addtogroup W25Q_SUS Suspend functions
+ * @brief Pause/resume operations
+ * @{
+ */
+
+/**
+ * @brief W25Q Programm/Erase Suspend
+ * Pause programm or suspend operatiom
+ *
+ * @note SUS == 0 && BUSY == 1, otherwise ignored
+ * @note Power loose during suspend state may corrupt data
+ * @param none
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgSuspend(void) {
+ if (W25Q_BUSY != W25Q_IsBusy())
+ return W25Q_CHIP_IGNORE;
+
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+ com.Instruction = W25Q_ERASEPROG_SUSPEND; // Command
+
+ com.AddressSize = QSPI_ADDRESS_NONE;
+ com.AddressMode = QSPI_ADDRESS_NONE;
+ com.Address = 0;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_NONE;
+ com.NbData = 0;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Programm/Erase Resume
+ * Resume suspended state
+ *
+ * @note SUS == 1, otherwise ignored
+ * @param none
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgResume(void) {
+
+ W25Q_STATE state = W25Q_ReadStatusStruct(NULL);
+ if (state != W25Q_OK)
+ return state;
+
+ if (w25q_status.SUS != 1)
+ return W25Q_CHIP_IGNORE;
+
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+ com.Instruction = W25Q_ERASEPROG_RESUME; // Command
+
+ com.AddressSize = QSPI_ADDRESS_NONE;
+ com.AddressMode = QSPI_ADDRESS_NONE;
+ com.Address = 0;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_NONE;
+ com.NbData = 0;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK)
+ return W25Q_SPI_ERR;
+
+ return W25Q_OK;
+}
+
+/**
+ * @}
+ * @addtogroup W25Q_Sleep Sleep functions
+ * @brief Баю-бай, ток засыпай
+ * @{
+ */
+
+/**
+ * @brief W25Q Sleep / Power Down
+ * Set chip to low-power state
+ *
+ * @note Use WakeUP or ReadID
+ * @param none
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_Sleep(void) {
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+ com.Instruction = W25Q_POWERDOWN; // Command
+
+ com.AddressMode = QSPI_ADDRESS_NONE;
+ com.AddressSize = QSPI_ADDRESS_NONE;
+ com.Address = 0x0U;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_NONE;
+ com.NbData = 0;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+ w25q_delay(1); // Give a little time to sleep
+
+ w25q_status.SLEEP = 1;
+
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q WakeUP
+ * Wake UP function
+ *
+ * @param none
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_WakeUP(void) {
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+ com.Instruction = W25Q_POWERUP; // Command
+
+ com.AddressMode = QSPI_ADDRESS_NONE;
+ com.AddressSize = QSPI_ADDRESS_NONE;
+ com.Address = 0x0U;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_NONE;
+ com.NbData = 0;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+ w25q_delay(1); // Give a little time to wake
+
+ return W25Q_OK;
+}
+
+/**
+ * @}
+ * @addtogroup W25Q_ID ID functions
+ * @brief Who am I? Хто я?
+ * @{
+ */
+
+/**
+ * @brief W25Q Read ID
+ * Function for reading chip ID
+ *
+ * @param[out] buf Pointer to output data (1 byte)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadID(u8_t *buf) {
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+ com.Instruction = W25Q_DEVID; // Command
+
+ com.AddressMode = QSPI_ADDRESS_1_LINE;
+ com.AddressSize = QSPI_ADDRESS_24_BITS;
+ com.Address = 0x0U;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_1_LINE;
+ com.NbData = 1;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+ if (HAL_QSPI_Receive(&hqspi, buf, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Read chip Full ID
+ * Read Manufacturer ID + Device ID
+ *
+ * @attention Func in development
+ * @param[out] buf Pointer to data from ID register
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadFullID(u8_t *buf) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief W25Q Read chip UID
+ * Read Unique ID
+ *
+ * @attention Func in development
+ * @param[out] buf Pointer to data from ID register
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadUID(u8_t *buf) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief W25Q Read JEDEC ID
+ * Read ID by JEDEC standards
+ *
+ * @attention Func in development
+ * @param[out] buf Pointer to data from ID register
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadJEDECID(u8_t *buf) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief W25Q Read SFDP Register
+ * Read device descriptor by SFDP standard
+ *
+ * @attention Func in development
+ * @param[out] buf Pointer to data from ID register
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadSFDPRegister(u8_t *buf) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @}
+ * @addtogroup W25Q_Secure Security register functions
+ * @brief Shhh, security
+ * @{
+ */
+
+/**
+ * @brief W25Q Erase Security Registers
+ * Clean security registers (one or all)
+ *
+ * @attention Func in development
+ * @param[in] numReg Number of security register (1..3 / 0-all)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_EraseSecurityRegisters(u8_t numReg) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief W25Q Program Security Register
+ * Write data to security reg
+ *
+ * @attention Func in development
+ * @param[in] buf Pointer to 8-bit data bufer
+ * @param[in] numReg Number of security register (1..3)
+ * @param[in] byteAddr Byte addr in register (0..255)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ProgSecurityRegisters(u8_t *buf, u8_t numReg, u8_t byteAddr) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief W25Q Read Security Register
+ * Read data from security reg
+ *
+ * @attention Func in development
+ * @param[out] buf Pointer to 8-bit data bufer
+ * @param[in] numReg Number of security register (1..3)
+ * @param[in] byteAddr Byte addr in register (0..255)
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_ReadSecurityRegisters(u8_t *buf, u8_t numReg, u8_t byteAddr) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @}
+ * @addtogroup W25Q_Protect Read-only protection functions
+ * @brief No writing! Protect block or whole chip
+ * @{
+ */
+
+/**
+ * @brief W25Q 4K Block lock
+ * Set read-only status to 4K block
+ *
+ * @attention Func in development
+ * @param[in] Addr Block address
+ * @param[in] enable 1-Enable/0-Disable
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_BlockReadOnly(u32_t Addr, bool enable) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief W25Q 4K Block lock CHECK
+ * Check read-only status from 4K block
+ *
+ * @attention Func in development
+ * @param[out] state Block read-only status (1-locked/0-unlocked)
+ * @param[in] Addr Block address
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_BlockReadOnlyCheck(bool *state, u32_t Addr) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief W25Q Global read-only lock
+ * Set read-only status to the whole chip
+ *
+ * @attention Func in development
+ * @param[in] enable 1-enable/0-disable
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_GlobalReadOnly(bool enable){
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @}
+ * @addtogroup W25Q_RST Reset functions
+ * @brief Reboot the chip
+ * @{
+ */
+
+/**
+ * @brief W25Q Software Reset
+ * Reset by register (not by external GPIO pin)
+ *
+ * @param[in] force Enable/disable (0/1) force reset - wait for BUSY and SUSpend
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_SwReset(bool force) {
+
+ W25Q_STATE state; // temp status reg
+
+ state = W25Q_ReadStatusStruct(NULL); // read settings
+ if (state != W25Q_OK)
+ return state;
+
+ if (!force || w25q_status.BUSY || w25q_status.SUS) // if busy or suspend
+ return W25Q_CHIP_ERR;
+
+ if (force) {
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+ if (w25q_status.SUS)
+ W25Q_ProgResume();
+ }
+
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+ com.Instruction = W25Q_ENABLE_RST; // Command
+
+ com.AddressMode = QSPI_ADDRESS_NONE;
+ com.AddressSize = QSPI_ADDRESS_NONE;
+ com.Address = 0x0U;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_NONE;
+ com.NbData = 0;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+ w25q_delay(1); // Give a little time to prepare
+
+ com.Instruction = W25Q_RESET;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+ w25q_delay(5); // Give a little time to reset
+
+ state = W25Q_Init();
+
+ return state;
+}
+/// @}
+// addgroup{
+/// @}
+// Public {
+
+/**
+ * @brief W25Q Toggle WEL bit
+ * Toggle write enable latch
+ *
+ * @param[in] enable 1-enable write/0-disable write
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_WriteEnable(bool enable) {
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+ com.Instruction = enable ? W25Q_WRITE_ENABLE : W25Q_WRITE_DISABLE;
+
+ com.AddressMode = QSPI_ADDRESS_NONE;
+ com.AddressSize = QSPI_ADDRESS_NONE;
+ com.Address = 0x0U;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_NONE;
+ com.NbData = 0;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+ w25q_delay(1); // Give a little time to sleep
+
+ w25q_status.WEL = 1;
+
+ return W25Q_OK;
+}
+
+/**
+ * @brief W25Q Toggle 4-byte mode
+ *
+ * @note Affects only ADS bit
+ * @param[in] enable 1-enable/0-disable
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_Enter4ByteMode(bool enable) {
+
+ while (W25Q_IsBusy() == W25Q_BUSY)
+ w25q_delay(1);
+
+ QSPI_CommandTypeDef com;
+
+ com.InstructionMode = QSPI_INSTRUCTION_1_LINE; // QSPI_INSTRUCTION_...
+ com.Instruction = enable ? W25Q_ENABLE_4B_MODE : W25Q_DISABLE_4B_MODE;
+
+ com.AddressMode = QSPI_ADDRESS_NONE;
+ com.AddressSize = QSPI_ADDRESS_NONE;
+ com.Address = 0x0U;
+
+ com.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytes = QSPI_ALTERNATE_BYTES_NONE;
+ com.AlternateBytesSize = QSPI_ALTERNATE_BYTES_NONE;
+
+ com.DummyCycles = 0;
+ com.DataMode = QSPI_DATA_NONE;
+ com.NbData = 0;
+
+ com.DdrMode = QSPI_DDR_MODE_DISABLE;
+ //com.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
+ com.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
+
+ if (HAL_QSPI_Command(&hqspi, &com, HAL_QSPI_TIMEOUT_DEFAULT_VALUE)
+ != HAL_OK) {
+ return W25Q_SPI_ERR;
+ }
+
+ w25q_delay(1); // Give a little time to set command
+
+ return W25Q_ReadStatusStruct(NULL);
+}
+
+/**
+ * @brief W25Q Set extended byte
+ * Extended byte in 3-byte mode
+ *
+ * @attention Func in development
+ * @param[in] Addr 4th byte of addr
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_SetExtendedAddr(u8_t Addr) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief W25Q Get extended byte
+ * Read extended byte in 3-byte mode
+ *
+ * @attention Func in development
+ * @param[out] Addr 4th byte of addr
+ * @return W25Q_STATE enum
+ */
+W25Q_STATE W25Q_GetExtendedAddr(u8_t *outAddr) {
+ return W25Q_PARAM_ERR;
+}
+
+/**
+ * @brief Page to address
+ * Translate page to byte-address
+ *
+ * @param[in] pageNum Number of page
+ * @param[in] pageShift Byte to shift inside page
+ * @return byte-address
+ */
+u32_t page_to_addr(u32_t pageNum, u8_t pageShift) {
+ return pageNum * MEM_PAGE_SIZE + pageShift;
+}
+
+///@}
diff --git a/firmware/rf test/Core/Startup/startup_stm32wb55cgux.s b/firmware/rf test/Core/Startup/startup_stm32wb55cgux.s
new file mode 100644
index 0000000..8f391be
--- /dev/null
+++ b/firmware/rf test/Core/Startup/startup_stm32wb55cgux.s
@@ -0,0 +1,447 @@
+/**
+ ******************************************************************************
+ * @file startup_stm32wb55xx_cm4.s
+ * @author MCD Application Team
+ * @brief STM32WB55xx devices vector table GCC toolchain.
+ * This module performs:
+ * - Set the initial SP
+ * - Set the initial PC == Reset_Handler,
+ * - Set the vector table entries with the exceptions ISR address
+ * - Branches to main in the C library (which eventually
+ * calls main()).
+ * After Reset the Cortex-M4 processor is in Thread mode,
+ * priority is Privileged, and the Stack is set to Main.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2019-2022 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+ .syntax unified
+ .cpu cortex-m4
+ .fpu softvfp
+ .thumb
+
+.global g_pfnVectors
+.global Default_Handler
+
+/* start address for the initialization values of the .data section.
+defined in linker script */
+.word _sidata
+/* start address for the .data section. defined in linker script */
+.word _sdata
+/* end address for the .data section. defined in linker script */
+.word _edata
+/* start address for the .bss section. defined in linker script */
+.word _sbss
+/* end address for the .bss section. defined in linker script */
+.word _ebss
+/* start address for the initialization values of the .MB_MEM2 section.
+defined in linker script */
+.word _siMB_MEM2
+/* start address for the .MB_MEM2 section. defined in linker script */
+.word _sMB_MEM2
+/* end address for the .MB_MEM2 section. defined in linker script */
+.word _eMB_MEM2
+
+/* INIT_BSS macro is used to fill the specified region [start : end] with zeros */
+.macro INIT_BSS start, end
+ ldr r0, =\start
+ ldr r1, =\end
+ movs r3, #0
+ bl LoopFillZerobss
+.endm
+
+/* INIT_DATA macro is used to copy data in the region [start : end] starting from 'src' */
+.macro INIT_DATA start, end, src
+ ldr r0, =\start
+ ldr r1, =\end
+ ldr r2, =\src
+ movs r3, #0
+ bl LoopCopyDataInit
+.endm
+
+.section .text.data_initializers
+CopyDataInit:
+ ldr r4, [r2, r3]
+ str r4, [r0, r3]
+ adds r3, r3, #4
+
+LoopCopyDataInit:
+ adds r4, r0, r3
+ cmp r4, r1
+ bcc CopyDataInit
+ bx lr
+
+FillZerobss:
+ str r3, [r0]
+ adds r0, r0, #4
+
+LoopFillZerobss:
+ cmp r0, r1
+ bcc FillZerobss
+ bx lr
+
+ .section .text.Reset_Handler
+ .weak Reset_Handler
+ .type Reset_Handler, %function
+Reset_Handler:
+ ldr r0, =_estack
+ mov sp, r0 /* set stack pointer */
+/* Call the clock system initialization function.*/
+ bl SystemInit
+
+/* Copy the data segment initializers from flash to SRAM */
+ INIT_DATA _sdata, _edata, _sidata
+ INIT_DATA _sMB_MEM2, _eMB_MEM2, _siMB_MEM2
+
+/* Zero fill the bss segments. */
+ INIT_BSS _sbss, _ebss
+
+/* Call static constructors */
+ bl __libc_init_array
+/* Call the application s entry point.*/
+ bl main
+
+LoopForever:
+ b LoopForever
+
+.size Reset_Handler, .-Reset_Handler
+
+/**
+ * @brief This is the code that gets called when the processor receives an
+ * unexpected interrupt. This simply enters an infinite loop, preserving
+ * the system state for examination by a debugger.
+ *
+ * @param None
+ * @retval None
+*/
+ .section .text.Default_Handler,"ax",%progbits
+Default_Handler:
+Infinite_Loop:
+ b Infinite_Loop
+ .size Default_Handler, .-Default_Handler
+/******************************************************************************
+*
+* The minimal vector table for a Cortex-M4. Note that the proper constructs
+* must be placed on this to ensure that it ends up at physical address
+* 0x0000.0000.
+*
+******************************************************************************/
+ .section .isr_vector,"a",%progbits
+ .type g_pfnVectors, %object
+
+
+g_pfnVectors:
+ .word _estack
+ .word Reset_Handler
+ .word NMI_Handler
+ .word HardFault_Handler
+ .word MemManage_Handler
+ .word BusFault_Handler
+ .word UsageFault_Handler
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word SVC_Handler
+ .word DebugMon_Handler
+ .word 0
+ .word PendSV_Handler
+ .word SysTick_Handler
+ .word WWDG_IRQHandler
+ .word PVD_PVM_IRQHandler
+ .word TAMP_STAMP_LSECSS_IRQHandler
+ .word RTC_WKUP_IRQHandler
+ .word FLASH_IRQHandler
+ .word RCC_IRQHandler
+ .word EXTI0_IRQHandler
+ .word EXTI1_IRQHandler
+ .word EXTI2_IRQHandler
+ .word EXTI3_IRQHandler
+ .word EXTI4_IRQHandler
+ .word DMA1_Channel1_IRQHandler
+ .word DMA1_Channel2_IRQHandler
+ .word DMA1_Channel3_IRQHandler
+ .word DMA1_Channel4_IRQHandler
+ .word DMA1_Channel5_IRQHandler
+ .word DMA1_Channel6_IRQHandler
+ .word DMA1_Channel7_IRQHandler
+ .word ADC1_IRQHandler
+ .word USB_HP_IRQHandler
+ .word USB_LP_IRQHandler
+ .word C2SEV_PWR_C2H_IRQHandler
+ .word COMP_IRQHandler
+ .word EXTI9_5_IRQHandler
+ .word TIM1_BRK_IRQHandler
+ .word TIM1_UP_TIM16_IRQHandler
+ .word TIM1_TRG_COM_TIM17_IRQHandler
+ .word TIM1_CC_IRQHandler
+ .word TIM2_IRQHandler
+ .word PKA_IRQHandler
+ .word I2C1_EV_IRQHandler
+ .word I2C1_ER_IRQHandler
+ .word I2C3_EV_IRQHandler
+ .word I2C3_ER_IRQHandler
+ .word SPI1_IRQHandler
+ .word SPI2_IRQHandler
+ .word USART1_IRQHandler
+ .word LPUART1_IRQHandler
+ .word SAI1_IRQHandler
+ .word TSC_IRQHandler
+ .word EXTI15_10_IRQHandler
+ .word RTC_Alarm_IRQHandler
+ .word CRS_IRQHandler
+ .word PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler
+ .word IPCC_C1_RX_IRQHandler
+ .word IPCC_C1_TX_IRQHandler
+ .word HSEM_IRQHandler
+ .word LPTIM1_IRQHandler
+ .word LPTIM2_IRQHandler
+ .word LCD_IRQHandler
+ .word QUADSPI_IRQHandler
+ .word AES1_IRQHandler
+ .word AES2_IRQHandler
+ .word RNG_IRQHandler
+ .word FPU_IRQHandler
+ .word DMA2_Channel1_IRQHandler
+ .word DMA2_Channel2_IRQHandler
+ .word DMA2_Channel3_IRQHandler
+ .word DMA2_Channel4_IRQHandler
+ .word DMA2_Channel5_IRQHandler
+ .word DMA2_Channel6_IRQHandler
+ .word DMA2_Channel7_IRQHandler
+ .word DMAMUX1_OVR_IRQHandler
+
+ .size g_pfnVectors, .-g_pfnVectors
+
+/*******************************************************************************
+*
+* Provide weak aliases for each Exception handler to the Default_Handler.
+* As they are weak aliases, any function with the same name will override
+* this definition.
+*
+*******************************************************************************/
+ .weak NMI_Handler
+ .thumb_set NMI_Handler,Default_Handler
+
+ .weak HardFault_Handler
+ .thumb_set HardFault_Handler,Default_Handler
+
+ .weak MemManage_Handler
+ .thumb_set MemManage_Handler,Default_Handler
+
+ .weak BusFault_Handler
+ .thumb_set BusFault_Handler,Default_Handler
+
+ .weak UsageFault_Handler
+ .thumb_set UsageFault_Handler,Default_Handler
+
+ .weak SVC_Handler
+ .thumb_set SVC_Handler,Default_Handler
+
+ .weak DebugMon_Handler
+ .thumb_set DebugMon_Handler,Default_Handler
+
+ .weak PendSV_Handler
+ .thumb_set PendSV_Handler,Default_Handler
+
+ .weak SysTick_Handler
+ .thumb_set SysTick_Handler,Default_Handler
+
+ .weak WWDG_IRQHandler
+ .thumb_set WWDG_IRQHandler,Default_Handler
+
+ .weak PVD_PVM_IRQHandler
+ .thumb_set PVD_PVM_IRQHandler,Default_Handler
+
+ .weak TAMP_STAMP_LSECSS_IRQHandler
+ .thumb_set TAMP_STAMP_LSECSS_IRQHandler,Default_Handler
+
+ .weak RTC_WKUP_IRQHandler
+ .thumb_set RTC_WKUP_IRQHandler,Default_Handler
+
+ .weak FLASH_IRQHandler
+ .thumb_set FLASH_IRQHandler,Default_Handler
+
+ .weak RCC_IRQHandler
+ .thumb_set RCC_IRQHandler,Default_Handler
+
+ .weak EXTI0_IRQHandler
+ .thumb_set EXTI0_IRQHandler,Default_Handler
+
+ .weak EXTI1_IRQHandler
+ .thumb_set EXTI1_IRQHandler,Default_Handler
+
+ .weak EXTI2_IRQHandler
+ .thumb_set EXTI2_IRQHandler,Default_Handler
+
+ .weak EXTI3_IRQHandler
+ .thumb_set EXTI3_IRQHandler,Default_Handler
+
+ .weak EXTI4_IRQHandler
+ .thumb_set EXTI4_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel1_IRQHandler
+ .thumb_set DMA1_Channel1_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel2_IRQHandler
+ .thumb_set DMA1_Channel2_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel3_IRQHandler
+ .thumb_set DMA1_Channel3_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel4_IRQHandler
+ .thumb_set DMA1_Channel4_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel5_IRQHandler
+ .thumb_set DMA1_Channel5_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel6_IRQHandler
+ .thumb_set DMA1_Channel6_IRQHandler,Default_Handler
+
+ .weak DMA1_Channel7_IRQHandler
+ .thumb_set DMA1_Channel7_IRQHandler,Default_Handler
+
+ .weak ADC1_IRQHandler
+ .thumb_set ADC1_IRQHandler,Default_Handler
+
+ .weak USB_HP_IRQHandler
+ .thumb_set USB_HP_IRQHandler,Default_Handler
+
+ .weak USB_LP_IRQHandler
+ .thumb_set USB_LP_IRQHandler,Default_Handler
+
+ .weak C2SEV_PWR_C2H_IRQHandler
+ .thumb_set C2SEV_PWR_C2H_IRQHandler,Default_Handler
+
+ .weak COMP_IRQHandler
+ .thumb_set COMP_IRQHandler,Default_Handler
+
+ .weak EXTI9_5_IRQHandler
+ .thumb_set EXTI9_5_IRQHandler,Default_Handler
+
+ .weak TIM1_BRK_IRQHandler
+ .thumb_set TIM1_BRK_IRQHandler,Default_Handler
+
+ .weak TIM1_UP_TIM16_IRQHandler
+ .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler
+
+ .weak TIM1_TRG_COM_TIM17_IRQHandler
+ .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler
+
+ .weak TIM1_CC_IRQHandler
+ .thumb_set TIM1_CC_IRQHandler,Default_Handler
+
+ .weak TIM2_IRQHandler
+ .thumb_set TIM2_IRQHandler,Default_Handler
+
+ .weak PKA_IRQHandler
+ .thumb_set PKA_IRQHandler,Default_Handler
+
+ .weak I2C1_EV_IRQHandler
+ .thumb_set I2C1_EV_IRQHandler,Default_Handler
+
+ .weak I2C1_ER_IRQHandler
+ .thumb_set I2C1_ER_IRQHandler,Default_Handler
+
+ .weak I2C3_EV_IRQHandler
+ .thumb_set I2C3_EV_IRQHandler,Default_Handler
+
+ .weak I2C3_ER_IRQHandler
+ .thumb_set I2C3_ER_IRQHandler,Default_Handler
+
+ .weak SPI1_IRQHandler
+ .thumb_set SPI1_IRQHandler,Default_Handler
+
+ .weak SPI2_IRQHandler
+ .thumb_set SPI2_IRQHandler,Default_Handler
+
+ .weak USART1_IRQHandler
+ .thumb_set USART1_IRQHandler,Default_Handler
+
+ .weak LPUART1_IRQHandler
+ .thumb_set LPUART1_IRQHandler,Default_Handler
+
+ .weak SAI1_IRQHandler
+ .thumb_set SAI1_IRQHandler,Default_Handler
+
+ .weak TSC_IRQHandler
+ .thumb_set TSC_IRQHandler,Default_Handler
+
+ .weak EXTI15_10_IRQHandler
+ .thumb_set EXTI15_10_IRQHandler,Default_Handler
+
+ .weak RTC_Alarm_IRQHandler
+ .thumb_set RTC_Alarm_IRQHandler,Default_Handler
+
+ .weak CRS_IRQHandler
+ .thumb_set CRS_IRQHandler,Default_Handler
+
+ .weak PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler
+ .thumb_set PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler,Default_Handler
+
+ .weak IPCC_C1_RX_IRQHandler
+ .thumb_set IPCC_C1_RX_IRQHandler,Default_Handler
+
+ .weak IPCC_C1_TX_IRQHandler
+ .thumb_set IPCC_C1_TX_IRQHandler,Default_Handler
+
+ .weak HSEM_IRQHandler
+ .thumb_set HSEM_IRQHandler,Default_Handler
+
+ .weak LPTIM1_IRQHandler
+ .thumb_set LPTIM1_IRQHandler,Default_Handler
+
+ .weak LPTIM2_IRQHandler
+ .thumb_set LPTIM2_IRQHandler,Default_Handler
+
+ .weak LCD_IRQHandler
+ .thumb_set LCD_IRQHandler,Default_Handler
+
+ .weak QUADSPI_IRQHandler
+ .thumb_set QUADSPI_IRQHandler,Default_Handler
+
+ .weak AES1_IRQHandler
+ .thumb_set AES1_IRQHandler,Default_Handler
+
+ .weak AES2_IRQHandler
+ .thumb_set AES2_IRQHandler,Default_Handler
+
+ .weak RNG_IRQHandler
+ .thumb_set RNG_IRQHandler,Default_Handler
+
+ .weak FPU_IRQHandler
+ .thumb_set FPU_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel1_IRQHandler
+ .thumb_set DMA2_Channel1_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel2_IRQHandler
+ .thumb_set DMA2_Channel2_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel3_IRQHandler
+ .thumb_set DMA2_Channel3_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel4_IRQHandler
+ .thumb_set DMA2_Channel4_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel5_IRQHandler
+ .thumb_set DMA2_Channel5_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel6_IRQHandler
+ .thumb_set DMA2_Channel6_IRQHandler,Default_Handler
+
+ .weak DMA2_Channel7_IRQHandler
+ .thumb_set DMA2_Channel7_IRQHandler,Default_Handler
+
+ .weak DMAMUX1_OVR_IRQHandler
+ .thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler
+