diff --git a/.github/workflows/build-atmega1284p-debug.yaml b/.github/workflows/build-atmega1284p-debug.yaml index 8ae509e..3c7ee80 100644 --- a/.github/workflows/build-atmega1284p-debug.yaml +++ b/.github/workflows/build-atmega1284p-debug.yaml @@ -14,21 +14,21 @@ jobs: build: runs-on: ubuntu-latest steps: - + - name: Install # Install AVR GCC toolchain run : | sudo apt-get update - sudo apt-get install -y gcc-avr binutils-avr avr-libc cmake make - + sudo apt-get install -y avr-libc binutils-avr cmake doxygen gcc-avr graphviz make + - name: Check Out # Check out latest code uses: actions/checkout@v4 - + - name: Configure # Configure build environment in build/ directory run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - + - name: Build # Execute the build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} @@ -39,7 +39,7 @@ jobs: with: name: superkey.elf path: build/superkey.elf - + - name: Upload Artifact (superkey.elf.stripped) # Upload stripped ELF file uses: actions/upload-artifact@v4 @@ -53,18 +53,18 @@ jobs: with: name: superkey.ihex path: build/superkey.ihex - + - name: Upload Artifact (superkey.map) # Upload memory map file uses: actions/upload-artifact@v4 with: name: superkey.map path: build/superkey.map - + - name: Upload Artifact (superkey.txt) # Upload executable text dump uses: actions/upload-artifact@v4 with: name: superkey.txt path: build/superkey.txt - + diff --git a/.github/workflows/build-atmega1284p-release.yaml b/.github/workflows/build-atmega1284p-release.yaml index 5c659bd..0d2913d 100644 --- a/.github/workflows/build-atmega1284p-release.yaml +++ b/.github/workflows/build-atmega1284p-release.yaml @@ -14,21 +14,21 @@ jobs: build: runs-on: ubuntu-latest steps: - + - name: Install # Install AVR GCC toolchain run : | sudo apt-get update - sudo apt-get install -y gcc-avr binutils-avr avr-libc cmake make - + sudo apt-get install -y avr-libc binutils-avr cmake doxygen gcc-avr graphviz make + - name: Check Out # Check out latest code uses: actions/checkout@v4 - + - name: Configure # Configure build environment in build/ directory run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - + - name: Build # Execute the build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} @@ -39,7 +39,7 @@ jobs: with: name: superkey.elf path: build/superkey.elf - + - name: Upload Artifact (superkey.elf.stripped) # Upload stripped ELF file uses: actions/upload-artifact@v4 @@ -53,18 +53,18 @@ jobs: with: name: superkey.ihex path: build/superkey.ihex - + - name: Upload Artifact (superkey.map) # Upload memory map file uses: actions/upload-artifact@v4 with: name: superkey.map path: build/superkey.map - + - name: Upload Artifact (superkey.txt) # Upload executable text dump uses: actions/upload-artifact@v4 with: name: superkey.txt path: build/superkey.txt - + diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index ac3fbd9..3b4fd1f 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,7 +4,6 @@ "name": "AVR (ATMega1284P)", "includePath": [ "${workspaceFolder}/build/autogen/superkey", - "${workspaceFolder}/lib", "${workspaceFolder}/src/main" ], "defines": [ diff --git a/CMakeLists.txt b/CMakeLists.txt index dd373cc..38a4352 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ cmake_minimum_required(VERSION 3.22) # -- Packages -- +find_package(Doxygen REQUIRED) find_package(Git REQUIRED) # -- Project Configuration -- @@ -104,6 +105,34 @@ add_link_options( -mmcu=${DEVICE_MCU} ) +# -- Documentation Setup -- + +# CMake will automatically generate the Doxyfile in the build directory based on the Doxyfile.in template +set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) +set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + +# Set Doxygen options +set(DOXYGEN_EXTRACT_ALL NO) +set(DOXYGEN_WARN_IF_UNDOCUMENTED YES) +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(DOXYGEN_EXTRACT_ALL YES) + set(DOXYGEN_WARN_IF_UNDOCUMENTED NO) +endif() + +# Configure the Doxyfile +configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) + +# Add custom target for Doxygen +# (Running `make doxygen` will build the documents in the build directory) +add_custom_target( + doxygen + ALL + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating documentation with Doxygen" + VERBATIM +) + # -- Subdirectories -- # Main executable diff --git a/Doxyfile.in b/Doxyfile.in new file mode 100644 index 0000000..a0b9a54 --- /dev/null +++ b/Doxyfile.in @@ -0,0 +1,24 @@ +# +# @file Doxyfile +# @brief Doxyfile for generating Doxygen documentation. +# +# @author Chris Vig (chris@invictus.so) +# @date 2025-08-25 +# +# NOTE: +# CMake processes Doxyfile.in in the root directory, and saves it to build/Doxyfile, which is then used to generate the +# documentation with Doxygen by running `make doxygen`. +# + +PROJECT_NAME = @PROJECT_NAME@ +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/docs +INPUT = @CMAKE_SOURCE_DIR@/readme.md \ + @CMAKE_SOURCE_DIR@/src +RECURSIVE = YES +EXTRACT_ALL = @DOXYGEN_EXTRACT_ALL@ +WARN_IF_UNDOCUMENTED = @DOXYGEN_WARN_IF_UNDOCUMENTED@ +GENERATE_LATEX = NO +GENERATE_HTML = YES +EXCLUDE_SYMBOLS = _Static_assert ISR +USE_MDFILE_AS_MAINPAGE = @CMAKE_SOURCE_DIR@/readme.md +MARKDOWN_SUPPORT = YES \ No newline at end of file diff --git a/configuration.cmake b/configuration.cmake index 92fd7ba..5566c3d 100644 --- a/configuration.cmake +++ b/configuration.cmake @@ -49,7 +49,6 @@ set(CONFIG_DFLT_KEYER_OUTPUT_ACTIVE_LOW true set(CONFIG_DFLT_KEYER_INVERT_PADDLES false CACHE STRING "Set to true to invert the paddles. (true / false)") - # Set defines add_compile_definitions( _CONFIG_DFLT_WPM=${CONFIG_DFLT_WPM} diff --git a/readme.md b/readme.md index 0a75ad7..c7fe525 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# `SUPERKEY` +# SuperKey **SuperKey** - the greatest CW keyer the world has ever seen. @@ -6,12 +6,14 @@ This will be a README someday. ## Build Status -[![Build - AVR ATmega1284P (Debug)](https://github.com/xchrishawk/superkey/actions/workflows/build-atmega1284p-debug.yaml/badge.svg)](https://github.com/xchrishawk/superkey/actions/workflows/build-atmega1284p-debug.yaml) +[![Build - AVR ATmega1284P (Debug)](https://github.com/xchrishawk/superkey/actions/workflows/build-atmega1284p-debug.yaml/badge.svg)](https://github.com/xchrishawk/superkey/actions/workflows/build-atmega1284p-debug.yaml)
[![Build - AVR ATmega1284P (Release)](https://github.com/xchrishawk/superkey/actions/workflows/build-atmega1284p-release.yaml/badge.svg)](https://github.com/xchrishawk/superkey/actions/workflows/build-atmega1284p-release.yaml) ## Notes -### `avrdude` Upload Command +### Upload Command + +The executable is uploaded to the MCU using [`avrdude`](https://www.nongnu.org/avrdude/) and an [AVRISP mkII programmer](https://a.co/d/59zSwb5). ``` avrdude -c avrispmkii -P usb -p m1284p -U flash:w:superkey.ihex -D diff --git a/src/main/application/config.c b/src/main/application/config.c index ec2b8c8..fa97fbe 100644 --- a/src/main/application/config.c +++ b/src/main/application/config.c @@ -1,5 +1,5 @@ /** - * @file src/main/core/config.c + * @file src/main/application/config.c * @brief Implementation for the application configuration module. * * @author Chris Vig (chris@invictus.so) diff --git a/src/main/application/config.h b/src/main/application/config.h index 3410a6f..63996f1 100644 --- a/src/main/application/config.h +++ b/src/main/application/config.h @@ -23,7 +23,7 @@ /* ----------------------------------------------------- TYPES ------------------------------------------------------ */ /** - * @typedef config_t + * @struct config_t * @brief Struct containing the current application configuration information. */ typedef struct diff --git a/src/main/application/debug_port.c b/src/main/application/debug_port.c index c050a42..d013b58 100644 --- a/src/main/application/debug_port.c +++ b/src/main/application/debug_port.c @@ -63,7 +63,7 @@ #define DISABLED_STR "disabled" /** - * @define OFF_STR + * @def OFF_STR * @brief The token which indicates that an input or output is off. */ #define OFF_STR "off" diff --git a/src/main/application/input.c b/src/main/application/input.c index 4d87a72..25b34f6 100644 --- a/src/main/application/input.c +++ b/src/main/application/input.c @@ -35,11 +35,24 @@ _Static_assert( array_count( s_pin_tbl ) == INPUT_PIN_COUNT, "Invalid pin table! /* ----------------------------------------------------- MACROS ----------------------------------------------------- */ -// Validation macros +/** + * @def validate_pin( _pin ) + * @brief Validates that the specified `input_pin_t` is valid. + */ #define validate_pin( _pin ) \ assert_always( ( _pin ) < INPUT_PIN_COUNT ) + +/** + * @def validate_polarity( _polarity ) + * @brief Validates that the specified `input_polarity_t` is valid. + */ #define validate_polarity( _polarity ) \ assert_always( ( _polarity ) < INPUT_POLARITY_COUNT ) + +/** + * @def validate_type( _type ) + * @brief Validates that the specified `input_type_t` is valid. + */ #define validate_type( _input ) \ assert_always( ( _input ) < INPUT_TYPE_COUNT ) diff --git a/src/main/application/input.h b/src/main/application/input.h index e931da2..7a97088 100644 --- a/src/main/application/input.h +++ b/src/main/application/input.h @@ -54,7 +54,7 @@ enum }; /** - * @typedef input_type_tt + * @typedef input_type_t * @brief Enumeration of the supported input types. */ typedef uint8_t input_type_t; diff --git a/src/main/application/keyer.c b/src/main/application/keyer.c index 9312005..c6cd2a1 100644 --- a/src/main/application/keyer.c +++ b/src/main/application/keyer.c @@ -89,11 +89,24 @@ static tick_t s_space_ticks = 0; /**< Number of ticks per element spa /* ----------------------------------------------------- MACROS ----------------------------------------------------- */ -// Utility macros +/** + * @def is_timeout_elapsed( _tick, _duration ) + * @brief Returns `true` if the specified timeout has elapsed at the specified tick. + */ #define is_timeout_elapsed( _tick, _duration ) \ ( sys_elapsed( ( _tick ), s_element_start ) > ( _duration ) ) + +/** + * @def is_duration_elapsed( _tick ) + * @brief Returns `true` if the `s_element_duration` timeout has elapsed at the specified tick. + */ #define is_duration_elapsed( _tick ) \ is_timeout_elapsed( _tick, s_element_duration ) + +/** + * @def is_lockout_elapsed( _tick ) + * @brief Returns `true` if the `s_element_lockout` timeout has elapsed at the specified tick. + */ #define is_lockout_elapsed( _tick ) \ is_timeout_elapsed( _tick, s_element_lockout ) @@ -136,7 +149,7 @@ static void do_state_on( tick_t tick, bool new_state ); static bool get_keyed( void ); /** - * @fn next_state( void ) + * @fn get_next_state( void ) * @brief Returns the next keyer state, based on current inputs. */ static state_t get_next_state( void ); diff --git a/src/main/application/keyer.h b/src/main/application/keyer.h index f916584..d326ad7 100644 --- a/src/main/application/keyer.h +++ b/src/main/application/keyer.h @@ -64,7 +64,7 @@ bool keyer_get_invert_paddles( void ); keyer_mode_t keyer_get_mode( void ); /** - * @fn keyer_get_active_low( void ) + * @fn keyer_get_output_active_low( void ) * @brief Returns `true` if the keyer's output is active low. */ bool keyer_get_output_active_low( void ); diff --git a/src/main/application/wpm.c b/src/main/application/wpm.c index ee465f6..80822db 100644 --- a/src/main/application/wpm.c +++ b/src/main/application/wpm.c @@ -50,6 +50,7 @@ void wpm_set( wpm_t wpm ) } /* wpm_set() */ + void wpm_ticks( wpm_t wpm, tick_t * dot, tick_t * dash, diff --git a/src/main/application/wpm.h b/src/main/application/wpm.h index 6b13fef..780af49 100644 --- a/src/main/application/wpm.h +++ b/src/main/application/wpm.h @@ -61,7 +61,7 @@ wpm_t wpm_get( void ); void wpm_set( wpm_t wpm ); /** - * @fn wpm_ticks( wpm, tick_t *, tick_t *, tick_t *, tick_t *, tick_t * ) + * @fn wpm_ticks( wpm_t, tick_t *, tick_t *, tick_t *, tick_t *, tick_t * ) * @brief Calculates the duration (in ticks) of various Morse code elements. * @note This function does floating-point math and should not be called frequently. */ diff --git a/src/main/core/main.c b/src/main/core/main.c index 9543386..fb7a48b 100644 --- a/src/main/core/main.c +++ b/src/main/core/main.c @@ -30,13 +30,32 @@ /* --------------------------------------------------- CONSTANTS ---------------------------------------------------- */ -// Periodic processing periods in ticks +/** + * @def TICKS_1_MS + * @brief Number of ticks for 1 millisecond tasks. + */ #define TICKS_1_MS ( 1 * TICKS_PER_MSEC ) + +/** + * @def TICKS_50_MS + * @brief Number of ticks for 50 millisecond tasks. + */ #define TICKS_50_MS ( 50 * TICKS_PER_MSEC ) + +/** + * @def TICKS_1_S + * @brief Number of ticks for 1 second tasks. + */ #define TICKS_1_S ( 1 * TICKS_PER_SEC ) /* ---------------------------------------------- PROCEDURE PROTOTYPES ---------------------------------------------- */ +/** + * @fn main( void ) + * @brief Main entry point for the application. + */ +int main( void ); + /** * @fn handle_input_state( void ) * @brief Handles the `EVENT_INPUT_STATE` event. @@ -71,7 +90,7 @@ static void init( void ); * @fn main_loop( void ) * @brief Runs the main loop of the application. */ -static void main_loop( void ) FUNC_NEVER_RETURNS; +static void main_loop( void ); /** * @fn periodic_1ms( tick_t ) diff --git a/src/main/core/sys.c b/src/main/core/sys.c index 50d5a5d..f4c6b1f 100644 --- a/src/main/core/sys.c +++ b/src/main/core/sys.c @@ -23,7 +23,7 @@ /* --------------------------------------------------- CONSTANTS ---------------------------------------------------- */ /** - * @def TEST_CLOCK_WRAPAROUND + * @def DEBUG_TEST_CLOCK_WRAPAROUND * @brief If set to `ON`, the system tick will be set to 15 seconds prior to a wraparound at startup. */ #define DEBUG_TEST_CLOCK_WRAPAROUND ON @@ -35,7 +35,10 @@ static tick_t s_tick = 0; /**< Current system tick. /* ----------------------------------------------------- MACROS ----------------------------------------------------- */ -// Validation macros +/** + * @def validate_event( _event ) + * @brief Ensures that the specified `event_t` is valid. + */ #define validate_event( _event ) \ assert_always( ( _event ) < EVENT_COUNT ) diff --git a/src/main/core/version.c b/src/main/core/version.c index 97558cb..4182e7e 100644 --- a/src/main/core/version.c +++ b/src/main/core/version.c @@ -14,9 +14,22 @@ /* --------------------------------------------------- CONSTANTS ---------------------------------------------------- */ -// Manually maintained +/** + * @def VERSION_MAJOR + * @brief The application's current major version number. + */ #define VERSION_MAJOR 0 + +/** + * @def VERSION_MINOR + * @brief The application's current minor version number. + */ #define VERSION_MINOR 1 + +/** + * @def VERSION_REVISION + * @brief The application's current revision version number. + */ #define VERSION_REVISION 0 // Public variables diff --git a/src/main/core/version.h b/src/main/core/version.h index d85e219..7f532c1 100644 --- a/src/main/core/version.h +++ b/src/main/core/version.h @@ -27,7 +27,7 @@ extern uint8_t const PRODUCT_VERSION_REVISION; /* ----------------------------------------------------- TYPES ------------------------------------------------------ */ /** - * @typedef version_t + * @struct version_t * @brief Struct containing version information for the application. */ typedef struct diff --git a/src/main/doxygen.dox b/src/main/doxygen.dox new file mode 100644 index 0000000..0fc5903 --- /dev/null +++ b/src/main/doxygen.dox @@ -0,0 +1,37 @@ +/** + * @file src/main/doxygen.dox + * @brief Dummy header file containing Doxygen documentation commands. + * + * @author Chris Vig (chris@invictus.so) + * @date 2025-08-25 + */ + +/** + * @dir src + * @brief Source directory for all executables. + */ + +/** + * @dir src/main + * @brief Source directory for the main SuperKey application. + */ + +/** + * @dir src/main/application + * @brief Directory containing application-level implementation. + */ + +/** + * @dir src/main/core + * @brief Directory containing core system-level functionality. + */ + +/** + * @dir src/main/drivers + * @brief Directory containing low-level hardware drivers. + */ + +/** + * @dir src/main/utility + * @brief Directory containing miscellaneous utility functionality. + */ diff --git a/src/main/drivers/gpio.h b/src/main/drivers/gpio.h index b9b5045..af6a7ae 100644 --- a/src/main/drivers/gpio.h +++ b/src/main/drivers/gpio.h @@ -157,14 +157,14 @@ gpio_state_t gpio_get_state( gpio_pin_t pin ); void gpio_set_dir( gpio_pin_t pin, gpio_dir_t dir ); /** - * @fn gpio_set_pcint_enabled_pin( gpio_pin_t ) + * @fn gpio_set_pcint_enabled_pin( gpio_pin_t, bool ) * @brief Enables or disables the pin change interrupt for the specified GPIO pin. * @note The interrupt must also be enabled on the corresponding GPIO port - see `gpio_set_pcint_enabled_port()`. */ void gpio_set_pcint_enabled_pin( gpio_pin_t pin, bool enabled ); /** - * @fn gpio_set_pcint_enabled_port( gpio_port_t ) + * @fn gpio_set_pcint_enabled_port( gpio_port_t, bool ) * @brief Enables or disables the pin change interrupt for the specified GPIO port. * @note The interrupt must also be enabled on the corresponding GPIO pin - see `gpio_set_pcint_enabled_pin()`. */ diff --git a/src/main/utility/debug.h b/src/main/utility/debug.h index 539a360..34515da 100644 --- a/src/main/utility/debug.h +++ b/src/main/utility/debug.h @@ -44,7 +44,7 @@ void fail( void ) FUNC_NEVER_RETURNS; /** - * @fn fail( uint8_t ) + * @fn fail_code( uint8_t ) * @brief Aborts the application. Enters an infinite loop which flashes the specified code on the status LED. */ void fail_code( uint8_t code ) FUNC_NEVER_RETURNS;