From 66e18ed24811e60428d29dc256d0c2fa6a927cca Mon Sep 17 00:00:00 2001 From: Mohamed Salem Date: Mon, 13 Apr 2026 03:55:25 +0200 Subject: [PATCH] Extract reusable components into git submodules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit STD_TYPES, MCU_UART, MCU_USB, MCU_PIO, HAL_COM, HAL_LED moved to separate repos under common/ as git submodules. Each submodule ships with default config (cfg/) that projects can override. color_switcher/src/ now contains only project-specific components (APP_CLSW, SYS_ECU). CMake sources_config references common/ via COMMON_DIR. Docker volume mounts ../common:/common so the container sees the submodules. Build verified — zero errors. --- .gitmodules | 18 + .../cmake/cmake_config/mcu_config.cmake | 2 +- .../cmake/cmake_config/sources_config.cmake | 85 ++-- color_switcher/docker-compose.yml | 8 +- color_switcher/src/HAL_COM/cfg/HAL_COM_cfg.c | 106 ----- color_switcher/src/HAL_COM/cfg/HAL_COM_cfg.h | 39 -- color_switcher/src/HAL_COM/inc/HAL_COM.h | 151 ------- color_switcher/src/HAL_COM/prg/HAL_COM_prg.c | 106 ----- color_switcher/src/HAL_COM/prg/HAL_COM_priv.h | 32 -- color_switcher/src/HAL_LED/cfg/HAL_LED_cfg.c | 19 - color_switcher/src/HAL_LED/cfg/HAL_LED_cfg.h | 46 -- color_switcher/src/HAL_LED/inc/HAL_LED.h | 70 --- color_switcher/src/HAL_LED/prg/HAL_LED_prg.c | 117 ----- color_switcher/src/HAL_LED/prg/HAL_LED_priv.h | 51 --- color_switcher/src/MCU_PIO/cfg/MCU_PIO_cfg.c | 53 --- color_switcher/src/MCU_PIO/cfg/MCU_PIO_cfg.h | 40 -- color_switcher/src/MCU_PIO/inc/MCU_PIO.h | 107 ----- color_switcher/src/MCU_PIO/pio/ws2812.pio | 73 --- color_switcher/src/MCU_PIO/prg/MCU_PIO_prg.c | 115 ----- color_switcher/src/MCU_PIO/prg/MCU_PIO_priv.h | 34 -- .../src/MCU_UART/cfg/MCU_UART_cfg.c | 26 -- .../src/MCU_UART/cfg/MCU_UART_cfg.h | 51 --- color_switcher/src/MCU_UART/inc/MCU_UART.h | 124 ------ .../src/MCU_UART/prg/MCU_UART_prg.c | 421 ------------------ .../src/MCU_UART/prg/MCU_UART_priv.h | 34 -- color_switcher/src/MCU_USB/cfg/MCU_USB_cfg.c | 14 - color_switcher/src/MCU_USB/cfg/MCU_USB_cfg.h | 86 ---- color_switcher/src/MCU_USB/inc/MCU_USB.h | 68 --- color_switcher/src/MCU_USB/prg/MCU_USB_prg.c | 229 ---------- color_switcher/src/MCU_USB/prg/MCU_USB_priv.h | 18 - color_switcher/src/STD_TYPES/inc/STD_TYPES.h | 288 ------------ common/HAL_COM | 1 + common/HAL_LED | 1 + common/MCU_PIO | 1 + common/MCU_UART | 1 + common/MCU_USB | 1 + common/STD_TYPES | 1 + 37 files changed, 73 insertions(+), 2564 deletions(-) create mode 100644 .gitmodules delete mode 100644 color_switcher/src/HAL_COM/cfg/HAL_COM_cfg.c delete mode 100644 color_switcher/src/HAL_COM/cfg/HAL_COM_cfg.h delete mode 100644 color_switcher/src/HAL_COM/inc/HAL_COM.h delete mode 100644 color_switcher/src/HAL_COM/prg/HAL_COM_prg.c delete mode 100644 color_switcher/src/HAL_COM/prg/HAL_COM_priv.h delete mode 100644 color_switcher/src/HAL_LED/cfg/HAL_LED_cfg.c delete mode 100644 color_switcher/src/HAL_LED/cfg/HAL_LED_cfg.h delete mode 100644 color_switcher/src/HAL_LED/inc/HAL_LED.h delete mode 100644 color_switcher/src/HAL_LED/prg/HAL_LED_prg.c delete mode 100644 color_switcher/src/HAL_LED/prg/HAL_LED_priv.h delete mode 100644 color_switcher/src/MCU_PIO/cfg/MCU_PIO_cfg.c delete mode 100644 color_switcher/src/MCU_PIO/cfg/MCU_PIO_cfg.h delete mode 100644 color_switcher/src/MCU_PIO/inc/MCU_PIO.h delete mode 100644 color_switcher/src/MCU_PIO/pio/ws2812.pio delete mode 100644 color_switcher/src/MCU_PIO/prg/MCU_PIO_prg.c delete mode 100644 color_switcher/src/MCU_PIO/prg/MCU_PIO_priv.h delete mode 100644 color_switcher/src/MCU_UART/cfg/MCU_UART_cfg.c delete mode 100644 color_switcher/src/MCU_UART/cfg/MCU_UART_cfg.h delete mode 100644 color_switcher/src/MCU_UART/inc/MCU_UART.h delete mode 100644 color_switcher/src/MCU_UART/prg/MCU_UART_prg.c delete mode 100644 color_switcher/src/MCU_UART/prg/MCU_UART_priv.h delete mode 100644 color_switcher/src/MCU_USB/cfg/MCU_USB_cfg.c delete mode 100644 color_switcher/src/MCU_USB/cfg/MCU_USB_cfg.h delete mode 100644 color_switcher/src/MCU_USB/inc/MCU_USB.h delete mode 100644 color_switcher/src/MCU_USB/prg/MCU_USB_prg.c delete mode 100644 color_switcher/src/MCU_USB/prg/MCU_USB_priv.h delete mode 100644 color_switcher/src/STD_TYPES/inc/STD_TYPES.h create mode 160000 common/HAL_COM create mode 160000 common/HAL_LED create mode 160000 common/MCU_PIO create mode 160000 common/MCU_UART create mode 160000 common/MCU_USB create mode 160000 common/STD_TYPES diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c44fad6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,18 @@ +[submodule "common/STD_TYPES"] + path = common/STD_TYPES + url = http://git.teqanylogix.com:3000/mohamed.salem/std_types.git +[submodule "common/MCU_UART"] + path = common/MCU_UART + url = http://git.teqanylogix.com:3000/mohamed.salem/mcu_uart.git +[submodule "common/MCU_USB"] + path = common/MCU_USB + url = http://git.teqanylogix.com:3000/mohamed.salem/mcu_usb.git +[submodule "common/MCU_PIO"] + path = common/MCU_PIO + url = http://git.teqanylogix.com:3000/mohamed.salem/mcu_pio.git +[submodule "common/HAL_COM"] + path = common/HAL_COM + url = http://git.teqanylogix.com:3000/mohamed.salem/hal_com.git +[submodule "common/HAL_LED"] + path = common/HAL_LED + url = http://git.teqanylogix.com:3000/mohamed.salem/hal_led.git diff --git a/color_switcher/cmake/cmake_config/mcu_config.cmake b/color_switcher/cmake/cmake_config/mcu_config.cmake index d1d7837..936670e 100644 --- a/color_switcher/cmake/cmake_config/mcu_config.cmake +++ b/color_switcher/cmake/cmake_config/mcu_config.cmake @@ -72,7 +72,7 @@ function(mcu_link_target target) # placed in the build directory and automatically added to the # target's include path. pico_generate_pio_header(${target} - ${PROJECT_ROOT_DIR}/src/MCU_PIO/pio/ws2812.pio) + ${PROJECT_ROOT_DIR}/../common/MCU_PIO/pio/ws2812.pio) # Route stdio over USB-CDC: the Pico will appear as a virtual serial # port on the host when plugged in, so printf/getchar are visible in diff --git a/color_switcher/cmake/cmake_config/sources_config.cmake b/color_switcher/cmake/cmake_config/sources_config.cmake index 7f91e45..c073b26 100644 --- a/color_switcher/cmake/cmake_config/sources_config.cmake +++ b/color_switcher/cmake/cmake_config/sources_config.cmake @@ -5,61 +5,62 @@ # Does NOT declare the executable - the top-level CMakeLists.txt handles # add_executable() so the build target is visible in one obvious place. # +# Sources come from two locations: +# - PROJECT_ROOT_DIR/src/ project-specific components (APP, SYS) +# - COMMON_DIR/ reusable components (git submodules) +# # Exported variables: -# PROJECT_SOURCES - list of every .c file under src/ -# PROJECT_INCLUDE_DIRS - list of include paths for each component +# PROJECT_SOURCES - list of every .c file to compile +# PROJECT_INCLUDE_DIRS - list of include paths for all components # ============================================================================ -# NOTE: all source/header paths below are rooted at PROJECT_ROOT_DIR, which -# the top-level CMakeLists.txt computes as the parent of its own directory -# (i.e. one level above cmake/). We do NOT use CMAKE_SOURCE_DIR here because -# that variable points at the cmake/ folder itself, not at the project root. +# PROJECT_ROOT_DIR = one level above cmake/ (the color_switcher/ folder). +# COMMON_DIR = the shared component submodules at the repo root level. +set(COMMON_DIR "${PROJECT_ROOT_DIR}/../common") -# Recursively collect every .c file under src/. CONFIGURE_DEPENDS makes -# CMake re-check the glob on every build, so newly added .c files are -# picked up without having to manually re-run cmake. The trade-off is a -# tiny build-time stat check on each file, which is well worth it for a -# small project where we add files often. +# Collect .c files from BOTH the project's own src/ and the common submodules. +# CONFIGURE_DEPENDS re-checks on every build so new files are picked up. file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS - "${PROJECT_ROOT_DIR}/src/*.c") + "${PROJECT_ROOT_DIR}/src/*.c" + "${COMMON_DIR}/STD_TYPES/*.c" + "${COMMON_DIR}/MCU_UART/*.c" + "${COMMON_DIR}/MCU_USB/*.c" + "${COMMON_DIR}/MCU_PIO/*.c" + "${COMMON_DIR}/HAL_COM/*.c" + "${COMMON_DIR}/HAL_LED/*.c") -# Every component follows the same folder convention: -# inc/ - public API headers (safe for any other component to include) -# prg/ - private headers and implementation files (component-internal) -# cfg/ - configuration headers and constants -# -# All three are added to the include path here so #include "MCU_UART.h" -# etc. resolves regardless of which translation unit is doing the include. set(PROJECT_INCLUDE_DIRS + # ---- Common components (git submodules under pico/common/) ---- + # Shared library layer - fundamental types used by every component - ${PROJECT_ROOT_DIR}/src/STD_TYPES/inc + ${COMMON_DIR}/STD_TYPES/inc - # MCU layer - hardware abstraction for the RP2040 UART peripheral - ${PROJECT_ROOT_DIR}/src/MCU_UART/inc - ${PROJECT_ROOT_DIR}/src/MCU_UART/prg - ${PROJECT_ROOT_DIR}/src/MCU_UART/cfg + # MCU layer - hardware UART driver with DMA/ISR TX and ring buffer RX + ${COMMON_DIR}/MCU_UART/inc + ${COMMON_DIR}/MCU_UART/prg + ${COMMON_DIR}/MCU_UART/cfg - # MCU layer - PIO peripheral driver for programmable I/O state machines - ${PROJECT_ROOT_DIR}/src/MCU_PIO/inc - ${PROJECT_ROOT_DIR}/src/MCU_PIO/prg - ${PROJECT_ROOT_DIR}/src/MCU_PIO/cfg + # MCU layer - generic PIO state machine driver (WS2812 etc.) + ${COMMON_DIR}/MCU_PIO/inc + ${COMMON_DIR}/MCU_PIO/prg + ${COMMON_DIR}/MCU_PIO/cfg - # MCU layer - hardware abstraction for the RP2040 USB-CDC peripheral - # (the Pico appears as a virtual serial port on the host computer) - ${PROJECT_ROOT_DIR}/src/MCU_USB/inc - ${PROJECT_ROOT_DIR}/src/MCU_USB/prg - ${PROJECT_ROOT_DIR}/src/MCU_USB/cfg + # MCU layer - USB-CDC virtual serial port driver + ${COMMON_DIR}/MCU_USB/inc + ${COMMON_DIR}/MCU_USB/prg + ${COMMON_DIR}/MCU_USB/cfg - # HAL layer - transport-agnostic communication abstraction that - # dispatches to MCU_UART, MCU_USB, or both depending on configuration - ${PROJECT_ROOT_DIR}/src/HAL_COM/inc - ${PROJECT_ROOT_DIR}/src/HAL_COM/prg - ${PROJECT_ROOT_DIR}/src/HAL_COM/cfg + # HAL layer - transport-agnostic communication (function-pointer dispatch) + ${COMMON_DIR}/HAL_COM/inc + ${COMMON_DIR}/HAL_COM/prg + ${COMMON_DIR}/HAL_COM/cfg - # HAL layer - LED strip/pixel abstraction over PIO-based WS2812 driver - ${PROJECT_ROOT_DIR}/src/HAL_LED/inc - ${PROJECT_ROOT_DIR}/src/HAL_LED/prg - ${PROJECT_ROOT_DIR}/src/HAL_LED/cfg + # HAL layer - LED strip/pixel abstraction over PIO + ${COMMON_DIR}/HAL_LED/inc + ${COMMON_DIR}/HAL_LED/prg + ${COMMON_DIR}/HAL_LED/cfg + + # ---- Project-specific components (under color_switcher/src/) ---- # Application layer - color switcher application logic ${PROJECT_ROOT_DIR}/src/APP_CLSW/inc diff --git a/color_switcher/docker-compose.yml b/color_switcher/docker-compose.yml index d196836..25ccb62 100644 --- a/color_switcher/docker-compose.yml +++ b/color_switcher/docker-compose.yml @@ -21,11 +21,13 @@ services: # Build the image from the Dockerfile in the project root build: . - # Mount the project source code into the container's working directory. - # This lets the container read our source files and write build artifacts - # (including the .uf2 firmware file) back to the host filesystem. + # Mount project source and the shared common components into the container. + # The project mounts at /project (working directory). The common submodules + # mount at /common so the CMake COMMON_DIR path (../common relative to the + # project root) resolves correctly inside the container. volumes: - .:/project + - ../common:/common # Keep the container alive indefinitely. We intentionally do NOT run the # build on startup - `sleep infinity` lets the container stay up so it can diff --git a/color_switcher/src/HAL_COM/cfg/HAL_COM_cfg.c b/color_switcher/src/HAL_COM/cfg/HAL_COM_cfg.c deleted file mode 100644 index 72c3456..0000000 --- a/color_switcher/src/HAL_COM/cfg/HAL_COM_cfg.c +++ /dev/null @@ -1,106 +0,0 @@ -/****************************************************************************** - * File: HAL_COM_cfg.c - * Component: HAL_COM - * Description: Configuration implementation for the HAL_COM abstraction. - * Defines the channel config array that wires each HAL_COM - * channel to a specific MCU-level transport driver via function - * pointers. Also contains thin wrapper functions to normalize - * driver signatures that don't match the generic prototype - * (e.g., MCU_USB which has no instance parameter). - * - * Layer: HAL - configuration - *****************************************************************************/ - -#include "HAL_COM.h" -#include "HAL_COM_cfg.h" - -/* MCU drivers that channels may be wired to */ -#include "MCU_USB.h" -#include "MCU_UART.h" - -/* ------------------------------------------------------------------------ */ -/* SIGNATURE NORMALIZATION WRAPPERS */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Wrapper for MCU_USB_enuSendByte to match HAL_COM_tpfSendByte. - * - * MCU_USB has only one instance (the RP2040's single USB peripheral), - * so its public API does not take a u8Instance parameter. This wrapper - * adds the parameter and ignores it, making the signature compatible - * with HAL_COM's generic function pointer type. - */ -static STD_tenuResult vUsbSendByte(u8 u8Instance, u8 u8Byte) -{ - (void)u8Instance; - return MCU_USB_enuSendByte(u8Byte); -} - -/** - * @brief Wrapper for MCU_USB_enuSendBuffer to match HAL_COM_tpfSendBuffer. - * - * Same rationale as vUsbSendByte — normalizes the missing instance - * parameter so USB can be plugged into a HAL_COM channel. - */ -static STD_tenuResult vUsbSendBuffer(u8 u8Instance, const u8 *pu8Data, u16 u16Length) -{ - (void)u8Instance; - return MCU_USB_enuSendBuffer(pu8Data, u16Length); -} - -/* MCU_UART already matches the HAL_COM function pointer signatures - * (u8 u8Instance as the first parameter), so no wrapper is needed - * for TX or RX. Its functions can be assigned directly. */ - -/* --- USB RX wrappers (normalize missing instance parameter) --- */ - -static STD_tenuResult vUsbReadByte(u8 u8Instance, u8 *pu8Byte) -{ - (void)u8Instance; - return MCU_USB_enuReadByte(pu8Byte); -} - -static STD_tenuResult vUsbReadBuffer(u8 u8Instance, u8 *pu8Data, u16 u16MaxLength, u16 *pu16Read) -{ - (void)u8Instance; - return MCU_USB_enuReadBuffer(pu8Data, u16MaxLength, pu16Read); -} - -static STD_tBool vUsbIsRxDataAvailable(u8 u8Instance) -{ - (void)u8Instance; - return MCU_USB_bIsRxDataAvailable(); -} - -/* ------------------------------------------------------------------------ */ -/* CHANNEL CONFIGURATION ARRAY */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Per-channel config, indexed by HAL_COM_tenuChannel. - * - * [HAL_COM_CHANNEL_0] = USB-CDC (primary communication path). - * - * To add a UART channel: - * 1. Add HAL_COM_CHANNEL_1 to the enum in HAL_COM_cfg.h - * 2. Add an entry here with MCU_UART functions (no wrapper needed): - * [HAL_COM_CHANNEL_1] = { - * .pfSendByte = MCU_UART_enuSendByte, - * .pfSendBuffer = MCU_UART_enuSendBuffer, - * .pfReceiveByte = MCU_UART_enuReceiveByte, - * .pfIsRxDataAvailable = MCU_UART_bIsRxDataAvailable, - * .u8Instance = 0U, - * }, - */ -const HAL_COM_tstrChannelConfig HAL_COM_astrChannelConfig[HAL_COM_NUM_CHANNELS] = -{ - [HAL_COM_CHANNEL_0] = - { - .pfSendByte = vUsbSendByte, - .pfSendBuffer = vUsbSendBuffer, - .pfReadByte = vUsbReadByte, - .pfReadBuffer = vUsbReadBuffer, - .pfIsRxDataAvailable = vUsbIsRxDataAvailable, - .u8Instance = 0U, - }, -}; diff --git a/color_switcher/src/HAL_COM/cfg/HAL_COM_cfg.h b/color_switcher/src/HAL_COM/cfg/HAL_COM_cfg.h deleted file mode 100644 index 8af7c77..0000000 --- a/color_switcher/src/HAL_COM/cfg/HAL_COM_cfg.h +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - * File: HAL_COM_cfg.h - * Component: HAL_COM - * Description: Configuration header for the HAL_COM abstraction. - * Defines the communication channels and which MCU-level - * transport each one routes through via function pointers. - * Adding a new channel or swapping a transport is a config-only - * change — no code in HAL_COM_prg.c needs to be modified. - * - * Layer: HAL - configuration - *****************************************************************************/ - -#ifndef HAL_COM_CFG_H -#define HAL_COM_CFG_H - -#include "STD_TYPES.h" - -/* ------------------------------------------------------------------------ */ -/* CHANNEL ENUMERATION */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Enumeration of configured HAL_COM channels. - * - * Each channel is one logical communication path wired to a specific - * MCU-level driver. The enumerator values are used as array indices - * into HAL_COM_astrChannelConfig[]. - * - * To add a channel: add an enumerator before HAL_COM_NUM_CHANNELS, - * define its function pointer macros below, and add an entry in - * HAL_COM_cfg.c. - */ -typedef enum -{ - HAL_COM_CHANNEL_0 = 0U, /**< Primary channel (USB-CDC by default) */ - HAL_COM_NUM_CHANNELS -} HAL_COM_tenuChannel; - -#endif /* HAL_COM_CFG_H */ diff --git a/color_switcher/src/HAL_COM/inc/HAL_COM.h b/color_switcher/src/HAL_COM/inc/HAL_COM.h deleted file mode 100644 index 3b0750b..0000000 --- a/color_switcher/src/HAL_COM/inc/HAL_COM.h +++ /dev/null @@ -1,151 +0,0 @@ -/****************************************************************************** - * File: HAL_COM.h - * Component: HAL_COM - * Description: Public interface for the HAL communication abstraction layer. - * Provides a transport-agnostic, multi-channel API for sending - * and receiving bytes. Each channel is independently configured - * with function pointers to an MCU-level driver (USB, UART, - * SPI, I2C, or any future transport that matches the function - * signatures). - * - * Higher layers (e.g. APP_CLSW) call HAL_COM_* with a channel - * number and stay unaware of which physical transport is in use. - * Adding a new transport requires zero changes to this file or - * to HAL_COM_prg.c — only the config needs a new channel entry. - * - * Layer: HAL (hardware abstraction, one level above MCU drivers) - *****************************************************************************/ - -#ifndef HAL_COM_H -#define HAL_COM_H - -#include "STD_TYPES.h" -#include "HAL_COM_cfg.h" - -/* ------------------------------------------------------------------------ */ -/* TRANSPORT FUNCTION POINTER TYPES */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Generic send-byte function pointer type. - * - * Any MCU driver that can send a single byte and matches this signature - * can be plugged into a HAL_COM channel. The u8Instance parameter - * identifies the peripheral instance within that driver (e.g., UART0 - * vs UART1). Drivers that have only one instance (e.g., MCU_USB) use - * a thin wrapper that ignores the parameter. - * - * @param u8Instance Peripheral instance index within the driver. - * @param u8Byte The byte to transmit. - * @return STD_tenuResult - */ -typedef STD_tenuResult (*HAL_COM_tpfSendByte)(u8 u8Instance, u8 u8Byte); - -/** - * @brief Generic send-buffer function pointer type. - * - * Same concept as HAL_COM_tpfSendByte but for multi-byte transfers. - * - * @param u8Instance Peripheral instance index within the driver. - * @param pu8Data Pointer to the byte buffer. - * @param u16Length Number of bytes to transmit. - * @return STD_tenuResult - */ -typedef STD_tenuResult (*HAL_COM_tpfSendBuffer)(u8 u8Instance, const u8 *pu8Data, u16 u16Length); - -/** - * @brief Generic read-byte function pointer type (non-blocking). - */ -typedef STD_tenuResult (*HAL_COM_tpfReadByte)(u8 u8Instance, u8 *pu8Byte); - -/** - * @brief Generic read-buffer function pointer type (non-blocking). - */ -typedef STD_tenuResult (*HAL_COM_tpfReadBuffer)(u8 u8Instance, u8 *pu8Data, u16 u16MaxLength, u16 *pu16Read); - -/** - * @brief Generic RX-data-available check function pointer type. - */ -typedef STD_tBool (*HAL_COM_tpfIsRxDataAvailable)(u8 u8Instance); - -/* ------------------------------------------------------------------------ */ -/* CONFIGURATION STRUCTURE */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Per-channel communication configuration. - * - * One entry per HAL_COM channel, stored in HAL_COM_astrChannelConfig[]. - * The array index is the channel number passed to all public functions. - * - * Each channel is wired to exactly one MCU-level transport by holding - * function pointers to that driver's send functions + the instance index - * to pass through. To route through a different transport, just change - * the function pointers in the config — no code changes needed. - */ -typedef struct -{ - HAL_COM_tpfSendByte pfSendByte; /**< Driver's send-byte function */ - HAL_COM_tpfSendBuffer pfSendBuffer; /**< Driver's send-buffer function */ - HAL_COM_tpfReadByte pfReadByte; /**< Driver's read-byte function */ - HAL_COM_tpfReadBuffer pfReadBuffer; /**< Driver's read-buffer function */ - HAL_COM_tpfIsRxDataAvailable pfIsRxDataAvailable; /**< Driver's RX-available check */ - u8 u8Instance; /**< Peripheral instance to pass through */ -} HAL_COM_tstrChannelConfig; - -/* ------------------------------------------------------------------------ */ -/* PUBLIC API */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Initialize the HAL communication layer's own internal state. - * - * Does NOT initialize the underlying MCU drivers — SYS_ECU owns the init - * sequence and calls each driver's enuInit() before calling this. - * - * @return STD_OK on success, STD_NOK on failure. - */ -STD_tenuResult HAL_COM_enuInit(void); - -/** - * @brief Send a single byte through the specified channel. - * - * @param u8Channel Channel index (from HAL_COM_cfg.h channel enum). - * @param u8Byte The byte to transmit. - * @return STD_OK on success, STD_NOK on failure. - */ -STD_tenuResult HAL_COM_enuSendByte(u8 u8Channel, u8 u8Byte); - -/** - * @brief Send a buffer through the specified channel. - * - * The underlying driver may be blocking or non-blocking depending on the - * MCU driver wired to this channel. When non-blocking (e.g., MCU_UART - * with DMA), the caller must keep the buffer valid until the transfer - * completes. - * - * @param u8Channel Channel index. - * @param pu8Data Pointer to the byte buffer. Must not be NULL. - * @param u16Length Number of bytes to transmit. - * @return STD_OK on success, - * STD_NULL_POINTER_ERROR if pu8Data is NULL, - * STD_NOK on failure. - */ -STD_tenuResult HAL_COM_enuSendBuffer(u8 u8Channel, const u8 *pu8Data, u16 u16Length); - -/** - * @brief Read one byte from the specified channel (non-blocking). - */ -STD_tenuResult HAL_COM_enuReadByte(u8 u8Channel, u8 *pu8Byte); - -/** - * @brief Read up to u16MaxLength bytes from the specified channel (non-blocking). - */ -STD_tenuResult HAL_COM_enuReadBuffer(u8 u8Channel, u8 *pu8Data, u16 u16MaxLength, u16 *pu16Read); - -/** - * @brief Check if the specified channel has RX data available. - */ -STD_tBool HAL_COM_bIsRxDataAvailable(u8 u8Channel); - -#endif /* HAL_COM_H */ \ No newline at end of file diff --git a/color_switcher/src/HAL_COM/prg/HAL_COM_prg.c b/color_switcher/src/HAL_COM/prg/HAL_COM_prg.c deleted file mode 100644 index 271abd7..0000000 --- a/color_switcher/src/HAL_COM/prg/HAL_COM_prg.c +++ /dev/null @@ -1,106 +0,0 @@ -/****************************************************************************** - * File: HAL_COM_prg.c - * Component: HAL_COM - * Description: Program (implementation) file for the HAL_COM abstraction. - * Dispatches send operations to the MCU-level driver wired to - * each channel via function pointers in HAL_COM_astrChannelConfig. - * - * The dispatch is a single indirect call — no if/else chains, - * no transport-specific code. Adding a new transport (SPI, I2C, - * etc.) requires zero changes here — only a new config entry. - * - * Layer: HAL - *****************************************************************************/ - -#include "HAL_COM.h" -#include "HAL_COM_priv.h" -#include "HAL_COM_cfg.h" - -/* ========================================================================= */ -/* INIT */ -/* ========================================================================= */ - -STD_tenuResult HAL_COM_enuInit(void) -{ - STD_tenuResult enuResultLoc = STD_OK; - - /* HAL_COM has no internal state to set up yet. The underlying MCU - * drivers are already initialized by SYS_ECU before this function - * is called. When internal queuing or channel-level state is added, - * initialize it here. */ - - return enuResultLoc; -} - -/* ========================================================================= */ -/* SEND BYTE */ -/* ========================================================================= */ - -STD_tenuResult HAL_COM_enuSendByte(u8 u8Channel, u8 u8Byte) -{ - STD_tenuResult enuResultLoc = STD_OK; - const HAL_COM_tstrChannelConfig *pstrCfgLoc = &HAL_COM_astrChannelConfig[u8Channel]; - - /* Dispatch through the function pointer configured for this channel. - * The driver's instance index is passed through transparently — the - * caller never sees it. */ - enuResultLoc = pstrCfgLoc->pfSendByte(pstrCfgLoc->u8Instance, u8Byte); - - return enuResultLoc; -} - -/* ========================================================================= */ -/* SEND BUFFER */ -/* ========================================================================= */ - -STD_tenuResult HAL_COM_enuSendBuffer(u8 u8Channel, const u8 *pu8Data, u16 u16Length) -{ - STD_tenuResult enuResultLoc = STD_OK; - const HAL_COM_tstrChannelConfig *pstrCfgLoc = &HAL_COM_astrChannelConfig[u8Channel]; - - /* Dispatch through the function pointer configured for this channel. - * Null-pointer validation is handled inside the MCU driver, so we - * don't duplicate the check here. */ - enuResultLoc = pstrCfgLoc->pfSendBuffer(pstrCfgLoc->u8Instance, pu8Data, u16Length); - - return enuResultLoc; -} - -/* ========================================================================= */ -/* RECEIVE BYTE (BLOCKING) */ -/* ========================================================================= */ - -STD_tenuResult HAL_COM_enuReadByte(u8 u8Channel, u8 *pu8Byte) -{ - STD_tenuResult enuResultLoc = STD_OK; - const HAL_COM_tstrChannelConfig *pstrCfgLoc = &HAL_COM_astrChannelConfig[u8Channel]; - - enuResultLoc = pstrCfgLoc->pfReadByte(pstrCfgLoc->u8Instance, pu8Byte); - - return enuResultLoc; -} - -/* ========================================================================= */ -/* READ BUFFER (NON-BLOCKING) */ -/* ========================================================================= */ - -STD_tenuResult HAL_COM_enuReadBuffer(u8 u8Channel, u8 *pu8Data, u16 u16MaxLength, u16 *pu16Read) -{ - STD_tenuResult enuResultLoc = STD_OK; - const HAL_COM_tstrChannelConfig *pstrCfgLoc = &HAL_COM_astrChannelConfig[u8Channel]; - - enuResultLoc = pstrCfgLoc->pfReadBuffer(pstrCfgLoc->u8Instance, pu8Data, u16MaxLength, pu16Read); - - return enuResultLoc; -} - -/* ========================================================================= */ -/* RX DATA AVAILABLE CHECK */ -/* ========================================================================= */ - -STD_tBool HAL_COM_bIsRxDataAvailable(u8 u8Channel) -{ - const HAL_COM_tstrChannelConfig *pstrCfgLoc = &HAL_COM_astrChannelConfig[u8Channel]; - - return pstrCfgLoc->pfIsRxDataAvailable(pstrCfgLoc->u8Instance); -} diff --git a/color_switcher/src/HAL_COM/prg/HAL_COM_priv.h b/color_switcher/src/HAL_COM/prg/HAL_COM_priv.h deleted file mode 100644 index f6f4fce..0000000 --- a/color_switcher/src/HAL_COM/prg/HAL_COM_priv.h +++ /dev/null @@ -1,32 +0,0 @@ -/****************************************************************************** - * File: HAL_COM_priv.h - * Component: HAL_COM - * Description: Private header for the HAL_COM abstraction. - * Contains the extern declaration of the channel config array - * (only accessed internally by _prg.c) and any other private - * definitions. - * - * Layer: HAL - internal use only - *****************************************************************************/ - -#ifndef HAL_COM_PRIV_H -#define HAL_COM_PRIV_H - -#include "HAL_COM.h" -#include "HAL_COM_cfg.h" - -/* ------------------------------------------------------------------------ */ -/* CONFIG ARRAY (EXTERN) */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Channel configuration array indexed by HAL_COM_tenuChannel. - * - * Defined in HAL_COM_cfg.c. Each entry holds function pointers to an - * MCU-level driver's send functions + the instance index to pass through. - * Only HAL_COM_prg.c accesses this — no external component should read - * the raw config. - */ -extern const HAL_COM_tstrChannelConfig HAL_COM_astrChannelConfig[HAL_COM_NUM_CHANNELS]; - -#endif /* HAL_COM_PRIV_H */ \ No newline at end of file diff --git a/color_switcher/src/HAL_LED/cfg/HAL_LED_cfg.c b/color_switcher/src/HAL_LED/cfg/HAL_LED_cfg.c deleted file mode 100644 index 2e90e93..0000000 --- a/color_switcher/src/HAL_LED/cfg/HAL_LED_cfg.c +++ /dev/null @@ -1,19 +0,0 @@ -/****************************************************************************** - * File: HAL_LED_cfg.c - * Component: HAL_LED - * Description: Configuration array definition for the LED abstraction. - * - * Layer: HAL - configuration - *****************************************************************************/ - -#include "HAL_LED.h" -#include "HAL_LED_cfg.h" - -const HAL_LED_tstrConfig HAL_LED_astrConfig[HAL_LED_NUM_INSTANCES] = -{ - [HAL_LED_INSTANCE_ONBOARD] = - { - .u8NumLeds = HAL_LED_ONBOARD_NUM_LEDS, - .u8PioInstance = HAL_LED_ONBOARD_PIO_INSTANCE, - }, -}; \ No newline at end of file diff --git a/color_switcher/src/HAL_LED/cfg/HAL_LED_cfg.h b/color_switcher/src/HAL_LED/cfg/HAL_LED_cfg.h deleted file mode 100644 index 06b1b47..0000000 --- a/color_switcher/src/HAL_LED/cfg/HAL_LED_cfg.h +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * File: HAL_LED_cfg.h - * Component: HAL_LED - * Description: Configuration header for the LED abstraction layer. - * Defines LED strip instances, maximum strip length, - * and per-instance settings. - * - * Layer: HAL - configuration - *****************************************************************************/ - -#ifndef HAL_LED_CFG_H -#define HAL_LED_CFG_H - -#include "STD_TYPES.h" - -/* ------------------------------------------------------------------------ */ -/* INSTANCE ENUMERATION */ -/* ------------------------------------------------------------------------ */ - -typedef enum -{ - HAL_LED_INSTANCE_ONBOARD = 0U, /**< Onboard WS2812B on RP2040-Zero */ - HAL_LED_NUM_INSTANCES -} HAL_LED_tenuInstance; - -/* ------------------------------------------------------------------------ */ -/* BUFFER SIZING */ -/* ------------------------------------------------------------------------ */ - -/** @brief Maximum number of LEDs any single instance can support. - * Determines the pixel buffer size in the control struct. - * Increase when adding longer strips. */ -#define HAL_LED_MAX_LEDS_PER_INSTANCE 1U - -/* ------------------------------------------------------------------------ */ -/* INSTANCE 0 (ONBOARD) CONFIGURATION */ -/* ------------------------------------------------------------------------ */ - -/** @brief Number of LEDs in the onboard strip (just 1 on the RP2040-Zero). */ -#define HAL_LED_ONBOARD_NUM_LEDS 1U - -/** @brief MCU_PIO instance index for the onboard LED. - * Maps to MCU_PIO_INSTANCE_WS2812 (defined in MCU_PIO_cfg.h). */ -#define HAL_LED_ONBOARD_PIO_INSTANCE 0U - -#endif /* HAL_LED_CFG_H */ \ No newline at end of file diff --git a/color_switcher/src/HAL_LED/inc/HAL_LED.h b/color_switcher/src/HAL_LED/inc/HAL_LED.h deleted file mode 100644 index 536194e..0000000 --- a/color_switcher/src/HAL_LED/inc/HAL_LED.h +++ /dev/null @@ -1,70 +0,0 @@ -/****************************************************************************** - * File: HAL_LED.h - * Component: HAL_LED - * Description: Public interface for the LED abstraction layer. - * Manages a pixel buffer for WS2812-style addressable LEDs - * and pushes color data through MCU_PIO. Supports indexed - * LED strips with per-pixel intensity scaling. - * - * SetColor sets one LED's color and immediately pushes the - * entire strip to the hardware — no separate Update call needed. - * - * Layer: HAL (hardware abstraction, one level above MCU drivers) - *****************************************************************************/ - -#ifndef HAL_LED_H -#define HAL_LED_H - -#include "STD_TYPES.h" - -/* ------------------------------------------------------------------------ */ -/* CONFIGURATION STRUCTURE */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Per-instance LED strip/array configuration. - * - * One entry per LED strip, stored in HAL_LED_astrConfig[]. - * The array index is the instance parameter in all public API calls. - */ -typedef struct -{ - u8 u8NumLeds; /**< Number of LEDs in this strip (1 for single LED) */ - u8 u8PioInstance; /**< MCU_PIO config index for the data output */ -} HAL_LED_tstrConfig; - -/* ------------------------------------------------------------------------ */ -/* PUBLIC API */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Initialize the LED abstraction layer. - * - * Clears the internal pixel buffer to all-off (black). Does NOT init - * MCU_PIO — SYS_ECU must call MCU_PIO_enuInit() before this. - * - * @return STD_OK on success. - */ -STD_tenuResult HAL_LED_enuInit(void); - -/** - * @brief Set the color of a single LED and push the entire strip. - * - * Scales each color channel by u8Intensity (0-255), stores the result - * in the internal pixel buffer, then immediately pushes all LEDs in - * this strip to the PIO state machine. - * - * @param u8Instance HAL_LED config instance. - * @param u8LedIndex LED position in the strip (0-based). - * @param u8Red Red intensity (0-255, before scaling). - * @param u8Green Green intensity (0-255, before scaling). - * @param u8Blue Blue intensity (0-255, before scaling). - * @param u8Intensity Global brightness scaler (0-255). 255 = full. - * @return STD_OK on success, - * STD_INDEX_OUT_OF_RANGE_ERROR if u8LedIndex >= u8NumLeds. - */ -STD_tenuResult HAL_LED_enuSetColor(u8 u8Instance, u8 u8LedIndex, - u8 u8Red, u8 u8Green, u8 u8Blue, - u8 u8Intensity); - -#endif /* HAL_LED_H */ \ No newline at end of file diff --git a/color_switcher/src/HAL_LED/prg/HAL_LED_prg.c b/color_switcher/src/HAL_LED/prg/HAL_LED_prg.c deleted file mode 100644 index 272911e..0000000 --- a/color_switcher/src/HAL_LED/prg/HAL_LED_prg.c +++ /dev/null @@ -1,117 +0,0 @@ -/****************************************************************************** - * File: HAL_LED_prg.c - * Component: HAL_LED - * Description: LED abstraction implementation. Manages a pixel buffer with - * intensity scaling and pushes color data to the hardware via - * MCU_PIO. SetColor updates one LED and immediately pushes the - * entire strip — no separate Update call needed. - * - * Layer: HAL - *****************************************************************************/ - -#include "HAL_LED.h" -#include "HAL_LED_priv.h" -#include "HAL_LED_cfg.h" - -#include "MCU_PIO.h" - -/* ------------------------------------------------------------------------ */ -/* RUNTIME STATE */ -/* ------------------------------------------------------------------------ */ - -static HAL_LED_tstrControl strControl; - -/* ------------------------------------------------------------------------ */ -/* INTERNAL HELPERS */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Push the entire pixel buffer for one instance to the PIO FIFO. - * - * Iterates through the pixel buffer, packs each pixel into a 32-bit - * GRB word (left-justified: G in [31:24], R in [23:16], B in [15:8], - * bits [7:0] unused), and sends it via MCU_PIO_vPutBlocking. - * - * @param u8Instance HAL_LED instance index. - */ -static void vPushStrip(u8 u8Instance) -{ - u8 u8PioInstLoc = HAL_LED_astrConfig[u8Instance].u8PioInstance; - u8 u8NumLedsLoc = HAL_LED_astrConfig[u8Instance].u8NumLeds; - u8 u8LedLoc; - - for (u8LedLoc = 0U; u8LedLoc < u8NumLedsLoc; u8LedLoc++) - { - HAL_LED_tstrPixel *pstrPixLoc = &strControl.astrPixels[u8Instance][u8LedLoc]; - - /* Pack RGB into bits [31:8] of the 32-bit word. - * The WS2812 variant on the RP2040-Zero uses RGB byte order - * (red first, green second, blue third) rather than the standard - * GRB. Bits [7:0] are padding (shifted out but ignored). */ - u32 u32RgbLoc = ((u32)pstrPixLoc->u8Red << 24U) - | ((u32)pstrPixLoc->u8Green << 16U) - | ((u32)pstrPixLoc->u8Blue << 8U); - - MCU_PIO_vPutBlocking(u8PioInstLoc, u32RgbLoc); - } -} - -/* ========================================================================= */ -/* INIT */ -/* ========================================================================= */ - -STD_tenuResult HAL_LED_enuInit(void) -{ - STD_tenuResult enuResultLoc = STD_OK; - u8 u8InstLoc; - u8 u8LedLoc; - - /* Clear all pixels to off (black) */ - for (u8InstLoc = 0U; u8InstLoc < (u8)HAL_LED_NUM_INSTANCES; u8InstLoc++) - { - for (u8LedLoc = 0U; u8LedLoc < HAL_LED_astrConfig[u8InstLoc].u8NumLeds; u8LedLoc++) - { - strControl.astrPixels[u8InstLoc][u8LedLoc].u8Green = 0U; - strControl.astrPixels[u8InstLoc][u8LedLoc].u8Red = 0U; - strControl.astrPixels[u8InstLoc][u8LedLoc].u8Blue = 0U; - } - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* SET COLOR */ -/* ========================================================================= */ - -STD_tenuResult HAL_LED_enuSetColor(u8 u8Instance, u8 u8LedIndex, - u8 u8Red, u8 u8Green, u8 u8Blue, - u8 u8Intensity) -{ - STD_tenuResult enuResultLoc = STD_OK; - u8 u8NumLedsLoc = HAL_LED_astrConfig[u8Instance].u8NumLeds; - - if (u8LedIndex >= u8NumLedsLoc) - { - enuResultLoc = STD_INDEX_OUT_OF_RANGE_ERROR; - } - else - { - /* Scale each channel by intensity: (channel * intensity) / 255. - * Use u16 intermediate to avoid overflow (255 * 255 = 65025, - * which fits in u16 but not u8). */ - u8 u8ScaledRLoc = (u8)(((u16)u8Red * (u16)u8Intensity) / 255U); - u8 u8ScaledGLoc = (u8)(((u16)u8Green * (u16)u8Intensity) / 255U); - u8 u8ScaledBLoc = (u8)(((u16)u8Blue * (u16)u8Intensity) / 255U); - - /* Store the scaled pixel in the buffer */ - strControl.astrPixels[u8Instance][u8LedIndex].u8Red = u8ScaledRLoc; - strControl.astrPixels[u8Instance][u8LedIndex].u8Green = u8ScaledGLoc; - strControl.astrPixels[u8Instance][u8LedIndex].u8Blue = u8ScaledBLoc; - - /* Immediately push the entire strip to the hardware */ - vPushStrip(u8Instance); - } - - return enuResultLoc; -} \ No newline at end of file diff --git a/color_switcher/src/HAL_LED/prg/HAL_LED_priv.h b/color_switcher/src/HAL_LED/prg/HAL_LED_priv.h deleted file mode 100644 index 169757e..0000000 --- a/color_switcher/src/HAL_LED/prg/HAL_LED_priv.h +++ /dev/null @@ -1,51 +0,0 @@ -/****************************************************************************** - * File: HAL_LED_priv.h - * Component: HAL_LED - * Description: Private header — pixel struct, control struct with the - * pixel buffer, and extern config array declaration. - * - * Layer: HAL - internal use only - *****************************************************************************/ - -#ifndef HAL_LED_PRIV_H -#define HAL_LED_PRIV_H - -#include "HAL_LED.h" -#include "HAL_LED_cfg.h" - -extern const HAL_LED_tstrConfig HAL_LED_astrConfig[HAL_LED_NUM_INSTANCES]; - -/* ------------------------------------------------------------------------ */ -/* PIXEL STRUCTURE */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Per-LED color data in GRB order (matching WS2812 protocol). - * - * Stored after intensity scaling has been applied, so these values - * are the actual brightnesses sent to the hardware. - */ -typedef struct -{ - u8 u8Green; - u8 u8Red; - u8 u8Blue; -} HAL_LED_tstrPixel; - -/* ------------------------------------------------------------------------ */ -/* CONTROL STRUCTURE */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Internal runtime state for all HAL_LED instances. - * - * astrPixels is a 2D array: [instance][led_index]. Each pixel holds - * the intensity-scaled GRB values ready to be packed into 32-bit words - * for the PIO FIFO. - */ -typedef struct -{ - HAL_LED_tstrPixel astrPixels[HAL_LED_NUM_INSTANCES][HAL_LED_MAX_LEDS_PER_INSTANCE]; -} HAL_LED_tstrControl; - -#endif /* HAL_LED_PRIV_H */ \ No newline at end of file diff --git a/color_switcher/src/MCU_PIO/cfg/MCU_PIO_cfg.c b/color_switcher/src/MCU_PIO/cfg/MCU_PIO_cfg.c deleted file mode 100644 index 39c6d34..0000000 --- a/color_switcher/src/MCU_PIO/cfg/MCU_PIO_cfg.c +++ /dev/null @@ -1,53 +0,0 @@ -/****************************************************************************** - * File: MCU_PIO_cfg.c - * Component: MCU_PIO - * Description: Configuration array definition for the PIO driver. - * Wires each PIO instance to its compiled program and - * program-specific init function. The WS2812 init wrapper - * adapts the auto-generated ws2812_program_init() signature - * to match the generic MCU_PIO_tpfProgramInit callback type. - * - * Layer: MCU (hardware abstraction) - configuration - *****************************************************************************/ - -#include "MCU_PIO.h" -#include "MCU_PIO_cfg.h" - -/* Auto-generated header from ws2812.pio — provides ws2812_program struct - * and ws2812_program_init() helper. Generated at build time by - * pico_generate_pio_header() in mcu_config.cmake. */ -#include "ws2812.pio.h" - -/* ------------------------------------------------------------------------ */ -/* WS2812 INIT WRAPPER */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Adapts ws2812_program_init() to the MCU_PIO_tpfProgramInit - * signature by hardcoding the WS2812 bit frequency (800 kHz). - * - * The auto-generated ws2812_program_init() takes an extra `float freq` - * parameter that is not part of the generic callback type. This wrapper - * fills it in so the generic driver can call it without knowing about - * WS2812 specifics. - */ -static void vWs2812Init(PIO pstrPio, u8 u8Sm, u8 u8Pin, u32 u32Offset) -{ - ws2812_program_init(pstrPio, (u32)u8Sm, (u32)u32Offset, (u32)u8Pin, 800000.0f); -} - -/* ------------------------------------------------------------------------ */ -/* CONFIGURATION ARRAY */ -/* ------------------------------------------------------------------------ */ - -const MCU_PIO_tstrConfig MCU_PIO_astrConfig[MCU_PIO_NUM_INSTANCES] = -{ - [MCU_PIO_INSTANCE_WS2812] = - { - .pstrPio = pio0, /* use PIO block 0 */ - .u8Sm = 0U, /* state machine 0 within pio0 */ - .u8Pin = MCU_PIO_WS2812_PIN, - .pstrProgram = &ws2812_program, - .pfProgramInit = vWs2812Init, - }, -}; diff --git a/color_switcher/src/MCU_PIO/cfg/MCU_PIO_cfg.h b/color_switcher/src/MCU_PIO/cfg/MCU_PIO_cfg.h deleted file mode 100644 index f676eda..0000000 --- a/color_switcher/src/MCU_PIO/cfg/MCU_PIO_cfg.h +++ /dev/null @@ -1,40 +0,0 @@ -/****************************************************************************** - * File: MCU_PIO_cfg.h - * Component: MCU_PIO - * Description: Configuration header for the generic PIO driver. - * Defines which PIO programs are loaded and on which - * state machines / GPIO pins they operate. - * - * Layer: MCU (hardware abstraction) - configuration - *****************************************************************************/ - -#ifndef MCU_PIO_CFG_H -#define MCU_PIO_CFG_H - -#include "STD_TYPES.h" - -/* ------------------------------------------------------------------------ */ -/* INSTANCE ENUMERATION */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Enumeration of configured PIO program instances. - * - * Each entry represents one PIO program running on one state machine. - * The enumerator value is the array index into MCU_PIO_astrConfig[]. - */ -typedef enum -{ - MCU_PIO_INSTANCE_WS2812 = 0U, /**< WS2812 LED driver on GP16 */ - MCU_PIO_NUM_INSTANCES -} MCU_PIO_tenuInstance; - -/* ------------------------------------------------------------------------ */ -/* WS2812 INSTANCE CONFIGURATION */ -/* ------------------------------------------------------------------------ */ - -/** @brief GPIO pin for the WS2812B data line. - * GP16 is the onboard WS2812B on the Waveshare RP2040-Zero. */ -#define MCU_PIO_WS2812_PIN 16U - -#endif /* MCU_PIO_CFG_H */ diff --git a/color_switcher/src/MCU_PIO/inc/MCU_PIO.h b/color_switcher/src/MCU_PIO/inc/MCU_PIO.h deleted file mode 100644 index 600a9ec..0000000 --- a/color_switcher/src/MCU_PIO/inc/MCU_PIO.h +++ /dev/null @@ -1,107 +0,0 @@ -/****************************************************************************** - * File: MCU_PIO.h - * Component: MCU_PIO - * Description: Public interface for the generic PIO driver component. - * Abstracts the RP2040's Programmable I/O hardware — loading - * PIO programs into instruction memory, configuring state - * machines, and pushing data through the TX FIFO. - * - * The driver is program-agnostic: each config entry holds a - * pointer to a compiled PIO program and a function pointer - * for the program-specific state machine init. WS2812 is one - * such program; future PIO uses (custom protocols, etc.) - * plug in the same way with zero driver code changes. - * - * Layer: MCU (hardware abstraction) - *****************************************************************************/ - -#ifndef MCU_PIO_H -#define MCU_PIO_H - -#include "STD_TYPES.h" -#include "hardware/pio.h" - -/* ------------------------------------------------------------------------ */ -/* PROGRAM INIT FUNCTION POINTER TYPE */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Callback type for program-specific state machine configuration. - * - * Each PIO program has its own pin mapping, shift config, clock divider, - * etc. The generic MCU_PIO driver calls this function after loading the - * program into instruction memory. The function must fully configure and - * enable the state machine. - * - * @param pstrPio PIO instance (pio0 or pio1). - * @param u8Sm State machine index (0-3) within that PIO instance. - * @param u8Pin GPIO pin from the config struct. - * @param u32Offset Instruction memory offset where the program was loaded. - */ -typedef void (*MCU_PIO_tpfProgramInit)(PIO pstrPio, u8 u8Sm, u8 u8Pin, u32 u32Offset); - -/* ------------------------------------------------------------------------ */ -/* CONFIGURATION STRUCTURE */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Per-instance PIO configuration. - * - * One entry per PIO program/state-machine pair, stored in - * MCU_PIO_astrConfig[]. The array index is used as the instance - * parameter in all public API calls. - */ -typedef struct -{ - PIO pstrPio; /**< PIO block: pio0 or pio1 */ - u8 u8Sm; /**< State machine index (0-3) */ - u8 u8Pin; /**< GPIO pin used by this program */ - const pio_program_t *pstrProgram; /**< Pointer to compiled PIO program */ - MCU_PIO_tpfProgramInit pfProgramInit; /**< Program-specific SM config callback */ -} MCU_PIO_tstrConfig; - -/* ------------------------------------------------------------------------ */ -/* PUBLIC API */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Initialize all configured PIO instances. - * - * For each config entry: loads the PIO program into the instruction - * memory of the selected PIO block, then calls the program-specific - * init callback to configure the state machine (pins, shift, clock). - * - * SYS_ECU calls this once during the init sequence. - * - * @return STD_OK on success, STD_NOK if any instance fails. - */ -STD_tenuResult MCU_PIO_enuInit(void); - -/** - * @brief Push a 32-bit word into a PIO state machine's TX FIFO (blocking). - * - * Blocks until the FIFO has space, then writes the data. For WS2812, - * each call sends one pixel (24-bit GRB left-justified in the 32-bit word). - * - * @param u8Instance Config array index (MCU_PIO_tenuInstance). - * @param u32Data The 32-bit value to push. - */ -void MCU_PIO_vPutBlocking(u8 u8Instance, u32 u32Data); - -/** - * @brief Push a buffer of 32-bit words to the TX FIFO via DMA (non-blocking). - * - * Starts a DMA transfer from pu32Data into the PIO TX FIFO. Returns - * immediately. The DMA channel was pre-claimed during Init. - * - * The caller MUST keep pu32Data valid until the transfer completes. - * - * @param u8Instance Config array index. - * @param pu32Data Pointer to array of 32-bit words. Must not be NULL. - * @param u16Count Number of 32-bit words to transfer. - * @return STD_OK transfer started, - * STD_NULL_POINTER_ERROR if pu32Data is NULL. - */ -STD_tenuResult MCU_PIO_enuPutBufferAsync(u8 u8Instance, const u32 *pu32Data, u16 u16Count); - -#endif /* MCU_PIO_H */ diff --git a/color_switcher/src/MCU_PIO/pio/ws2812.pio b/color_switcher/src/MCU_PIO/pio/ws2812.pio deleted file mode 100644 index 2c60c3d..0000000 --- a/color_switcher/src/MCU_PIO/pio/ws2812.pio +++ /dev/null @@ -1,73 +0,0 @@ -; ============================================================================ -; ws2812.pio — WS2812B NZR protocol driver for RP2040 PIO -; ============================================================================ -; Written from scratch for the color_switcher project. -; -; WS2812 protocol: each bit is a fixed-length pulse (~1.25 us at 800 kHz). -; "1" bit: long high (~875 ns) + short low (~375 ns) -; "0" bit: short high (~375 ns) + long low (~875 ns) -; -; Timing: 10 PIO cycles per bit at 8 MHz PIO clock (sysclk 125 MHz / 15.625). -; "1" bit: high 7 cycles, low 3 cycles -; "0" bit: high 3 cycles, low 7 cycles -; -; Data: 24-bit GRB, MSB first, left-justified in 32-bit FIFO word. -; Autopull at 24 bits, shift left. Side-set pin drives the data line. -; ============================================================================ - -.program ws2812 -.side_set 1 - -.wrap_target -bitloop: - out x, 1 side 0 [2] ; shift 1 bit into X, drive LOW, 3 cycles total - jmp !x do_zero side 1 [1] ; if bit=0 jump, drive HIGH, 2 cycles total -do_one: - jmp bitloop side 1 [4] ; bit=1: stay HIGH 5 more (total HIGH=7), loop -do_zero: - nop side 0 [4] ; bit=0: drive LOW 5 more (total LOW from next out=3+5) -.wrap - -; ============================================================================ -; C SDK helper — emitted into ws2812.pio.h by pico_generate_pio_header. -; Configures the state machine for WS2812 output on a single GPIO pin. -; -; Parameters: -; pio — PIO instance (pio0 or pio1) -; sm — state machine index (0-3) -; offset — instruction memory offset where the program was loaded -; pin — GPIO pin connected to the WS2812 data line -; freq — bit frequency in Hz (800000.0f for standard WS2812) -; ============================================================================ - -% c-sdk { -#include "hardware/clocks.h" - -static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq) -{ - /* Configure the GPIO pin for PIO output */ - pio_gpio_init(pio, pin); - pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); - - /* Get the default config (sets wrap points and sideset count from the .pio) */ - pio_sm_config c = ws2812_program_get_default_config(offset); - - /* Side-set pin = the WS2812 data line */ - sm_config_set_sideset_pins(&c, pin); - - /* Shift left, autopull at 24 bits (GRB = 3 bytes). - * Data must be left-justified in the 32-bit FIFO word (bits [31:8]). */ - sm_config_set_out_shift(&c, false, true, 24); - - /* Join both FIFOs into a single 8-entry TX FIFO for deeper buffering */ - sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); - - /* Clock divider: 10 PIO cycles per bit, so PIO freq = bit_freq * 10. - * clkdiv = sysclk / (freq * 10). E.g., 125 MHz / 8 MHz = 15.625 */ - sm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / (freq * 10.0f)); - - /* Apply the config and start the state machine */ - pio_sm_init(pio, sm, offset, &c); - pio_sm_set_enabled(pio, sm, true); -} -%} \ No newline at end of file diff --git a/color_switcher/src/MCU_PIO/prg/MCU_PIO_prg.c b/color_switcher/src/MCU_PIO/prg/MCU_PIO_prg.c deleted file mode 100644 index 3867048..0000000 --- a/color_switcher/src/MCU_PIO/prg/MCU_PIO_prg.c +++ /dev/null @@ -1,115 +0,0 @@ -/****************************************************************************** - * File: MCU_PIO_prg.c - * Component: MCU_PIO - * Description: Generic PIO driver implementation. Loads PIO programs into - * instruction memory, calls program-specific init callbacks, - * claims DMA channels, and provides blocking + async writes. - * - * Layer: MCU (hardware abstraction) - *****************************************************************************/ - -#include "MCU_PIO.h" -#include "MCU_PIO_priv.h" -#include "MCU_PIO_cfg.h" - -#include "hardware/pio.h" -#include "hardware/dma.h" - -/* ------------------------------------------------------------------------ */ -/* RUNTIME STATE */ -/* ------------------------------------------------------------------------ */ - -static MCU_PIO_tstrControl strControl; - -/* ========================================================================= */ -/* INIT */ -/* ========================================================================= */ - -STD_tenuResult MCU_PIO_enuInit(void) -{ - STD_tenuResult enuResultLoc = STD_OK; - u8 u8IndexLoc; - - for (u8IndexLoc = 0U; u8IndexLoc < (u8)MCU_PIO_NUM_INSTANCES; u8IndexLoc++) - { - const MCU_PIO_tstrConfig *pstrCfgLoc = &MCU_PIO_astrConfig[u8IndexLoc]; - - /* Load the PIO program into instruction memory */ - u32 u32OffsetLoc = (u32)pio_add_program(pstrCfgLoc->pstrPio, - pstrCfgLoc->pstrProgram); - - /* Call the program-specific init callback to configure the SM */ - pstrCfgLoc->pfProgramInit(pstrCfgLoc->pstrPio, - pstrCfgLoc->u8Sm, - pstrCfgLoc->u8Pin, - u32OffsetLoc); - - /* Claim a DMA channel for async FIFO writes. Reserved for the - * lifetime of the application — never released. true = panic - * if no channels available (misconfiguration, not a runtime error). */ - strControl.as8DmaChannel[u8IndexLoc] = (s8)dma_claim_unused_channel(true); - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* PUT BLOCKING (SINGLE WORD) */ -/* ========================================================================= */ - -void MCU_PIO_vPutBlocking(u8 u8Instance, u32 u32Data) -{ - const MCU_PIO_tstrConfig *pstrCfgLoc = &MCU_PIO_astrConfig[u8Instance]; - - /* Blocks until the TX FIFO has space, then writes the 32-bit word */ - pio_sm_put_blocking(pstrCfgLoc->pstrPio, pstrCfgLoc->u8Sm, u32Data); -} - -/* ========================================================================= */ -/* PUT BUFFER ASYNC (DMA, NON-BLOCKING) */ -/* ========================================================================= */ - -STD_tenuResult MCU_PIO_enuPutBufferAsync(u8 u8Instance, const u32 *pu32Data, u16 u16Count) -{ - STD_tenuResult enuResultLoc = STD_OK; - - if (pu32Data == STD_NULL) - { - enuResultLoc = STD_NULL_POINTER_ERROR; - } - else - { - const MCU_PIO_tstrConfig *pstrCfgLoc = &MCU_PIO_astrConfig[u8Instance]; - s8 s8ChLoc = strControl.as8DmaChannel[u8Instance]; - - dma_channel_config strCfgLoc = dma_channel_get_default_config((u32)s8ChLoc); - - /* 32-bit transfers — matches the PIO FIFO word size */ - channel_config_set_transfer_data_size(&strCfgLoc, DMA_SIZE_32); - - /* Source: increment through the caller's buffer */ - channel_config_set_read_increment(&strCfgLoc, true); - - /* Destination: PIO TX FIFO register (fixed address) */ - channel_config_set_write_increment(&strCfgLoc, false); - - /* Pace by PIO TX FIFO DREQ — DMA only pushes when SM can accept */ - channel_config_set_dreq(&strCfgLoc, pio_get_dreq(pstrCfgLoc->pstrPio, - pstrCfgLoc->u8Sm, - true)); - - /* Start the DMA transfer. Runs autonomously until u16Count words - * have been pushed into the FIFO. Caller must keep pu32Data valid - * until transfer completes. */ - dma_channel_configure( - (u32)s8ChLoc, - &strCfgLoc, - &pstrCfgLoc->pstrPio->txf[pstrCfgLoc->u8Sm], /* dest: PIO TX FIFO */ - pu32Data, /* source: buffer */ - u16Count, /* word count */ - true /* start immediately */ - ); - } - - return enuResultLoc; -} \ No newline at end of file diff --git a/color_switcher/src/MCU_PIO/prg/MCU_PIO_priv.h b/color_switcher/src/MCU_PIO/prg/MCU_PIO_priv.h deleted file mode 100644 index a50a9ce..0000000 --- a/color_switcher/src/MCU_PIO/prg/MCU_PIO_priv.h +++ /dev/null @@ -1,34 +0,0 @@ -/****************************************************************************** - * File: MCU_PIO_priv.h - * Component: MCU_PIO - * Description: Private header — extern config array and runtime control - * struct holding pre-claimed DMA channels per instance. - * - * Layer: MCU (hardware abstraction) - internal use only - *****************************************************************************/ - -#ifndef MCU_PIO_PRIV_H -#define MCU_PIO_PRIV_H - -#include "MCU_PIO.h" -#include "MCU_PIO_cfg.h" - -extern const MCU_PIO_tstrConfig MCU_PIO_astrConfig[MCU_PIO_NUM_INSTANCES]; - -/* ------------------------------------------------------------------------ */ -/* RUNTIME CONTROL STRUCTURE */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Per-instance runtime state. - * - * as8DmaChannel — DMA channel claimed during Init for async FIFO writes. - * One channel per PIO instance, reserved for the lifetime - * of the application. - */ -typedef struct -{ - s8 as8DmaChannel[MCU_PIO_NUM_INSTANCES]; -} MCU_PIO_tstrControl; - -#endif /* MCU_PIO_PRIV_H */ \ No newline at end of file diff --git a/color_switcher/src/MCU_UART/cfg/MCU_UART_cfg.c b/color_switcher/src/MCU_UART/cfg/MCU_UART_cfg.c deleted file mode 100644 index c490e8f..0000000 --- a/color_switcher/src/MCU_UART/cfg/MCU_UART_cfg.c +++ /dev/null @@ -1,26 +0,0 @@ -/****************************************************************************** - * File: MCU_UART_cfg.c - * Component: MCU_UART - * Description: Configuration array definition for the MCU_UART driver. - * - * Layer: MCU (hardware abstraction) - configuration - *****************************************************************************/ - -#include "MCU_UART.h" -#include "MCU_UART_cfg.h" - -const MCU_UART_tstrConfig MCU_UART_astrConfig[MCU_UART_NUM_INSTANCES] = -{ - [MCU_UART_INSTANCE_0] = - { - .u8TxPin = MCU_UART_0_TX_PIN, - .u8RxPin = MCU_UART_0_RX_PIN, - .u32BaudRate = MCU_UART_0_BAUD_RATE, - .enuDataBits = MCU_UART_0_DATA_BITS, - .enuStopBits = MCU_UART_0_STOP_BITS, - .enuParity = MCU_UART_0_PARITY, - .enuTxAsyncMode = MCU_UART_0_TX_ASYNC_MODE, - .pfTxCompleteCallback = MCU_UART_0_TX_COMPLETE_CALLBACK, - .enuRxAsyncMode = MCU_UART_0_RX_ASYNC_MODE, - }, -}; \ No newline at end of file diff --git a/color_switcher/src/MCU_UART/cfg/MCU_UART_cfg.h b/color_switcher/src/MCU_UART/cfg/MCU_UART_cfg.h deleted file mode 100644 index 9166a19..0000000 --- a/color_switcher/src/MCU_UART/cfg/MCU_UART_cfg.h +++ /dev/null @@ -1,51 +0,0 @@ -/****************************************************************************** - * File: MCU_UART_cfg.h - * Component: MCU_UART - * Description: Configuration for the MCU_UART driver. Defines instances, - * pin assignments, baud rates, data format, TX/RX async modes, - * and RX buffer sizing. - * - * Layer: MCU (hardware abstraction) - configuration - *****************************************************************************/ - -#ifndef MCU_UART_CFG_H -#define MCU_UART_CFG_H - -#include "STD_TYPES.h" - -/* ------------------------------------------------------------------------ */ -/* INSTANCE ENUMERATION */ -/* ------------------------------------------------------------------------ */ - -typedef enum -{ - MCU_UART_INSTANCE_0 = 0U, - MCU_UART_NUM_INSTANCES -} MCU_UART_tenuInstance; - -/* ------------------------------------------------------------------------ */ -/* RX RING BUFFER SIZING */ -/* ------------------------------------------------------------------------ */ - -/** @brief Number of address bits for the RX ring buffer (2^N bytes). - * Must be power of 2 for DMA ring wrap. - * 5 = 32, 6 = 64, 7 = 128, 8 = 256. */ -#define MCU_UART_RX_BUFFER_SIZE_BITS 6U -#define MCU_UART_RX_BUFFER_SIZE (1U << MCU_UART_RX_BUFFER_SIZE_BITS) -#define MCU_UART_RX_BUFFER_MASK (MCU_UART_RX_BUFFER_SIZE - 1U) - -/* ------------------------------------------------------------------------ */ -/* INSTANCE 0 CONFIGURATION */ -/* ------------------------------------------------------------------------ */ - -#define MCU_UART_0_TX_PIN 0U -#define MCU_UART_0_RX_PIN 1U -#define MCU_UART_0_BAUD_RATE 115200U -#define MCU_UART_0_DATA_BITS MCU_UART_DATA_BITS_8 -#define MCU_UART_0_STOP_BITS MCU_UART_STOP_BITS_1 -#define MCU_UART_0_PARITY MCU_UART_PARITY_NONE -#define MCU_UART_0_TX_ASYNC_MODE MCU_UART_ASYNC_DMA -#define MCU_UART_0_TX_COMPLETE_CALLBACK STD_NULL -#define MCU_UART_0_RX_ASYNC_MODE MCU_UART_ASYNC_ISR - -#endif /* MCU_UART_CFG_H */ \ No newline at end of file diff --git a/color_switcher/src/MCU_UART/inc/MCU_UART.h b/color_switcher/src/MCU_UART/inc/MCU_UART.h deleted file mode 100644 index 283a327..0000000 --- a/color_switcher/src/MCU_UART/inc/MCU_UART.h +++ /dev/null @@ -1,124 +0,0 @@ -/****************************************************************************** - * File: MCU_UART.h - * Component: MCU_UART - * Description: Public interface for the MCU UART driver component. - * - * TX: SendByte (blocking), SendBuffer (non-blocking DMA/ISR), - * SendBufferBlocking. - * RX: background ring buffer filled by ISR or DMA. - * ReadByte / ReadBuffer read from the buffer (non-blocking). - * - * Layer: MCU (hardware abstraction) - *****************************************************************************/ - -#ifndef MCU_UART_H -#define MCU_UART_H - -#include "STD_TYPES.h" - -/* ------------------------------------------------------------------------ */ -/* CONFIGURATION VALUE TYPES */ -/* ------------------------------------------------------------------------ */ - -typedef enum -{ - MCU_UART_PARITY_NONE = 0U, - MCU_UART_PARITY_EVEN, - MCU_UART_PARITY_ODD -} MCU_UART_tenuParity; - -typedef enum -{ - MCU_UART_DATA_BITS_5 = 5U, - MCU_UART_DATA_BITS_6 = 6U, - MCU_UART_DATA_BITS_7 = 7U, - MCU_UART_DATA_BITS_8 = 8U -} MCU_UART_tenuDataBits; - -typedef enum -{ - MCU_UART_STOP_BITS_1 = 1U, - MCU_UART_STOP_BITS_2 = 2U -} MCU_UART_tenuStopBits; - -typedef enum -{ - MCU_UART_ASYNC_DMA = 0U, - MCU_UART_ASYNC_ISR -} MCU_UART_tenuAsyncMode; - -/* ------------------------------------------------------------------------ */ -/* CONFIGURATION STRUCTURE */ -/* ------------------------------------------------------------------------ */ - -typedef struct -{ - u8 u8TxPin; - u8 u8RxPin; - u32 u32BaudRate; - MCU_UART_tenuDataBits enuDataBits; - MCU_UART_tenuStopBits enuStopBits; - MCU_UART_tenuParity enuParity; - MCU_UART_tenuAsyncMode enuTxAsyncMode; - STD_tpfCallbackFunc pfTxCompleteCallback; - MCU_UART_tenuAsyncMode enuRxAsyncMode; -} MCU_UART_tstrConfig; - -/* ------------------------------------------------------------------------ */ -/* TX PUBLIC API */ -/* ------------------------------------------------------------------------ */ - -STD_tenuResult MCU_UART_enuInit(void); - -STD_tenuResult MCU_UART_enuSendByte(u8 u8Instance, u8 u8Byte); - -STD_tenuResult MCU_UART_enuSendBuffer(u8 u8Instance, const u8 *pu8Data, u16 u16Length); - -STD_tenuResult MCU_UART_enuSendBufferBlocking(u8 u8Instance, const u8 *pu8Data, u16 u16Length); - -STD_tBool MCU_UART_bIsTxBusy(u8 u8Instance); - -/* ------------------------------------------------------------------------ */ -/* RX PUBLIC API */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Read one byte from the RX ring buffer (non-blocking). - * - * The ring buffer is filled in the background by ISR or DMA. - * Returns immediately — STD_OK with the byte, or STD_NOK if empty. - * - * @param u8Instance UART instance index. - * @param pu8Byte Pointer to store the received byte. - * @return STD_OK byte read, - * STD_NULL_POINTER_ERROR if pu8Byte is NULL, - * STD_NOK if ring buffer is empty. - */ -STD_tenuResult MCU_UART_enuReadByte(u8 u8Instance, u8 *pu8Byte); - -/** - * @brief Read up to u16MaxLength bytes from the RX ring buffer (non-blocking). - * - * Copies as many bytes as are currently available (up to u16MaxLength) - * into pu8Data. Reports the actual number of bytes read via pu16Read. - * Returns immediately even if fewer than u16MaxLength bytes are available. - * - * @param u8Instance UART instance index. - * @param pu8Data Pointer to output buffer. - * @param u16MaxLength Maximum bytes to read. - * @param pu16Read Pointer to store actual bytes read. Must not be NULL. - * @return STD_OK at least one byte read, - * STD_NULL_POINTER_ERROR if pu8Data or pu16Read is NULL, - * STD_NOK if ring buffer is empty (zero bytes read). - */ -STD_tenuResult MCU_UART_enuReadBuffer(u8 u8Instance, u8 *pu8Data, u16 u16MaxLength, u16 *pu16Read); - -/** - * @brief Check if the RX ring buffer has data. - * - * @param u8Instance UART instance index. - * @return STD_TRUE if at least one byte available, STD_FALSE if empty. - */ -STD_tBool MCU_UART_bIsRxDataAvailable(u8 u8Instance); - -#endif /* MCU_UART_H */ \ No newline at end of file diff --git a/color_switcher/src/MCU_UART/prg/MCU_UART_prg.c b/color_switcher/src/MCU_UART/prg/MCU_UART_prg.c deleted file mode 100644 index 89b1138..0000000 --- a/color_switcher/src/MCU_UART/prg/MCU_UART_prg.c +++ /dev/null @@ -1,421 +0,0 @@ -/****************************************************************************** - * File: MCU_UART_prg.c - * Component: MCU_UART - * Description: TX: blocking + non-blocking (DMA or ISR) with callback. - * RX: ISR or DMA fills ring buffer in background. ReadByte - * and ReadBuffer read from the buffer non-blocking. - * - * Layer: MCU (hardware abstraction) - *****************************************************************************/ - -#include "MCU_UART.h" -#include "MCU_UART_priv.h" -#include "MCU_UART_cfg.h" - -#include "hardware/uart.h" -#include "hardware/gpio.h" -#include "hardware/dma.h" -#include "hardware/irq.h" - -/* ------------------------------------------------------------------------ */ -/* INSTANCE LOOKUP TABLE */ -/* ------------------------------------------------------------------------ */ - -static uart_inst_t * const apstrInstances[] = { uart0, uart1 }; - -/* ------------------------------------------------------------------------ */ -/* RUNTIME STATE */ -/* ------------------------------------------------------------------------ */ - -static MCU_UART_tstrControl strControl; - -/* ------------------------------------------------------------------------ */ -/* INTERNAL HELPERS */ -/* ------------------------------------------------------------------------ */ - -static void vCallTxCallback(u8 u8Instance) -{ - STD_tpfCallbackFunc pfCbLoc = MCU_UART_astrConfig[u8Instance].pfTxCompleteCallback; - - if (pfCbLoc != STD_NULL) - { - pfCbLoc(); - } -} - -/** @brief Get current RX head. DMA mode derives from hw write pointer. */ -static u16 u16GetRxHead(u8 u8Instance) -{ - u16 u16HeadLoc; - - if (MCU_UART_astrConfig[u8Instance].enuRxAsyncMode == MCU_UART_ASYNC_DMA) - { - s8 s8ChLoc = strControl.as8RxDmaChannel[u8Instance]; - u32 u32WrLoc = (u32)dma_channel_hw_addr((u32)s8ChLoc)->write_addr; - u32 u32BaseLoc = (u32)(&strControl.aau8RxBuffer[u8Instance][0]); - u16HeadLoc = (u16)((u32WrLoc - u32BaseLoc) & MCU_UART_RX_BUFFER_MASK); - } - else - { - u16HeadLoc = strControl.au16RxHead[u8Instance]; - } - - return u16HeadLoc; -} - -/* ------------------------------------------------------------------------ */ -/* TX DMA IRQ HANDLER (INSTANCE 0) */ -/* ------------------------------------------------------------------------ */ - -static void vTxDmaIrqHandler0(void) -{ - s8 s8ChLoc = strControl.as8TxDmaChannel[MCU_UART_INSTANCE_0]; - u32 u32StatusLoc = dma_channel_get_irq0_status((u32)s8ChLoc); - - if (u32StatusLoc != 0U) - { - dma_irqn_acknowledge_channel(0, (u32)s8ChLoc); - strControl.abTxBusy[MCU_UART_INSTANCE_0] = STD_FALSE; - vCallTxCallback((u8)MCU_UART_INSTANCE_0); - } -} - -/* ------------------------------------------------------------------------ */ -/* UART ISR HANDLER (RX + TX) */ -/* ------------------------------------------------------------------------ */ - -static void vUartIsrHandler(u8 u8Instance) -{ - uart_inst_t *pstrUartLoc = apstrInstances[u8Instance]; - - /* --- RX: drain FIFO into ring buffer --- */ - STD_tBool bReadableLoc = (uart_is_readable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE; - - while (bReadableLoc == STD_TRUE) - { - u8 u8ByteLoc = (u8)uart_getc(pstrUartLoc); - u16 u16HeadLoc = strControl.au16RxHead[u8Instance]; - - strControl.aau8RxBuffer[u8Instance][u16HeadLoc] = u8ByteLoc; - strControl.au16RxHead[u8Instance] = (u16HeadLoc + 1U) & MCU_UART_RX_BUFFER_MASK; - - bReadableLoc = (uart_is_readable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE; - } - - /* --- TX: fill FIFO from buffer (if TX ISR active) --- */ - STD_tBool bTxBusyLoc = strControl.abTxBusy[u8Instance]; - - if (bTxBusyLoc == STD_TRUE) - { - STD_tBool bFifoReady = (uart_is_writable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE; - STD_tBool bDataLeft = (strControl.au16TxIndex[u8Instance] < strControl.au16TxLength[u8Instance]) ? STD_TRUE : STD_FALSE; - - while ((bFifoReady == STD_TRUE) && (bDataLeft == STD_TRUE)) - { - uart_putc_raw(pstrUartLoc, - strControl.apu8TxBuffer[u8Instance][strControl.au16TxIndex[u8Instance]]); - strControl.au16TxIndex[u8Instance]++; - - bFifoReady = (uart_is_writable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE; - bDataLeft = (strControl.au16TxIndex[u8Instance] < strControl.au16TxLength[u8Instance]) ? STD_TRUE : STD_FALSE; - } - - if (bDataLeft == STD_FALSE) - { - uart_set_irqs_enabled(pstrUartLoc, false, true); - strControl.abTxBusy[u8Instance] = STD_FALSE; - vCallTxCallback(u8Instance); - } - } -} - -static void vUart0IrqHandler(void) -{ - vUartIsrHandler((u8)MCU_UART_INSTANCE_0); -} - -/* ========================================================================= */ -/* INIT */ -/* ========================================================================= */ - -STD_tenuResult MCU_UART_enuInit(void) -{ - STD_tenuResult enuResultLoc = STD_OK; - u8 u8IndexLoc; - - for (u8IndexLoc = 0U; u8IndexLoc < (u8)MCU_UART_NUM_INSTANCES; u8IndexLoc++) - { - strControl.apu8TxBuffer[u8IndexLoc] = STD_NULL; - strControl.au16TxLength[u8IndexLoc] = 0U; - strControl.au16TxIndex[u8IndexLoc] = 0U; - strControl.abTxBusy[u8IndexLoc] = STD_FALSE; - strControl.as8TxDmaChannel[u8IndexLoc] = -1; - strControl.au16RxHead[u8IndexLoc] = 0U; - strControl.au16RxTail[u8IndexLoc] = 0U; - strControl.as8RxDmaChannel[u8IndexLoc] = -1; - } - - for (u8IndexLoc = 0U; u8IndexLoc < (u8)MCU_UART_NUM_INSTANCES; u8IndexLoc++) - { - const MCU_UART_tstrConfig *pstrCfgLoc = &MCU_UART_astrConfig[u8IndexLoc]; - uart_inst_t *pstrUartLoc = apstrInstances[u8IndexLoc]; - - uart_init(pstrUartLoc, pstrCfgLoc->u32BaudRate); - gpio_set_function(pstrCfgLoc->u8TxPin, GPIO_FUNC_UART); - gpio_set_function(pstrCfgLoc->u8RxPin, GPIO_FUNC_UART); - uart_set_format(pstrUartLoc, - pstrCfgLoc->enuDataBits, - pstrCfgLoc->enuStopBits, - pstrCfgLoc->enuParity); - - /* TX async setup */ - if (pstrCfgLoc->enuTxAsyncMode == MCU_UART_ASYNC_DMA) - { - s8 s8ChLoc = (s8)dma_claim_unused_channel(true); - strControl.as8TxDmaChannel[u8IndexLoc] = s8ChLoc; - dma_channel_set_irq0_enabled((u32)s8ChLoc, true); - - if (u8IndexLoc == (u8)MCU_UART_INSTANCE_0) - { - irq_set_exclusive_handler(DMA_IRQ_0, vTxDmaIrqHandler0); - irq_set_enabled(DMA_IRQ_0, true); - } - } - - /* RX async setup */ - if (pstrCfgLoc->enuRxAsyncMode == MCU_UART_ASYNC_DMA) - { - s8 s8RxChLoc = (s8)dma_claim_unused_channel(true); - strControl.as8RxDmaChannel[u8IndexLoc] = s8RxChLoc; - - dma_channel_config strRxCfgLoc = dma_channel_get_default_config((u32)s8RxChLoc); - channel_config_set_transfer_data_size(&strRxCfgLoc, DMA_SIZE_8); - channel_config_set_read_increment(&strRxCfgLoc, false); - channel_config_set_write_increment(&strRxCfgLoc, true); - channel_config_set_dreq(&strRxCfgLoc, uart_get_dreq(pstrUartLoc, false)); - channel_config_set_ring(&strRxCfgLoc, true, MCU_UART_RX_BUFFER_SIZE_BITS); - - dma_channel_configure( - (u32)s8RxChLoc, - &strRxCfgLoc, - &strControl.aau8RxBuffer[u8IndexLoc][0], - &uart_get_hw(pstrUartLoc)->dr, - 0xFFFFFFFFU, - true - ); - } - else - { - if (u8IndexLoc == (u8)MCU_UART_INSTANCE_0) - { - irq_set_exclusive_handler(UART0_IRQ, vUart0IrqHandler); - irq_set_enabled(UART0_IRQ, true); - } - uart_set_irqs_enabled(pstrUartLoc, false, true); - } - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* SEND BYTE (BLOCKING) */ -/* ========================================================================= */ - -STD_tenuResult MCU_UART_enuSendByte(u8 u8Instance, u8 u8Byte) -{ - STD_tenuResult enuResultLoc = STD_OK; - - uart_putc_raw(apstrInstances[u8Instance], u8Byte); - - return enuResultLoc; -} - -/* ========================================================================= */ -/* SEND BUFFER (NON-BLOCKING) */ -/* ========================================================================= */ - -STD_tenuResult MCU_UART_enuSendBuffer(u8 u8Instance, const u8 *pu8Data, u16 u16Length) -{ - STD_tenuResult enuResultLoc = STD_OK; - STD_tBool bBusyLoc = strControl.abTxBusy[u8Instance]; - MCU_UART_tenuAsyncMode enuModeLoc = MCU_UART_astrConfig[u8Instance].enuTxAsyncMode; - - if (pu8Data == STD_NULL) - { - enuResultLoc = STD_NULL_POINTER_ERROR; - } - else if (bBusyLoc == STD_TRUE) - { - enuResultLoc = STD_NOK; - } - else - { - strControl.apu8TxBuffer[u8Instance] = pu8Data; - strControl.au16TxLength[u8Instance] = u16Length; - strControl.au16TxIndex[u8Instance] = 0U; - strControl.abTxBusy[u8Instance] = STD_TRUE; - - if (enuModeLoc == MCU_UART_ASYNC_DMA) - { - s8 s8ChLoc = strControl.as8TxDmaChannel[u8Instance]; - uart_inst_t *pstrUartLoc = apstrInstances[u8Instance]; - - dma_channel_config strCfgLoc = dma_channel_get_default_config((u32)s8ChLoc); - channel_config_set_transfer_data_size(&strCfgLoc, DMA_SIZE_8); - channel_config_set_read_increment(&strCfgLoc, true); - channel_config_set_write_increment(&strCfgLoc, false); - channel_config_set_dreq(&strCfgLoc, uart_get_dreq(pstrUartLoc, true)); - - dma_channel_configure( - (u32)s8ChLoc, &strCfgLoc, - &uart_get_hw(pstrUartLoc)->dr, pu8Data, u16Length, true); - } - else - { - uart_inst_t *pstrUartLoc = apstrInstances[u8Instance]; - STD_tBool bFifoReady = (uart_is_writable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE; - STD_tBool bDataLeft = (strControl.au16TxIndex[u8Instance] < u16Length) ? STD_TRUE : STD_FALSE; - - while ((bFifoReady == STD_TRUE) && (bDataLeft == STD_TRUE)) - { - uart_putc_raw(pstrUartLoc, pu8Data[strControl.au16TxIndex[u8Instance]]); - strControl.au16TxIndex[u8Instance]++; - bFifoReady = (uart_is_writable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE; - bDataLeft = (strControl.au16TxIndex[u8Instance] < u16Length) ? STD_TRUE : STD_FALSE; - } - - if (bDataLeft == STD_FALSE) - { - strControl.abTxBusy[u8Instance] = STD_FALSE; - vCallTxCallback(u8Instance); - } - else - { - uart_set_irqs_enabled(pstrUartLoc, true, true); - } - } - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* SEND BUFFER (BLOCKING) */ -/* ========================================================================= */ - -STD_tenuResult MCU_UART_enuSendBufferBlocking(u8 u8Instance, const u8 *pu8Data, u16 u16Length) -{ - STD_tenuResult enuResultLoc = STD_OK; - u16 u16IndexLoc; - - if (pu8Data == STD_NULL) - { - enuResultLoc = STD_NULL_POINTER_ERROR; - } - else - { - for (u16IndexLoc = 0U; u16IndexLoc < u16Length; u16IndexLoc++) - { - uart_putc_raw(apstrInstances[u8Instance], pu8Data[u16IndexLoc]); - } - vCallTxCallback(u8Instance); - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* TX BUSY CHECK */ -/* ========================================================================= */ - -STD_tBool MCU_UART_bIsTxBusy(u8 u8Instance) -{ - return strControl.abTxBusy[u8Instance]; -} - -/* ========================================================================= */ -/* READ BYTE (NON-BLOCKING) */ -/* ========================================================================= */ - -STD_tenuResult MCU_UART_enuReadByte(u8 u8Instance, u8 *pu8Byte) -{ - STD_tenuResult enuResultLoc = STD_OK; - - if (pu8Byte == STD_NULL) - { - enuResultLoc = STD_NULL_POINTER_ERROR; - } - else - { - u16 u16HeadLoc = u16GetRxHead(u8Instance); - u16 u16TailLoc = strControl.au16RxTail[u8Instance]; - - if (u16HeadLoc == u16TailLoc) - { - enuResultLoc = STD_NOK; - } - else - { - *pu8Byte = strControl.aau8RxBuffer[u8Instance][u16TailLoc]; - strControl.au16RxTail[u8Instance] = (u16TailLoc + 1U) & MCU_UART_RX_BUFFER_MASK; - } - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* READ BUFFER (NON-BLOCKING) */ -/* ========================================================================= */ - -STD_tenuResult MCU_UART_enuReadBuffer(u8 u8Instance, u8 *pu8Data, u16 u16MaxLength, u16 *pu16Read) -{ - STD_tenuResult enuResultLoc = STD_OK; - - if ((pu8Data == STD_NULL) || (pu16Read == STD_NULL)) - { - enuResultLoc = STD_NULL_POINTER_ERROR; - } - else - { - u16 u16HeadLoc = u16GetRxHead(u8Instance); - u16 u16TailLoc = strControl.au16RxTail[u8Instance]; - u16 u16CountLoc = 0U; - - while ((u16HeadLoc != u16TailLoc) && (u16CountLoc < u16MaxLength)) - { - pu8Data[u16CountLoc] = strControl.aau8RxBuffer[u8Instance][u16TailLoc]; - u16TailLoc = (u16TailLoc + 1U) & MCU_UART_RX_BUFFER_MASK; - u16CountLoc++; - } - - strControl.au16RxTail[u8Instance] = u16TailLoc; - *pu16Read = u16CountLoc; - - if (u16CountLoc == 0U) - { - enuResultLoc = STD_NOK; - } - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* RX DATA AVAILABLE CHECK */ -/* ========================================================================= */ - -STD_tBool MCU_UART_bIsRxDataAvailable(u8 u8Instance) -{ - STD_tBool bResultLoc = STD_FALSE; - u16 u16HeadLoc = u16GetRxHead(u8Instance); - u16 u16TailLoc = strControl.au16RxTail[u8Instance]; - - if (u16HeadLoc != u16TailLoc) - { - bResultLoc = STD_TRUE; - } - - return bResultLoc; -} \ No newline at end of file diff --git a/color_switcher/src/MCU_UART/prg/MCU_UART_priv.h b/color_switcher/src/MCU_UART/prg/MCU_UART_priv.h deleted file mode 100644 index 59178c1..0000000 --- a/color_switcher/src/MCU_UART/prg/MCU_UART_priv.h +++ /dev/null @@ -1,34 +0,0 @@ -/****************************************************************************** - * File: MCU_UART_priv.h - * Component: MCU_UART - * Description: Private header — control struct and extern config array. - * - * Layer: MCU (hardware abstraction) - internal use only - *****************************************************************************/ - -#ifndef MCU_UART_PRIV_H -#define MCU_UART_PRIV_H - -#include "MCU_UART.h" -#include "MCU_UART_cfg.h" - -extern const MCU_UART_tstrConfig MCU_UART_astrConfig[MCU_UART_NUM_INSTANCES]; - -typedef struct -{ - /* TX state */ - const u8 *apu8TxBuffer[MCU_UART_NUM_INSTANCES]; - u16 au16TxLength[MCU_UART_NUM_INSTANCES]; - u16 au16TxIndex[MCU_UART_NUM_INSTANCES]; - STD_tBool abTxBusy[MCU_UART_NUM_INSTANCES]; - s8 as8TxDmaChannel[MCU_UART_NUM_INSTANCES]; - - /* RX ring buffer — filled by ISR or DMA in the background */ - u8 aau8RxBuffer[MCU_UART_NUM_INSTANCES][MCU_UART_RX_BUFFER_SIZE] - __attribute__((aligned(MCU_UART_RX_BUFFER_SIZE))); - u16 au16RxHead[MCU_UART_NUM_INSTANCES]; - u16 au16RxTail[MCU_UART_NUM_INSTANCES]; - s8 as8RxDmaChannel[MCU_UART_NUM_INSTANCES]; -} MCU_UART_tstrControl; - -#endif /* MCU_UART_PRIV_H */ diff --git a/color_switcher/src/MCU_USB/cfg/MCU_USB_cfg.c b/color_switcher/src/MCU_USB/cfg/MCU_USB_cfg.c deleted file mode 100644 index 1efe6f9..0000000 --- a/color_switcher/src/MCU_USB/cfg/MCU_USB_cfg.c +++ /dev/null @@ -1,14 +0,0 @@ -/****************************************************************************** - * File: MCU_USB_cfg.c - * Component: MCU_USB - * Description: Configuration implementation for the MCU_USB driver. - * Holds the actual configuration values (timeouts, buffer - * sizes, mode flags) defined as constants or configuration - * structures consumed by MCU_USB_prg.c. - * - * Layer: MCU (hardware abstraction) - configuration - *****************************************************************************/ - -#include "MCU_USB_cfg.h" - -/* Configuration definitions will go here */ diff --git a/color_switcher/src/MCU_USB/cfg/MCU_USB_cfg.h b/color_switcher/src/MCU_USB/cfg/MCU_USB_cfg.h deleted file mode 100644 index 6fc02f7..0000000 --- a/color_switcher/src/MCU_USB/cfg/MCU_USB_cfg.h +++ /dev/null @@ -1,86 +0,0 @@ -/****************************************************************************** - * File: MCU_USB_cfg.h - * Component: MCU_USB - * Description: Configuration header for the MCU_USB driver. - * Declares configuration structures and constants that can be - * edited to adapt the USB-CDC driver to the application's - * needs (e.g., enable/disable connection wait, timeout values, - * transmit buffer sizes). - * - * Layer: MCU (hardware abstraction) - configuration - *****************************************************************************/ - -#ifndef MCU_USB_CFG_H -#define MCU_USB_CFG_H - -/* STD_TYPES is needed for STD_TRUE / STD_FALSE and the u8/u16/u32 typedefs - * used by the config values and timeout comparisons below. */ -#include "STD_TYPES.h" - -/* ------------------------------------------------------------------------ */ -/* CONNECTION / INIT BEHAVIOR */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Whether MCU_USB_enuInit() should block until the host has opened - * the CDC serial port before returning. - * - * Set to STD_TRUE to avoid losing the first bytes sent by the application - * (the host needs ~1-2 s after power-up to enumerate and open the port). - * Set to STD_FALSE for a fire-and-forget init that returns immediately - - * useful if the firmware must not stall when no host is attached. - */ -#define MCU_USB_WAIT_FOR_CONNECTION MCU_USB_WAIT_FOR_CONNECTION_ENABLED - -/** - * @brief Maximum time (in milliseconds) to wait for the host to open - * the CDC serial port during MCU_USB_enuInit(). - * - * Only applies when MCU_USB_WAIT_FOR_CONNECTION is ENABLED. USB host - * enumeration typically takes ~1-2 seconds, so 3000 ms gives a - * comfortable margin. Set to 0 for an infinite wait (never times out). - * This is separate from TRANSMIT/RECEIVE timeouts because connection - * setup is a one-time event with different timing characteristics - * than per-byte I/O operations. - */ -#define MCU_USB_CONNECTION_TIMEOUT_MS 3000U - -/* ------------------------------------------------------------------------ */ -/* TIMEOUTS */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Maximum time (in milliseconds) to wait for a single transmit - * operation to complete before returning STD_NOK / STD_TIMEOUT. - * - * Applied to each transmit call in MCU_USB_prg.c. Prevents the driver - * from blocking forever if the host-side serial port is closed mid-send - * or the USB bus becomes unresponsive. - */ -#define MCU_USB_TRANSMIT_TIMEOUT_MS 1000U - -/** - * @brief Maximum time (in milliseconds) to wait for a byte to arrive on - * the receive side before returning a timeout result. - * - * Applied to each blocking receive call. Prevents the driver from hanging - * when the host is attached but simply not sending anything. - */ -#define MCU_USB_RECEIVE_TIMEOUT_MS 1000U - -/* ------------------------------------------------------------------------ */ -/* BUFFER SIZING */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Size (in bytes) of the software transmit buffer used by the - * USB driver to queue outbound data. - * - * A larger buffer lets the application call MCU_USB_enuSendBuffer with - * bigger chunks without having to wait for the USB peripheral to drain, - * at the cost of more SRAM. 64 bytes matches the USB Full-Speed bulk - * endpoint packet size, which is a convenient minimum for alignment. - */ -#define MCU_USB_TRANSMIT_BUFFER_SIZE 64U - -#endif /* MCU_USB_CFG_H */ diff --git a/color_switcher/src/MCU_USB/inc/MCU_USB.h b/color_switcher/src/MCU_USB/inc/MCU_USB.h deleted file mode 100644 index 9bac727..0000000 --- a/color_switcher/src/MCU_USB/inc/MCU_USB.h +++ /dev/null @@ -1,68 +0,0 @@ -/****************************************************************************** - * File: MCU_USB.h - * Component: MCU_USB - * Description: Public interface for the MCU USB-CDC driver. - * TX: SendByte, SendBuffer (both fire-and-forget via putchar_raw). - * RX: background ring buffer drained lazily from the SDK's - * stdio layer. ReadByte / bIsRxDataAvailable read from it. - * - * Layer: MCU (hardware abstraction) - *****************************************************************************/ - -#ifndef MCU_USB_H -#define MCU_USB_H - -#include "STD_TYPES.h" - -#define MCU_USB_WAIT_FOR_CONNECTION_DISABLED 0U -#define MCU_USB_WAIT_FOR_CONNECTION_ENABLED 1U - -/* ------------------------------------------------------------------------ */ -/* TX PUBLIC API */ -/* ------------------------------------------------------------------------ */ - -STD_tenuResult MCU_USB_enuInit(void); - -STD_tenuResult MCU_USB_enuSendByte(u8 u8Byte); - -STD_tenuResult MCU_USB_enuSendBuffer(const u8 *pu8Data, u16 u16Length); - -/* ------------------------------------------------------------------------ */ -/* RX PUBLIC API */ -/* ------------------------------------------------------------------------ */ - -/** - * @brief Read one byte from the USB RX ring buffer (non-blocking). - * - * Internally drains any pending bytes from the SDK's stdio layer into - * the ring buffer before checking. Returns immediately. - * - * @param pu8Byte Pointer to store the received byte. - * @return STD_OK byte read, - * STD_NULL_POINTER_ERROR if pu8Byte is NULL, - * STD_NOK if no data available. - */ -STD_tenuResult MCU_USB_enuReadByte(u8 *pu8Byte); - -/** - * @brief Read up to u16MaxLength bytes from the USB RX ring buffer. - * - * @param pu8Data Output buffer. - * @param u16MaxLength Maximum bytes to read. - * @param pu16Read Actual bytes read. - * @return STD_OK at least one byte read, - * STD_NULL_POINTER_ERROR if pu8Data or pu16Read is NULL, - * STD_NOK if no data available. - */ -STD_tenuResult MCU_USB_enuReadBuffer(u8 *pu8Data, u16 u16MaxLength, u16 *pu16Read); - -/** - * @brief Check if USB RX data is available. - * - * Drains pending bytes from the SDK first, then checks the ring buffer. - * - * @return STD_TRUE if data available, STD_FALSE if empty. - */ -STD_tBool MCU_USB_bIsRxDataAvailable(void); - -#endif /* MCU_USB_H */ \ No newline at end of file diff --git a/color_switcher/src/MCU_USB/prg/MCU_USB_prg.c b/color_switcher/src/MCU_USB/prg/MCU_USB_prg.c deleted file mode 100644 index 9256900..0000000 --- a/color_switcher/src/MCU_USB/prg/MCU_USB_prg.c +++ /dev/null @@ -1,229 +0,0 @@ -/****************************************************************************** - * File: MCU_USB_prg.c - * Component: MCU_USB - * Description: USB-CDC driver. TX via putchar_raw (fire-and-forget). - * RX via internal ring buffer, lazily drained from the SDK's - * stdio layer on every ReadByte / ReadBuffer / IsDataAvailable - * call. No separate RX task or interrupt needed — the SDK's - * TinyUSB background task fills stdio internally, and we pull - * from stdio into our ring buffer on demand. - * - * Layer: MCU (hardware abstraction) - *****************************************************************************/ - -#include "STD_TYPES.h" - -#include "pico/stdio_usb.h" -#include "pico/stdio.h" -#include "pico/time.h" - -#include "MCU_USB.h" -#include "MCU_USB_priv.h" -#include "MCU_USB_cfg.h" - -/* ------------------------------------------------------------------------ */ -/* RX RING BUFFER */ -/* ------------------------------------------------------------------------ */ - -/** @brief RX ring buffer size — must be power of 2. */ -#define USB_RX_BUFFER_SIZE_BITS 6U -#define USB_RX_BUFFER_SIZE (1U << USB_RX_BUFFER_SIZE_BITS) -#define USB_RX_BUFFER_MASK (USB_RX_BUFFER_SIZE - 1U) - -static u8 au8RxBuffer[USB_RX_BUFFER_SIZE]; -static u16 u16RxHead = 0U; -static u16 u16RxTail = 0U; - -/** - * @brief Drain any available bytes from the SDK's stdio into our ring buffer. - * - * Called lazily from ReadByte, ReadBuffer, and bIsRxDataAvailable. - * getchar_timeout_us(0) is non-blocking — returns PICO_ERROR_TIMEOUT (-1) - * immediately if no data. We keep pulling until the SDK has nothing left - * or our ring buffer is full. - */ -static void vDrainStdio(void) -{ - s32 s32ByteLoc; - u16 u16NextHeadLoc; - - s32ByteLoc = (s32)getchar_timeout_us(0); - - while (s32ByteLoc >= 0) - { - u16NextHeadLoc = (u16RxHead + 1U) & USB_RX_BUFFER_MASK; - - /* If the ring buffer is full, stop draining (oldest data preserved, - * newest data from SDK is lost). Caller should read faster. */ - if (u16NextHeadLoc == u16RxTail) - { - /* Buffer full — can't store this byte. Break out. */ - break; - } - - au8RxBuffer[u16RxHead] = (u8)s32ByteLoc; - u16RxHead = u16NextHeadLoc; - - s32ByteLoc = (s32)getchar_timeout_us(0); - } -} - -/* ========================================================================= */ -/* INIT */ -/* ========================================================================= */ - -STD_tenuResult MCU_USB_enuInit(void) -{ - STD_tenuResult enuResultLoc = STD_OK; - STD_tBool bSdkInitSuccess = STD_FALSE; - - bSdkInitSuccess = (stdio_usb_init() != 0) ? STD_TRUE : STD_FALSE; - - if (bSdkInitSuccess == STD_FALSE) - { - enuResultLoc = STD_NOK; - } - else - { - #if MCU_USB_WAIT_FOR_CONNECTION == MCU_USB_WAIT_FOR_CONNECTION_ENABLED - absolute_time_t absTimeout = make_timeout_time_ms(MCU_USB_CONNECTION_TIMEOUT_MS); - STD_tBool bHostOpen = STD_FALSE; - STD_tBool bTimeoutReached = STD_FALSE; - do - { - sleep_ms(10); - bHostOpen = (stdio_usb_connected() != 0) ? STD_TRUE : STD_FALSE; - bTimeoutReached = (time_reached(absTimeout) != 0) ? STD_TRUE : STD_FALSE; - } while ((bHostOpen == STD_FALSE) && (bTimeoutReached == STD_FALSE)); - - if (bHostOpen == STD_FALSE) - { - enuResultLoc = STD_NOK; - } - #endif - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* SEND BYTE */ -/* ========================================================================= */ - -STD_tenuResult MCU_USB_enuSendByte(u8 u8Byte) -{ - STD_tenuResult enuResultLoc = STD_OK; - - putchar_raw(u8Byte); - - return enuResultLoc; -} - -/* ========================================================================= */ -/* SEND BUFFER */ -/* ========================================================================= */ - -STD_tenuResult MCU_USB_enuSendBuffer(const u8 *pu8Data, u16 u16Length) -{ - STD_tenuResult enuResultLoc = STD_OK; - u16 u16IndexLoc; - - if (pu8Data == STD_NULL) - { - enuResultLoc = STD_NULL_POINTER_ERROR; - } - else - { - for (u16IndexLoc = 0U; u16IndexLoc < u16Length; u16IndexLoc++) - { - putchar_raw(pu8Data[u16IndexLoc]); - } - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* READ BYTE (NON-BLOCKING) */ -/* ========================================================================= */ - -STD_tenuResult MCU_USB_enuReadByte(u8 *pu8Byte) -{ - STD_tenuResult enuResultLoc = STD_OK; - - if (pu8Byte == STD_NULL) - { - enuResultLoc = STD_NULL_POINTER_ERROR; - } - else - { - /* Pull any pending data from SDK into our ring buffer */ - vDrainStdio(); - - if (u16RxHead == u16RxTail) - { - enuResultLoc = STD_NOK; - } - else - { - *pu8Byte = au8RxBuffer[u16RxTail]; - u16RxTail = (u16RxTail + 1U) & USB_RX_BUFFER_MASK; - } - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* READ BUFFER (NON-BLOCKING) */ -/* ========================================================================= */ - -STD_tenuResult MCU_USB_enuReadBuffer(u8 *pu8Data, u16 u16MaxLength, u16 *pu16Read) -{ - STD_tenuResult enuResultLoc = STD_OK; - - if ((pu8Data == STD_NULL) || (pu16Read == STD_NULL)) - { - enuResultLoc = STD_NULL_POINTER_ERROR; - } - else - { - vDrainStdio(); - - u16 u16CountLoc = 0U; - - while ((u16RxHead != u16RxTail) && (u16CountLoc < u16MaxLength)) - { - pu8Data[u16CountLoc] = au8RxBuffer[u16RxTail]; - u16RxTail = (u16RxTail + 1U) & USB_RX_BUFFER_MASK; - u16CountLoc++; - } - - *pu16Read = u16CountLoc; - - if (u16CountLoc == 0U) - { - enuResultLoc = STD_NOK; - } - } - - return enuResultLoc; -} - -/* ========================================================================= */ -/* RX DATA AVAILABLE CHECK */ -/* ========================================================================= */ - -STD_tBool MCU_USB_bIsRxDataAvailable(void) -{ - STD_tBool bResultLoc = STD_FALSE; - - vDrainStdio(); - - if (u16RxHead != u16RxTail) - { - bResultLoc = STD_TRUE; - } - - return bResultLoc; -} diff --git a/color_switcher/src/MCU_USB/prg/MCU_USB_priv.h b/color_switcher/src/MCU_USB/prg/MCU_USB_priv.h deleted file mode 100644 index 591d8e8..0000000 --- a/color_switcher/src/MCU_USB/prg/MCU_USB_priv.h +++ /dev/null @@ -1,18 +0,0 @@ -/****************************************************************************** - * File: MCU_USB_priv.h - * Component: MCU_USB - * Description: Private header for the MCU_USB driver. - * Contains internal macros, helper declarations, and any - * lower-level definitions that are only used inside this - * component itself. Nothing declared here is exposed to - * external components. - * - * Layer: MCU (hardware abstraction) - internal use only - *****************************************************************************/ - -#ifndef MCU_USB_PRIV_H -#define MCU_USB_PRIV_H - -/* Private declarations, internal macros and helpers will go here */ - -#endif /* MCU_USB_PRIV_H */ diff --git a/color_switcher/src/STD_TYPES/inc/STD_TYPES.h b/color_switcher/src/STD_TYPES/inc/STD_TYPES.h deleted file mode 100644 index f9f6ff3..0000000 --- a/color_switcher/src/STD_TYPES/inc/STD_TYPES.h +++ /dev/null @@ -1,288 +0,0 @@ -/****************************************************************************** - * File: STD_TYPES.h - * Component: STD_TYPES - * Description: Standard type definitions used across all components. - * Provides project-wide fixed-width integer typedefs, boolean - * types, and common return/status codes so that every module - * speaks the same "type language". - * - * Layer: Library (shared by all layers) - *****************************************************************************/ - -#ifndef STD_TYPES_H -#define STD_TYPES_H - -/* Standard type definitions will go here */ - -/* ************************************************************************** */ -/* ********************** PUBLIC TYPE DEFINITIONS **************************** */ -/* ************************************************************************** */ - -/** - * @addtogroup 1-LIB_TYP_Types - * @ingroup LIB_TYP - * @{ - */ - -/* ************************************************************************** */ -/* ************************ BASIC INTEGER TYPES ****************************** */ -/* ************************************************************************** */ - -/** - * @brief 8-bit unsigned integer type - * @details Size: 1 Byte, Range: [0 : 255] - */ -typedef unsigned char u8; -#define STD_u8MIN_VALUE ((u8)0) /**< Minimum value for u8 type */ -#define STD_u8MAX_VALUE ((u8)0xFF) /**< Maximum value for u8 type */ - -/** - * @brief 16-bit unsigned integer type - * @details Size: 2 Bytes, Range: [0 : 65535] - */ -typedef unsigned short int u16; -#define STD_u16MIN_VALUE ((u16)0) /**< Minimum value for u16 type */ -#define STD_u16MAX_VALUE ((u16)0xFFFFU) /**< Maximum value for u16 type */ - -/** - * @brief 32-bit unsigned integer type - * @details Size: 4 Bytes, Range: [0 : 4,294,967,295] - */ -typedef unsigned long int u32; -#define STD_u32MIN_VALUE ((u32)0) /**< Minimum value for u32 type */ -#define STD_u32MAX_VALUE ((u32)0xFFFFFFFFU) /**< Maximum value for u32 type */ - -/** - * @brief 64-bit unsigned integer type - * @details Size: 8 Bytes, Range: [0 : 18,446,744,073,709,551,615] - */ -typedef unsigned long long u64; -#define STD_u64MIN_VALUE ((u64)0) /**< Minimum value for u64 type */ -#define STD_u64MAX_VALUE ((u64)0xFFFFFFFFFFFFFFFFULL) /**< Maximum value for u64 type */ - -/** - * @brief 8-bit signed integer type - * @details Size: 1 Byte, Range: [-128 : 127] - */ -typedef signed char s8; -#define STD_s8MIN_VALUE ((s8)-128) /**< Minimum value for s8 type */ -#define STD_s8MAX_VALUE ((s8)127) /**< Maximum value for s8 type */ - -/** - * @brief 16-bit signed integer type - * @details Size: 2 Bytes, Range: [-32,768 : 32,767] - */ -typedef signed short int s16; -#define STD_s16MIN_VALUE ((s16)-32768) /**< Minimum value for s16 type */ -#define STD_s16MAX_VALUE ((s16)32767) /**< Maximum value for s16 type */ - -/** - * @brief 32-bit signed integer type - * @details Size: 4 Bytes, Range: [-2,147,483,648 : 2,147,483,647] - */ -typedef signed long int s32; -#define STD_s32MIN_VALUE ((s32)-2147483648) /**< Minimum value for s32 type */ -#define STD_s32MAX_VALUE ((s32)2147483647) /**< Maximum value for s32 type */ - -/** - * @brief 64-bit signed integer type - * @details Size: 8 Bytes, Range: [-9,223,372,036,854,775,808 : 9,223,372,036,854,775,807] - */ -typedef signed long long s64; -#define STD_s64MIN_VALUE ((s64)-9223372036854775807LL - 1LL) /**< Minimum value for s64 type */ -#define STD_s64MAX_VALUE ((s64)9223372036854775807LL) /**< Maximum value for s64 type */ - -/* ************************************************************************** */ -/* ************************* RESULT TYPES *********************************** */ -/* ************************************************************************** */ - -/** - * @brief Standard Result Type - * - * Enumeration for function return values indicating operation status - */ -typedef enum -{ - STD_OK = 0U, /**< Operation completed successfully */ - STD_INDEX_OUT_OF_RANGE_ERROR, /**< Array index out of bounds */ - STD_NULL_POINTER_ERROR, /**< Null pointer detected */ - STD_NOK /**< Operation failed */ -} STD_tenuResult; - -/* ************************************************************************** */ -/* ************************ CALLBACK TYPES ********************************** */ -/* ************************************************************************** */ - -/** - * @brief Callback Function Type - * @details Type definition for void callback functions - */ -typedef void (*STD_tpfCallbackFunc)(void); - -/** - * @brief Initialization Function Type - * @details Type definition for initialization functions returning STD_tenuResult - */ -typedef STD_tenuResult (*STD_tpfInitFunc)(void); - -/* ************************************************************************** */ -/* ************************ BOOLEAN AND STATE TYPES ************************* */ -/* ************************************************************************** */ - -/** - * @brief Boolean Type - * @details Standard boolean enumeration - */ -typedef enum -{ - STD_FALSE, /**< False value */ - STD_TRUE /**< True value */ -} STD_tBool; - -/** - * @brief State Type - * @details Standard state enumeration - */ -typedef enum -{ - STD_IDLE, /**< Idle state */ - STD_BUSY /**< Busy state */ -} STD_tenuState; - -/** - * @brief Compare State Type - * @details Type for comparison results - */ -typedef u8 STD_tu8CMPstate; - -/** @} */ // end of 1-LIB_TYP_Types group - - -/* ************************************************************************** */ -/* ************************* UTILITY MACROS ********************************* */ -/* ************************************************************************** */ - -/** - * @addtogroup 2-LIB_TYP_Macros - * @ingroup LIB_TYP - * @{ - */ - -/** @brief Null pointer definition */ -#define STD_NULL ((void *)0) - -/** - * @brief Constant qualifier macro - * @details Removes const qualifier in unit test builds - */ -#ifdef UTD -# define STD_CONST -#else -# define STD_CONST const -#endif - -/** - * @brief Static qualifier macro - * @details Removes static qualifier in unit test builds - */ -#ifdef UTD -# define STD_STATIC -#else -# define STD_STATIC static -#endif - -/** - * @brief Inline function macro - * @details Controls function inlining based on build type - */ -#ifdef UTD -# define STD_INLINE -#else -# define STD_INLINE __attribute__((always_inline)) inline -#endif - -/** - * @brief Interrupt function macro - * @details Marks functions as interrupts in non-test builds - */ -#ifdef UTD -# define STD_INTERRUPT -#else -# define STD_INTERRUPT __attribute__((interrupt)) -#endif - -/** - * @brief Non-inlined interrupt function macro - * @details Marks functions as non-inlined interrupts in non-test builds. This prevents - * the compiler from inlining interrupt service routines, which can be important - * for debugging and maintaining consistent interrupt latency. - */ -#ifdef UTD -# define STD_INTERRUPT_NO_INLINE -#else -# define STD_INTERRUPT_NO_INLINE __attribute__((interrupt, noinline)) -#endif - -/** - * @brief Weak symbol macro - * @details Marks symbols as weak in non-test builds - */ -#ifdef UTD -# define STD_WEAK -#else -# define STD_WEAK __attribute__((weak)) -#endif - -/** - * @brief Packed structure macro - * @details Forces packed memory layout - */ -#define STD_PACKED __attribute__((packed)) - -/** - * @brief 2-byte alignment macro - * @details Forces 2-byte alignment for structures and variables. - * Required for MLX16 architecture DMA buffers and optimal performance. - */ -#define STD_ALIGNED_2BYTE __attribute__((aligned(2))) - -/** - * @brief Switch case fallthrough macro - * @details Explicitly indicates intentional fallthrough in switch statements. - * Suppresses compiler warnings about implicit fallthrough between cases. - * Use this when you intentionally omit a break statement. - * @note Only available in GCC 7 and later - */ -#if __GNUC__ >= 7 -#define STD_FALLTHROUGH __attribute__((fallthrough)) -#else -#define STD_FALLTHROUGH -#endif - -/** - * @brief Static assertion macro - * @details Provides compile-time assertions for configuration validation. - * This macro abstracts the compiler-specific static assert mechanism - * allowing for easy portability across different compilers. - * - * @param condition The condition to assert (must be compile-time constant) - * @param message The error message to display if assertion fails - * - * @note For C11 compliant compilers, uses _Static_assert. - * For older compilers, falls back to a compatible implementation. - */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) - /* C11 and later: use standard _Static_assert */ - #define STD_STATIC_ASSERT(condition, message) _Static_assert(condition, message) -#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) - /* GCC 4.6+: use _Static_assert extension */ - #define STD_STATIC_ASSERT(condition, message) _Static_assert(condition, message) -#else - /* Fallback for older compilers: use array size trick */ - #define STD_STATIC_ASSERT(condition, message) \ - typedef char static_assertion_##__LINE__[(condition) ? 1 : -1] -#endif - -/** @} */ // end of 2-LIB_TYP_Macros group - -#endif /* STD_TYPES_H */ diff --git a/common/HAL_COM b/common/HAL_COM new file mode 160000 index 0000000..1cda81a --- /dev/null +++ b/common/HAL_COM @@ -0,0 +1 @@ +Subproject commit 1cda81a2dd2938598a8049808ab197ef8c1af45d diff --git a/common/HAL_LED b/common/HAL_LED new file mode 160000 index 0000000..b767b3c --- /dev/null +++ b/common/HAL_LED @@ -0,0 +1 @@ +Subproject commit b767b3c5b9cd4313f89e2184955b28e877431f8c diff --git a/common/MCU_PIO b/common/MCU_PIO new file mode 160000 index 0000000..48cd158 --- /dev/null +++ b/common/MCU_PIO @@ -0,0 +1 @@ +Subproject commit 48cd1588449581892e60dde3e002a2649fe3f4f2 diff --git a/common/MCU_UART b/common/MCU_UART new file mode 160000 index 0000000..5313ee9 --- /dev/null +++ b/common/MCU_UART @@ -0,0 +1 @@ +Subproject commit 5313ee98d21ca70d98ea6592961c2f6419d07b59 diff --git a/common/MCU_USB b/common/MCU_USB new file mode 160000 index 0000000..9cb8f89 --- /dev/null +++ b/common/MCU_USB @@ -0,0 +1 @@ +Subproject commit 9cb8f895714ebaaff1a6548c71d9dffbcab3ce65 diff --git a/common/STD_TYPES b/common/STD_TYPES new file mode 160000 index 0000000..dadad59 --- /dev/null +++ b/common/STD_TYPES @@ -0,0 +1 @@ +Subproject commit dadad59143bb6c8287b65d2841583f60f221fcc3