aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2024-06-01 11:47:45 -0400
committerClyne Sullivan <clyne@bitgloo.com>2024-06-01 11:47:45 -0400
commita78f3f6fe924d03be52ad7459203429ef261a4c9 (patch)
tree4dd6d122950d3fc678ed18484ae1843a71b7088c
initial commit
-rw-r--r--.gitignore2
-rw-r--r--Makefile190
-rw-r--r--STM32G031x6.ld85
-rw-r--r--board.c50
-rw-r--r--board.h105
-rw-r--r--cfg/chconf.h480
-rw-r--r--cfg/halconf.h553
-rw-r--r--cfg/mcuconf.h235
-rw-r--r--main.cpp124
-rw-r--r--sos-iir-filter.h128
10 files changed, 1952 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9ef14ad
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.*
+build
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4e12bd1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,190 @@
+##############################################################################
+# Build global options
+# NOTE: Can be overridden externally.
+#
+
+# Compiler options here.
+ifeq ($(USE_OPT),)
+ USE_OPT = -O3 -ggdb -fomit-frame-pointer -falign-functions=16
+endif
+
+# C specific options here (added to USE_OPT).
+ifeq ($(USE_COPT),)
+ USE_COPT =
+endif
+
+# C++ specific options here (added to USE_OPT).
+ifeq ($(USE_CPPOPT),)
+ USE_CPPOPT = -std=c++23 -fno-exceptions -fno-rtti
+endif
+
+# Enable this if you want the linker to remove unused code and data.
+ifeq ($(USE_LINK_GC),)
+ USE_LINK_GC = yes
+endif
+
+# Linker extra options here.
+ifeq ($(USE_LDOPT),)
+ USE_LDOPT = -lm
+endif
+
+# Enable this if you want link time optimizations (LTO).
+ifeq ($(USE_LTO),)
+ USE_LTO = yes
+endif
+
+# Enable this if you want to see the full log while compiling.
+ifeq ($(USE_VERBOSE_COMPILE),)
+ USE_VERBOSE_COMPILE = no
+endif
+
+# If enabled, this option makes the build process faster by not compiling
+# modules not used in the current configuration.
+ifeq ($(USE_SMART_BUILD),)
+ USE_SMART_BUILD = yes
+endif
+
+#
+# Build global options
+##############################################################################
+
+##############################################################################
+# Architecture or project specific options
+#
+
+# Stack size to be allocated to the Cortex-M process stack. This stack is
+# the stack used by the main() thread.
+ifeq ($(USE_PROCESS_STACKSIZE),)
+ USE_PROCESS_STACKSIZE = 0x200
+endif
+
+# Stack size to the allocated to the Cortex-M main/exceptions stack. This
+# stack is used for processing interrupts and exceptions.
+ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
+ USE_EXCEPTIONS_STACKSIZE = 0x100
+endif
+
+# Enables the use of FPU (no, softfp, hard).
+ifeq ($(USE_FPU),)
+ USE_FPU = softfp
+endif
+
+# FPU-related options.
+ifeq ($(USE_FPU_OPT),)
+ USE_FPU_OPT = -mfloat-abi=$(USE_FPU) -mfpu=fpv4-sp-d16
+endif
+
+#
+# Architecture or project specific options
+##############################################################################
+
+##############################################################################
+# Project, target, sources and paths
+#
+
+# Define project name here
+PROJECT = ch
+
+# Target settings.
+MCU = cortex-m0
+
+# Imported source files and paths.
+CHIBIOS := ../..
+CONFDIR := ./cfg
+BUILDDIR := ./build
+DEPDIR := ./.dep
+
+# Licensing files.
+include $(CHIBIOS)/os/license/license.mk
+# Startup files.
+include $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32g0xx.mk
+# HAL-OSAL files (optional).
+include $(CHIBIOS)/os/hal/hal.mk
+include $(CHIBIOS)/os/hal/ports/STM32/STM32G0xx/platform.mk
+#include $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G071RB/board.mk
+include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk
+# RTOS files (optional).
+include $(CHIBIOS)/os/nil/nil.mk
+include $(CHIBIOS)/os/common/ports/ARMv6-M/compilers/GCC/mk/port.mk
+## Auto-build files in ./source recursively.
+#include $(CHIBIOS)/tools/mk/autobuild.mk
+## Other files (optional).
+#include $(CHIBIOS)/os/test/test.mk
+#include $(CHIBIOS)/test/nil/nil_test.mk
+#include $(CHIBIOS)/test/oslib/oslib_test.mk
+
+# Define linker script file here
+LDSCRIPT= STM32G031x6.ld
+
+# C sources that can be compiled in ARM or THUMB mode depending on the global
+# setting.
+CSRC = $(ALLCSRC) \
+ board.c
+
+# C++ sources that can be compiled in ARM or THUMB mode depending on the global
+# setting.
+CPPSRC = $(ALLCPPSRC) \
+ main.cpp
+
+# List ASM source files here.
+ASMSRC = $(ALLASMSRC)
+
+# List ASM with preprocessor source files here.
+ASMXSRC = $(ALLXASMSRC)
+
+# Inclusion directories.
+INCDIR = $(CONFDIR) $(ALLINC) \
+ fpm/include
+
+# Define C warning options here.
+CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
+
+# Define C++ warning options here.
+CPPWARN = -Wall -Wextra -Wundef -Wno-volatile
+
+#
+# Project, target, sources and paths
+##############################################################################
+
+##############################################################################
+# Start of user section
+#
+
+# List all user C define here, like -D_DEBUG=1
+UDEFS =
+
+# Define ASM defines here
+UADEFS =
+
+# List all user directories here
+UINCDIR =
+
+# List the user directory to look for the libraries here
+ULIBDIR =
+
+# List all user libraries here
+ULIBS =
+
+#
+# End of user section
+##############################################################################
+
+##############################################################################
+# Common rules
+#
+
+RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk
+include $(RULESPATH)/arm-none-eabi.mk
+include $(RULESPATH)/rules.mk
+
+#
+# Common rules
+##############################################################################
+
+##############################################################################
+# Custom rules
+#
+
+#
+# Custom rules
+##############################################################################
diff --git a/STM32G031x6.ld b/STM32G031x6.ld
new file mode 100644
index 0000000..ea0c0d4
--- /dev/null
+++ b/STM32G031x6.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32G031x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 32k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/board.c b/board.c
new file mode 100644
index 0000000..b6a4567
--- /dev/null
+++ b/board.c
@@ -0,0 +1,50 @@
+/*
+ ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetIOP(STM32_GPIO_EN_MASK);
+ rccEnableIOP(STM32_GPIO_EN_MASK, true);
+}
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+/**
+ * @brief Board-specific initialization code.
+ * @note Add your board-specific code, if any.
+ */
+void boardInit(void) {
+ //palSetLineMode(LINE_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL);
+}
+
diff --git a/board.h b/board.h
new file mode 100644
index 0000000..3eecbae
--- /dev/null
+++ b/board.h
@@ -0,0 +1,105 @@
+/*
+ ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo32-G031K8 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO32_G031J6
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo32-G031J6"
+
+/*
+ * Board oscillators-related settings.
+ * NOTE: HSE not fitted.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#define STM32_LSEDRV (3U << 11U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 0U
+#endif
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32G031xx
+
+/*
+ * IO lines assignments.
+ */
+//#define LINE_LED_GREEN PAL_LINE(GPIOA, 12U)
+
+#define LINE_I2S_SD PAL_LINE(GPIOA, 12U) // or PB5
+#define LINE_I2S_WS PAL_LINE(GPIOB, 0U)
+#define LINE_I2S_CK PAL_LINE(GPIOA, 1U)
+
+#define LINE_USART2_TX PAL_LINE(GPIOA, 14U)
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/cfg/chconf.h b/cfg/chconf.h
new file mode 100644
index 0000000..8b143c3
--- /dev/null
+++ b/cfg/chconf.h
@@ -0,0 +1,480 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file nil/templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup NIL_CONFIG
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_NIL_CONF_
+#define _CHIBIOS_NIL_CONF_VER_4_0_
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Maximum number of user threads in the application.
+ * @note This number is not inclusive of the idle thread which is
+ * implicitly handled.
+ * @note Set this value to be exactly equal to the number of threads you
+ * will use or you would be wasting RAM and cycles.
+ * @note This values also defines the number of available priorities
+ * (0..CH_CFG_MAX_THREADS-1).
+ */
+#if !defined(CH_CFG_MAX_THREADS)
+#define CH_CFG_MAX_THREADS 2
+#endif
+
+/**
+ * @brief Auto starts threads when @p chSysInit() is invoked.
+ */
+#if !defined(CH_CFG_AUTOSTART_THREADS)
+#define CH_CFG_AUTOSTART_THREADS TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name System timer settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#if !defined(CH_CFG_ST_RESOLUTION)
+#define CH_CFG_ST_RESOLUTION 32
+#endif
+
+/**
+ * @brief System tick frequency.
+ * @note This value together with the @p CH_CFG_ST_RESOLUTION
+ * option defines the maximum amount of time allowed for
+ * timeouts.
+ */
+#if !defined(CH_CFG_ST_FREQUENCY)
+#define CH_CFG_ST_FREQUENCY 1000
+#endif
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#if !defined(CH_CFG_ST_TIMEDELTA)
+#define CH_CFG_ST_TIMEDELTA 2
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_WAITEXIT)
+#define CH_CFG_USE_WAITEXIT TRUE
+#endif
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_SEMAPHORES)
+#define CH_CFG_USE_SEMAPHORES TRUE
+#endif
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note Feature not currently implemented.
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_CFG_USE_MUTEXES)
+#define CH_CFG_USE_MUTEXES FALSE
+#endif
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_EVENTS)
+#define CH_CFG_USE_EVENTS FALSE
+#endif
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MESSAGES)
+#define CH_CFG_USE_MESSAGES FALSE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name OSLIB options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#if !defined(CH_CFG_USE_MAILBOXES)
+#define CH_CFG_USE_MAILBOXES FALSE
+#endif
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MEMCORE)
+#define CH_CFG_USE_MEMCORE FALSE
+#endif
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#if !defined(CH_CFG_MEMCORE_SIZE)
+#define CH_CFG_MEMCORE_SIZE 0
+#endif
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_HEAP)
+#define CH_CFG_USE_HEAP FALSE
+#endif
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MEMPOOLS)
+#define CH_CFG_USE_MEMPOOLS FALSE
+#endif
+
+/**
+ * @brief Objects FIFOs APIs.
+ * @details If enabled then the objects FIFOs APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_OBJ_FIFOS)
+#define CH_CFG_USE_OBJ_FIFOS FALSE
+#endif
+
+/**
+ * @brief Pipes APIs.
+ * @details If enabled then the pipes APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_PIPES)
+#define CH_CFG_USE_PIPES FALSE
+#endif
+
+/**
+ * @brief Objects Caches APIs.
+ * @details If enabled then the objects caches APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_OBJ_CACHES)
+#define CH_CFG_USE_OBJ_CACHES FALSE
+#endif
+
+/**
+ * @brief Delegate threads APIs.
+ * @details If enabled then the delegate threads APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_DELEGATES)
+#define CH_CFG_USE_DELEGATES FALSE
+#endif
+
+/**
+ * @brief Jobs Queues APIs.
+ * @details If enabled then the jobs queues APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_JOBS)
+#define CH_CFG_USE_JOBS FALSE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Objects factory options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Objects Factory APIs.
+ * @details If enabled then the objects factory APIs are included in the
+ * kernel.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_CFG_USE_FACTORY)
+#define CH_CFG_USE_FACTORY FALSE
+#endif
+
+/**
+ * @brief Maximum length for object names.
+ * @details If the specified length is zero then the name is stored by
+ * pointer but this could have unintended side effects.
+ */
+#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
+#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
+#endif
+
+/**
+ * @brief Enables the registry of generic objects.
+ */
+#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
+#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
+#endif
+
+/**
+ * @brief Enables factory for generic buffers.
+ */
+#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
+#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
+#endif
+
+/**
+ * @brief Enables factory for semaphores.
+ */
+#if !defined(CH_CFG_FACTORY_SEMAPHORES)
+#define CH_CFG_FACTORY_SEMAPHORES TRUE
+#endif
+
+/**
+ * @brief Enables factory for mailboxes.
+ */
+#if !defined(CH_CFG_FACTORY_MAILBOXES)
+#define CH_CFG_FACTORY_MAILBOXES TRUE
+#endif
+
+/**
+ * @brief Enables factory for objects FIFOs.
+ */
+#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
+#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
+#endif
+
+/**
+ * @brief Enables factory for Pipes.
+ */
+#if !defined(CH_CFG_FACTORY_PIPES)
+#define CH_CFG_FACTORY_PIPES TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note Feature not currently implemented.
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_STATISTICS)
+#define CH_DBG_STATISTICS FALSE
+#endif
+
+/**
+ * @brief Debug option, system state check.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_SYSTEM_STATE_CHECK)
+#define CH_DBG_SYSTEM_STATE_CHECK FALSE
+#endif
+
+/**
+ * @brief Debug option, parameters checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_CHECKS)
+#define CH_DBG_ENABLE_CHECKS FALSE
+#endif
+
+/**
+ * @brief System assertions.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_ASSERTS)
+#define CH_DBG_ENABLE_ASSERTS FALSE
+#endif
+
+/**
+ * @brief Stack check.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_STACK_CHECK)
+#define CH_DBG_ENABLE_STACK_CHECK FALSE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System initialization hook.
+ */
+#define CH_CFG_SYSTEM_INIT_HOOK() { \
+}
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXT_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ */
+#define CH_CFG_THREAD_EXT_INIT_HOOK(tr) { \
+ /* Add custom threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) {}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ asm("wfi"); \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+}
+
+/**
+ * @brief System halt hook.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in nilcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/cfg/halconf.h b/cfg/halconf.h
new file mode 100644
index 0000000..3a05139
--- /dev/null
+++ b/cfg/halconf.h
@@ -0,0 +1,553 @@
+/*
+ ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef HALCONF_H
+#define HALCONF_H
+
+#define _CHIBIOS_HAL_CONF_
+#define _CHIBIOS_HAL_CONF_VER_8_4_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the cryptographic subsystem.
+ */
+#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__)
+#define HAL_USE_CRY FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EFlash subsystem.
+ */
+#if !defined(HAL_USE_EFL) || defined(__DOXYGEN__)
+#define HAL_USE_EFL FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S TRUE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL TRUE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SIO subsystem.
+ */
+#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__)
+#define HAL_USE_SIO FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the TRNG subsystem.
+ */
+#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__)
+#define HAL_USE_TRNG FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB FALSE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/**
+ * @brief Enables the WSPI subsystem.
+ */
+#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__)
+#define HAL_USE_WSPI FALSE
+#endif
+
+/*===========================================================================*/
+/* PAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__)
+#define PAL_USE_CALLBACKS FALSE
+#endif
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
+#define PAL_USE_WAIT FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/**
+ * @brief Enforces the driver to use direct callbacks rather than OSAL events.
+ */
+#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__)
+#define CAN_ENFORCE_USE_CALLBACKS FALSE
+#endif
+
+/*===========================================================================*/
+/* CRY driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the SW fall-back of the cryptographic driver.
+ * @details When enabled, this option, activates a fall-back software
+ * implementation for algorithms not supported by the underlying
+ * hardware.
+ * @note Fall-back implementations may not be present for all algorithms.
+ */
+#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__)
+#define HAL_CRY_USE_FALLBACK FALSE
+#endif
+
+/**
+ * @brief Makes the driver forcibly use the fall-back implementations.
+ */
+#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__)
+#define HAL_CRY_ENFORCE_FALLBACK FALSE
+#endif
+
+/*===========================================================================*/
+/* DAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
+#define DAC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define DAC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the zero-copy API.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Timeout before assuming a failure while waiting for card idle.
+ * @note Time is in milliseconds.
+ */
+#if !defined(MMC_IDLE_TIMEOUT_MS) || defined(__DOXYGEN__)
+#define MMC_IDLE_TIMEOUT_MS 1000
+#endif
+
+/**
+ * @brief Mutual exclusion on the SPI bus.
+ */
+#if !defined(MMC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define MMC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/**
+ * @brief OCR initialization constant for V20 cards.
+ */
+#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__)
+#define SDC_INIT_OCR_V20 0x50FF8000U
+#endif
+
+/**
+ * @brief OCR initialization constant for non-V20 cards.
+ */
+#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__)
+#define SDC_INIT_OCR 0x80100000U
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 115200
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 16 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SIO driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SIO_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SIO_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Support for thread synchronization API.
+ */
+#if !defined(SIO_USE_SYNCHRONIZATION) || defined(__DOXYGEN__)
+#define SIO_USE_SYNCHRONIZATION TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 256 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/**
+ * @brief Serial over USB number of buffers.
+ * @note The default is 2 buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_NUMBER 2
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Inserts an assertion on function errors before returning.
+ */
+#if !defined(SPI_USE_ASSERT_ON_ERROR) || defined(__DOXYGEN__)
+#define SPI_USE_ASSERT_ON_ERROR TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/**
+ * @brief Handling method for SPI CS line.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__)
+#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
+#endif
+
+/*===========================================================================*/
+/* UART driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
+#define UART_USE_WAIT FALSE
+#endif
+
+/**
+ * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define UART_USE_MUTUAL_EXCLUSION FALSE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT FALSE
+#endif
+
+/*===========================================================================*/
+/* WSPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__)
+#define WSPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define WSPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+#endif /* HALCONF_H */
+
+/** @} */
diff --git a/cfg/mcuconf.h b/cfg/mcuconf.h
new file mode 100644
index 0000000..6e9c549
--- /dev/null
+++ b/cfg/mcuconf.h
@@ -0,0 +1,235 @@
+/*
+ ChibiOS - Copyright (C) 2006..2020 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32G0xx drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the whole
+ * driver is enabled in halconf.h.
+ *
+ * IRQ priorities:
+ * 3...0 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...3 Lowest...Highest.
+ */
+
+#ifndef MCUCONF_H
+#define MCUCONF_H
+
+#define STM32G0xx_MCUCONF
+#define STM32G031_MCUCONF
+#define STM32G041_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+#define STM32_NO_INIT FALSE
+#define STM32_CLOCK_DYNAMIC FALSE
+#define STM32_VOS STM32_VOS_RANGE2
+#define STM32_PWR_CR2 (STM32_PVDRT_LEV0 | STM32_PVDFT_LEV0 | STM32_PVDE_DISABLED)
+#define STM32_PWR_CR3 (PWR_CR3_EIWUL)
+#define STM32_PWR_CR4 (0U)
+#define STM32_PWR_PUCRA (0U)
+#define STM32_PWR_PDCRA (0U)
+#define STM32_PWR_PUCRB (0U)
+#define STM32_PWR_PDCRB (0U)
+#define STM32_PWR_PUCRC (0U)
+#define STM32_PWR_PDCRC (0U)
+#define STM32_PWR_PUCRD (0U)
+#define STM32_PWR_PDCRD (0U)
+#define STM32_PWR_PUCRF (0U)
+#define STM32_PWR_PDCRF (0U)
+#define STM32_HSIDIV_VALUE 1
+#define STM32_HSI16_ENABLED TRUE
+#define STM32_HSE_ENABLED FALSE
+#define STM32_LSI_ENABLED FALSE
+#define STM32_LSE_ENABLED FALSE
+#define STM32_SW STM32_SW_HSISYS
+#define STM32_PLLSRC STM32_PLLSRC_NOCLOCK
+#define STM32_PLLM_VALUE 2
+#define STM32_PLLN_VALUE 8
+#define STM32_PLLP_VALUE 4
+#define STM32_PLLQ_VALUE 4
+#define STM32_PLLR_VALUE 4
+#define STM32_HPRE STM32_HPRE_DIV1
+#define STM32_PPRE STM32_PPRE_DIV1
+#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
+#define STM32_MCOPRE STM32_MCOPRE_DIV1
+#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK
+
+/*
+ * Peripherals clocks and sources.
+ */
+#define STM32_USART1SEL STM32_USART1SEL_PCLK
+#define STM32_USART2SEL STM32_USART2SEL_PCLK
+#define STM32_LPUART1SEL STM32_LPUART1SEL_PCLK
+#define STM32_I2C1SEL STM32_I2C1SEL_PCLK
+#define STM32_I2S1SEL STM32_I2S1SEL_HSI16
+#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK
+#define STM32_TIM1SEL STM32_TIM1SEL_TIMPCLK
+#define STM32_RNGSEL STM32_RNGSEL_HSI16
+#define STM32_RNGDIV_VALUE 1
+#define STM32_ADCSEL STM32_ADCSEL_SYSCLK
+#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK
+
+/*
+ * Shared IRQ settings.
+ */
+#define STM32_IRQ_EXTI0_1_PRIORITY 3
+#define STM32_IRQ_EXTI2_3_PRIORITY 3
+#define STM32_IRQ_EXTI4_15_PRIORITY 3
+#define STM32_IRQ_EXTI1921_PRIORITY 3
+
+#define STM32_IRQ_USART1_PRIORITY 2
+#define STM32_IRQ_USART2_PRIORITY 2
+#define STM32_IRQ_LPUART1_PRIORITY 2
+
+#define STM32_IRQ_TIM1_UP_PRIORITY 1
+#define STM32_IRQ_TIM1_CC_PRIORITY 1
+#define STM32_IRQ_TIM2_PRIORITY 1
+#define STM32_IRQ_TIM3_PRIORITY 1
+#define STM32_IRQ_TIM14_PRIORITY 1
+#define STM32_IRQ_TIM16_PRIORITY 1
+#define STM32_IRQ_TIM17_PRIORITY 1
+
+/*
+ * ADC driver system settings.
+ */
+#define STM32_ADC_USE_ADC1 FALSE
+#define STM32_ADC_ADC1_CFGR2 ADC_CFGR2_CKMODE_ADCCLK
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2
+#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_ADC_PRESCALER_VALUE 2
+
+/*
+ * GPT driver system settings.
+ */
+#define STM32_GPT_USE_TIM1 FALSE
+#define STM32_GPT_USE_TIM2 FALSE
+#define STM32_GPT_USE_TIM3 FALSE
+#define STM32_GPT_USE_TIM14 FALSE
+#define STM32_GPT_USE_TIM16 FALSE
+#define STM32_GPT_USE_TIM17 FALSE
+
+/*
+ * I2C driver system settings.
+ */
+#define STM32_I2C_USE_I2C1 FALSE
+#define STM32_I2C_USE_I2C2 FALSE
+#define STM32_I2C_BUSY_TIMEOUT 50
+#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_I2C_I2C1_IRQ_PRIORITY 3
+#define STM32_I2C_I2C2_IRQ_PRIORITY 3
+#define STM32_I2C_I2C1_DMA_PRIORITY 3
+#define STM32_I2C_I2C2_DMA_PRIORITY 3
+#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+
+/*
+ * ICU driver system settings.
+ */
+#define STM32_ICU_USE_TIM1 FALSE
+#define STM32_ICU_USE_TIM2 FALSE
+#define STM32_ICU_USE_TIM3 FALSE
+
+/*
+ * PWM driver system settings.
+ */
+#define STM32_PWM_USE_TIM1 FALSE
+#define STM32_PWM_USE_TIM2 FALSE
+#define STM32_PWM_USE_TIM3 FALSE
+#define STM32_PWM_USE_TIM14 FALSE
+#define STM32_PWM_USE_TIM16 FALSE
+#define STM32_PWM_USE_TIM17 FALSE
+
+/*
+ * RTC driver system settings.
+ */
+#define STM32_RTC_PRESA_VALUE 32
+#define STM32_RTC_PRESS_VALUE 1024
+#define STM32_RTC_CR_INIT 0
+#define STM32_RTC_TAMPCR_INIT 0
+
+/*
+ * SERIAL driver system settings.
+ */
+#define STM32_SERIAL_USE_USART1 FALSE
+#define STM32_SERIAL_USE_USART2 TRUE
+#define STM32_SERIAL_USE_LPUART1 FALSE
+
+/*
+ * SIO driver system settings.
+ */
+#define STM32_SIO_USE_USART1 FALSE
+#define STM32_SIO_USE_USART2 FALSE
+#define STM32_SIO_USE_LPUART1 FALSE
+
+/*
+ * SPI driver system settings.
+ */
+#define STM32_SPI_USE_SPI1 FALSE
+#define STM32_SPI_USE_SPI2 FALSE
+#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_SPI_SPI1_DMA_PRIORITY 1
+#define STM32_SPI_SPI2_DMA_PRIORITY 1
+#define STM32_SPI_SPI1_IRQ_PRIORITY 2
+#define STM32_SPI_SPI2_IRQ_PRIORITY 2
+#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+
+#define STM32_I2S_USE_SPI1 TRUE
+#define STM32_I2S_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_I2S_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_I2S_SPI1_IRQ_PRIORITY 2
+
+/*
+ * ST driver system settings.
+ */
+#define STM32_ST_IRQ_PRIORITY 2
+#define STM32_ST_USE_TIMER 2
+
+/*
+ * TRNG driver system settings.
+ * NOTE: STM32G041 only.
+ */
+#define STM32_TRNG_USE_RNG1 FALSE
+
+/*
+ * UART driver system settings.
+ */
+#define STM32_UART_USE_USART1 FALSE
+#define STM32_UART_USE_USART2 FALSE
+#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID_ANY
+#define STM32_UART_USART1_DMA_PRIORITY 0
+#define STM32_UART_USART2_DMA_PRIORITY 0
+#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+
+/*
+ * WDG driver system settings.
+ */
+#define STM32_WDG_USE_IWDG FALSE
+
+#endif /* MCUCONF_H */
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..5151e33
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,124 @@
+#include "hal.h"
+#include "ch.h"
+#include "sos-iir-filter.h"
+
+#include <algorithm>
+#include <array>
+#include <cstring>
+#include <ranges>
+
+static constexpr auto& WEIGHTING = A_weighting;
+static constexpr auto& MIC_EQUALIZER = SPH0645LM4H_B_RB;
+static constexpr sos_t MIC_OFFSET_DB ( 0.f); // Linear offset
+static constexpr sos_t MIC_SENSITIVITY (-26.f); // dBFS value expected at MIC_REF_DB
+static constexpr sos_t MIC_REF_DB ( 94.f); // dB where sensitivity is specified
+static constexpr sos_t MIC_OVERLOAD_DB (120.f); // dB - Acoustic overload point
+static constexpr sos_t MIC_NOISE_DB ( 29.f); // dB - Noise floor
+static constexpr auto MIC_BITS = 16u; // SPH0645 is actually 18 bits
+static constexpr auto SAMPLE_RATE = 32000u;
+
+static constexpr unsigned I2S_BUFSIZ = 512; // was 1024
+static constexpr unsigned I2S_STRIDE = 16; // was 8
+
+// Calculate reference amplitude value at compile time
+static const auto MIC_REF_AMPL = fpm::pow(sos_t(10), MIC_SENSITIVITY / 20) *
+ ((1 << (MIC_BITS - 1)) - 1);
+
+static SEMAPHORE_DECL(i2sReady, 0);
+static THD_WORKING_AREA(waThread1, 128);
+static std::array<uint32_t, I2S_BUFSIZ> i2sBuffer;
+static sos_t Leq_sum_sqr (0);
+static unsigned Leq_samples = 0;
+
+static THD_FUNCTION(Thread1, arg);
+static void i2sCallback(I2SDriver *i2s);
+
+static constexpr auto I2SPRval = SAMPLE_RATE * 64 / 1000 / 1024 * 2;
+static constexpr I2SConfig i2sConfig = {
+ /* TX buffer */ NULL,
+ /* RX buffer */ i2sBuffer.data(),
+ /* Size */ i2sBuffer.size(),
+ /* Callback */ i2sCallback,
+ /* I2SCFGR */ (3 << SPI_I2SCFGR_I2SCFG_Pos) | // Master receive
+ (0 << SPI_I2SCFGR_I2SSTD_Pos) | // Philips I2S
+ (1 << SPI_I2SCFGR_DATLEN_Pos) | // 24-bit
+ SPI_I2SCFGR_CHLEN, // 32-bit frame
+ /* I2SPR */ I2SPRval | (((I2SPRval / 2) & 1) ? SPI_I2SPR_ODD : 0)
+};
+
+THD_TABLE_BEGIN
+ THD_TABLE_THREAD(0, "blinker1", waThread1, Thread1, NULL)
+THD_TABLE_END
+
+int main(void)
+{
+ halInit();
+ chSysInit();
+ for (;;)
+ asm("wfi");
+}
+
+THD_FUNCTION(Thread1, arg)
+{
+ (void)arg;
+
+ chThdSleepMilliseconds(2000);
+
+ palSetPadMode(GPIOF, 2, PAL_MODE_UNCONNECTED);
+ palSetLineMode(LINE_I2S_SD, PAL_MODE_ALTERNATE(0));
+ palSetLineMode(LINE_I2S_WS, PAL_MODE_ALTERNATE(0));
+ palSetLineMode(LINE_I2S_CK, PAL_MODE_ALTERNATE(0));
+ palSetLineMode(LINE_USART2_TX, PAL_MODE_ALTERNATE(1));
+
+ sdStart(&SD2, NULL);
+ sdWrite(&SD2, (uint8_t *)"Noisemeter\n", 11);
+ chThdSleepMilliseconds(100);
+
+ i2sStart(&I2SD1, &i2sConfig);
+ i2sStartExchange(&I2SD1);
+
+ uint8_t strbuf[7] = { 0, 0, 0, 'd', 'B', '\n', '\0' };
+ for (;;) {
+ chSemWait(&i2sReady);
+
+ const auto Leq_RMS = fpm::sqrt(Leq_sum_sqr / Leq_samples);
+ const auto Leq_dB = MIC_OFFSET_DB + MIC_REF_DB + 20 *
+ fpm::log10(Leq_RMS / MIC_REF_AMPL);
+ Leq_sum_sqr = sos_t(0);
+ Leq_samples = 0;
+
+ auto n = std::clamp(static_cast<int32_t>(Leq_dB), 0l, 999l);
+ strbuf[2] = n % 10 + '0'; n /= 10;
+ strbuf[1] = n % 10 + '0'; n /= 10;
+ strbuf[0] = n ? n + '0' : ' ';
+ sdWrite(&SD2, strbuf, sizeof(strbuf));
+ }
+}
+
+void i2sCallback(I2SDriver *i2s)
+{
+ // Note: samples come in as 16-bit big-endian, so for simplicity we just
+ // take the "high" 16-bits of valid data and drop the rest. Mic is
+ // technically 18-bit, so we are losing some precision.
+
+ const auto halfsize = i2sBuffer.size() / 2;
+ const auto offset = i2sIsBufferComplete(i2s) ? halfsize : 0;
+ auto samples = reinterpret_cast<sos_t *>(i2sBuffer.data() + offset);
+ std::ranges::copy(
+ std::views::counted(i2sBuffer.begin() + offset, halfsize)
+ | std::ranges::views::stride(2 * I2S_STRIDE)
+ | std::views::transform([](auto s) { return sos_t((int16_t)s); }),
+ samples);
+ auto samps = std::views::counted(samples, halfsize / (2 * I2S_STRIDE));
+
+ // Accumulate Leq sum
+ MIC_EQUALIZER.filter(samps);
+ Leq_sum_sqr += WEIGHTING.filter_sum_sqr(samps);
+ Leq_samples += samps.size();
+
+ // Wakeup main thread for dB calculation every second
+ if (Leq_samples >= 2 * SAMPLE_RATE / I2S_STRIDE) {
+ chSemSignalI(&i2sReady);
+ }
+}
+
diff --git a/sos-iir-filter.h b/sos-iir-filter.h
new file mode 100644
index 0000000..cc90b35
--- /dev/null
+++ b/sos-iir-filter.h
@@ -0,0 +1,128 @@
+/*
+ * ESP32 Second-Order Sections IIR Filter implementation
+ *
+ * (c)2019 Ivan Kostoski
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef SOS_IIR_FILTER_H
+#define SOS_IIR_FILTER_H
+
+#include <algorithm>
+#include <array>
+#include <cstdint>
+#include <ranges>
+#include <utility>
+
+#include <cmath>
+namespace fpm = std;
+using sos_t = float;
+//#include <fpm/math.hpp>
+//using sos_t = fpm::fixed_16_16;
+
+struct SOS_Coefficients {
+ sos_t b1;
+ sos_t b2;
+ sos_t a1;
+ sos_t a2;
+};
+
+struct SOS_Delay_State {
+ sos_t w0;
+ sos_t w1;
+};
+
+/**
+ * Envelops above asm functions into C++ class
+ */
+template<std::size_t N>
+struct SOS_IIR_Filter {
+ const sos_t gain;
+ std::array<SOS_Coefficients, N> sos;
+ std::array<SOS_Delay_State, N> w;
+
+ // Template constructor for const filter declaration
+ constexpr SOS_IIR_Filter(const sos_t gain, const SOS_Coefficients (&_sos)[N]):
+ gain(gain)
+ {
+ std::copy(_sos, _sos + N, sos.begin());
+ }
+
+ void filter(auto samples) {
+ // Apply all but last Second-Order-Section
+ for ([[maybe_unused]] auto _ : std::views::zip_transform(
+ [](auto samps, const auto& coeffs, auto& ww) {
+ // Assumes a0 and b0 coefficients are one (1.0)
+ for (auto& s : samps) {
+ auto f6 = s + coeffs.a1 * ww.w0 + coeffs.a2 * ww.w1;
+ s = f6 + coeffs.b1 * ww.w0 + coeffs.b2 * ww.w1;
+ ww.w1 = std::exchange(ww.w0, f6);
+ }
+ return 0;
+ },
+ std::views::repeat(samples, N), sos, w)) {}
+ }
+
+ sos_t filter_sum_sqr(auto samples) {
+ filter(samples);
+ return std::ranges::fold_left(samples, sos_t(0),
+ [this](auto a, auto b) { return a + b * gain * b * gain; });
+ }
+};
+
+#endif // SOS_IIR_FILTER_H
+
+// Knowles SPH0645LM4H-B, rev. B
+// https://cdn-shop.adafruit.com/product-files/3421/i2S+Datasheet.PDF
+// B ~= [1.001234, -1.991352, 0.990149]
+// A ~= [1.0, -1.993853, 0.993863]
+// With additional DC blocking component
+SOS_IIR_Filter SPH0645LM4H_B_RB = {
+ /* gain: */ sos_t(1.00123377961525),
+ /* sos: */ { // Second-Order Sections {b1, b2, -a1, -a2}
+ { sos_t(-1.0), sos_t(0.0),
+ sos_t(+0.9992), sos_t(0) }, // DC blocker, a1 = -0.9992
+ { sos_t(-1.988897663539382), sos_t(+0.988928479008099),
+ sos_t(+1.993853376183491), sos_t(-0.993862821429572) } }
+};
+
+//
+// A-weighting IIR Filter, Fs = 48KHz
+// (By Dr. Matt L., Source: https://dsp.stackexchange.com/a/36122)
+// B = [0.169994948147430, 0.280415310498794, -1.120574766348363, 0.131562559965936, 0.974153561246036, -0.282740857326553, -0.152810756202003]
+// A = [1.0, -2.12979364760736134, 0.42996125885751674, 1.62132698199721426, -0.96669962900852902, 0.00121015844426781, 0.04400300696788968]
+SOS_IIR_Filter A_weighting = {
+ /* gain: */ sos_t(0.169994948147430),
+ /* sos: */ { // Second-Order Sections {b1, b2, -a1, -a2}
+ { sos_t(-2.00026996133106), sos_t(+1.00027056142719),
+ sos_t(-1.060868438509278), sos_t(-0.163987445885926) },
+ { sos_t(+4.35912384203144), sos_t(+3.09120265783884),
+ sos_t(+1.208419926363593), sos_t(-0.273166998428332) },
+ { sos_t(-0.70930303489759), sos_t(-0.29071868393580),
+ sos_t(+1.982242159753048), sos_t(-0.982298594928989) } }
+};
+
+////
+//// C-weighting IIR Filter, Fs = 48KHz
+//// Designed by invfreqz curve-fitting, see respective .m file
+//// B = [-0.49164716933714026, 0.14844753846498662, 0.74117815661529129, -0.03281878334039314, -0.29709276192593875, -0.06442545322197900, -0.00364152725482682]
+//// A = [1.0, -1.0325358998928318, -0.9524000181023488, 0.8936404694728326 0.2256286147169398 -0.1499917107550188, 0.0156718181681081]
+//SOS_IIR_Filter C_weighting = {
+// gain: -0.491647169337140,
+// sos: {
+// { +1.4604385758204708, +0.5275070373815286, +1.9946144559930252, -0.9946217070140883 },
+// { +0.2376222404939509, +0.0140411206016894, -1.3396585608422749, -0.4421457807694559 },
+// { -2.0000000000000000, +1.0000000000000000, +0.3775800047420818, -0.0356365756680430 } }
+//};