diff --git a/examples/chapter09_08a/src/app/led/app_led.cpp b/examples/chapter09_08a/src/app/led/app_led.cpp index 974c7eacf..871d9aac6 100644 --- a/examples/chapter09_08a/src/app/led/app_led.cpp +++ b/examples/chapter09_08a/src/app/led/app_led.cpp @@ -21,28 +21,25 @@ namespace app } } -namespace -{ - using app_led_monochrome_timer_type = util::timer; - using app_led_rgb_timer_type = util::timer; - - auto app_led_monochrome_timer = static_cast(app_led_monochrome_timer_type::seconds(UINT8_C(1))); - auto app_led_rgb_timer = static_cast(app_led_rgb_timer_type::milliseconds(UINT8_C(30))); - - std::uint_fast8_t app_led_hue_r { UINT8_C(255) }; - std::uint_fast8_t app_led_hue_g { UINT8_C(0) }; - std::uint_fast8_t app_led_hue_b { UINT8_C(0) }; -} - auto app::led::task_init() -> void { mcal::led::led0().toggle(); - mcal::led::led_rgb0().set_color(app_led_hue_r, app_led_hue_g, app_led_hue_b); + mcal::led::led_rgb0().set_color(UINT8_C(255), UINT8_C(0), UINT8_C(0)); } auto app::led::task_func() -> void { + using app_led_monochrome_timer_type = util::timer; + using app_led_rgb_timer_type = util::timer; + + static auto app_led_monochrome_timer = static_cast(app_led_monochrome_timer_type::seconds(UINT8_C(1))); + static auto app_led_rgb_timer = static_cast(app_led_rgb_timer_type::milliseconds(UINT8_C(30))); + + static std::uint_fast8_t app_led_hue_r { UINT8_C(255) }; + static std::uint_fast8_t app_led_hue_g { UINT8_C(0) }; + static std::uint_fast8_t app_led_hue_b { UINT8_C(0) }; + if(app_led_monochrome_timer.timeout()) { // Toggle the monochrome user LED at 1/2 Hz. @@ -52,6 +49,21 @@ auto app::led::task_func() -> void app_led_monochrome_timer.start_interval(app_led_monochrome_timer_type::seconds(1U)); } + // Define the color transition states. + enum class color_transition_type + { + red_to_yellow, + yellow_to_green, + green_to_cyan, + cyan_to_blue, + blue_to_magenta, + magenta_to_red + }; + + + // Initialize the color transition state. + static auto color_transition_state = color_transition_type::red_to_yellow; + if(app_led_rgb_timer.timeout()) { // Animate the RGB LED with the colors of the spectrum. @@ -59,20 +71,6 @@ auto app::led::task_func() -> void // Implement the enhanced RGB-color-light-show mentioned // in the readme markdown of this example. - // Define the color transition states. - enum class color_transition_type - { - red_to_yellow, - yellow_to_green, - green_to_cyan, - cyan_to_blue, - blue_to_magenta, - magenta_to_red - }; - - // Initialize the color transition state. - static auto color_transition_state = color_transition_type::red_to_yellow; - const auto rgb_hue_sum = static_cast ( diff --git a/examples/chapter09_08a/src/mcal/avr/mcal_led_rgb_ws2812.h b/examples/chapter09_08a/src/mcal/avr/mcal_led_rgb_ws2812.h index e9b26af65..b36ad70be 100644 --- a/examples/chapter09_08a/src/mcal/avr/mcal_led_rgb_ws2812.h +++ b/examples/chapter09_08a/src/mcal/avr/mcal_led_rgb_ws2812.h @@ -45,23 +45,26 @@ } }; - // Timing of WS2812. + // Timing of WS2812B. // Next bit is 0: - // T0H = 0.35us - // T0L = 0.80us + // T0H = 220-380ns + // T0L = 580ns - 1us // Next bit is 1: - // T1H = 0.70us - // T1L = 0.60us + // T1H = 580ns - 1us + // T1L = 220-420ns + #define MCAL_LED_RGB_WS2812_NOPS_01 { asm volatile("nop"); } #define MCAL_LED_RGB_WS2812_NOPS_02 { asm volatile("nop"); asm volatile("nop"); } - #define MCAL_LED_RGB_WS2812_NOPS_06 { MCAL_LED_RGB_WS2812_NOPS_02 MCAL_LED_RGB_WS2812_NOPS_02 MCAL_LED_RGB_WS2812_NOPS_02 } - #define MCAL_LED_RGB_WS2812_NOPS_11 { MCAL_LED_RGB_WS2812_NOPS_06 MCAL_LED_RGB_WS2812_NOPS_02 MCAL_LED_RGB_WS2812_NOPS_02 asm volatile("nop"); } + #define MCAL_LED_RGB_WS2812_NOPS_03 { MCAL_LED_RGB_WS2812_NOPS_02 MCAL_LED_RGB_WS2812_NOPS_01 } + #define MCAL_LED_RGB_WS2812_NOPS_06 { MCAL_LED_RGB_WS2812_NOPS_03 MCAL_LED_RGB_WS2812_NOPS_03 } + #define MCAL_LED_RGB_WS2812_NOPS_08 { MCAL_LED_RGB_WS2812_NOPS_06 MCAL_LED_RGB_WS2812_NOPS_02 } + #define MCAL_LED_RGB_WS2812_NOPS_11 { MCAL_LED_RGB_WS2812_NOPS_08 MCAL_LED_RGB_WS2812_NOPS_03 } #define MCAL_LED_RGB_WS2812_PUSH_DATA(next_bit_is_zero) port_pin_type::set_pin_high(); \ - if (next_bit_is_zero) { MCAL_LED_RGB_WS2812_NOPS_02 port_pin_type::set_pin_low(); MCAL_LED_RGB_WS2812_NOPS_11 } \ - else { MCAL_LED_RGB_WS2812_NOPS_06 port_pin_type::set_pin_low(); MCAL_LED_RGB_WS2812_NOPS_06 } + if (next_bit_is_zero) { MCAL_LED_RGB_WS2812_NOPS_01 port_pin_type::set_pin_low(); MCAL_LED_RGB_WS2812_NOPS_11 } \ + else { MCAL_LED_RGB_WS2812_NOPS_08 port_pin_type::set_pin_low(); MCAL_LED_RGB_WS2812_NOPS_02 } template auto led_rgb_ws2812::push_color() -> void @@ -104,21 +107,14 @@ mcal::irq::enable_all(); } - #if defined(MCAL_LED_RGB_WS2812_PUSH_DATA) #undef MCAL_LED_RGB_WS2812_PUSH_DATA - #endif - #if defined(MCAL_LED_RGB_WS2812_NOPS_02) + #undef MCAL_LED_RGB_WS2812_NOPS_01 #undef MCAL_LED_RGB_WS2812_NOPS_02 - #endif - - #if defined(MCAL_LED_RGB_WS2812_NOPS_06) + #undef MCAL_LED_RGB_WS2812_NOPS_03 #undef MCAL_LED_RGB_WS2812_NOPS_06 - #endif - - #if defined(MCAL_LED_RGB_WS2812_NOPS_11) + #undef MCAL_LED_RGB_WS2812_NOPS_08 #undef MCAL_LED_RGB_WS2812_NOPS_11 - #endif } } // namespace mcal::led diff --git a/examples/chapter09_08a/src/mcal/mcal_gcc_cxx_completion.cpp b/examples/chapter09_08a/src/mcal/mcal_gcc_cxx_completion.cpp index ed32e0112..0e9d10e73 100644 --- a/examples/chapter09_08a/src/mcal/mcal_gcc_cxx_completion.cpp +++ b/examples/chapter09_08a/src/mcal/mcal_gcc_cxx_completion.cpp @@ -16,33 +16,6 @@ #pragma GCC diagnostic ignored "-Wmissing-declarations" #endif -// Implement std::chrono::high_resolution_clock::now() -// for the standard library's high-resolution clock. -namespace std -{ - namespace chrono - { - high_resolution_clock::time_point high_resolution_clock::now() noexcept - { - // The source of the high-resolution clock is microseconds. - using microsecond_time_point_type = - std::chrono::time_point; - - // Get the consistent system tick (having microsecond resolution). - const mcal::gpt::value_type microsecond_tick = - mcal::gpt::secure::get_time_elapsed(); - - // Obtain a time-point with microsecond resolution. - const auto time_point_in_microseconds = - microsecond_time_point_type(std::chrono::microseconds(microsecond_tick)); - - // And return the corresponding duration with microsecond resolution. - return time_point_cast(time_point_in_microseconds); - } - } -} - void* operator new(std::size_t size) { // This is a naive and not completely functional diff --git a/examples/chapter09_08b/readme.md b/examples/chapter09_08b/readme.md index e610f4a03..fe55bcf33 100644 --- a/examples/chapter09_08b/readme.md +++ b/examples/chapter09_08b/readme.md @@ -13,6 +13,9 @@ the commercially-available, open-platform [STM32F100 Value Line Discovery Kit](https://www.st.com/en/evaluation-tools/stm32vldiscovery.html) with soldered-on pins fitted on a breadboard. -The wiring is straightforward. The blinking LED uses the blue colored -user LED controlled by pin `portc.8`. The LED digital control signal -is on `portb.9`. The microcontroller is clocked at $24~\text{MHz}$. +The wiring is straightforward. The blinking LED at $\frac{1}{2}~\text{Hz}$ +uses the blue colored user-LED controlled by pin `portc.8`. +The RGB LED digital control signal is on `portb.9`. +A logic-AND gate shifts the microcontroller pin's level +from $3.3~\text{V}$ to $5~\text{V}$. +The microcontroller is clocked at $24~\text{MHz}$. diff --git a/examples/chapter09_08b/src/mcal/mcal_reg_access_static.h b/examples/chapter09_08b/src/mcal/mcal_reg_access_static.h index 564c3dc2f..93cb83008 100644 --- a/examples/chapter09_08b/src/mcal/mcal_reg_access_static.h +++ b/examples/chapter09_08b/src/mcal/mcal_reg_access_static.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2024. +// Copyright Christopher Kormanyos 2007 - 2025. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -26,18 +26,18 @@ using register_value_type = RegisterValueType; using register_address_type = RegisterAddressType; - static auto reg_get() -> register_value_type { volatile register_value_type* pa = reinterpret_cast(address); return *pa; } - static auto reg_set() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = value; } - static auto reg_and() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa & value); } - static auto reg_or () -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa | value); } - static auto reg_not() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa & static_cast(~value)); } + static auto reg_get() -> register_value_type { volatile register_value_type* p_addr = reinterpret_cast(address); return *p_addr; } + static auto reg_set() -> void { volatile register_value_type* p_addr = reinterpret_cast(address); *p_addr = value; } + static auto reg_and() -> void { volatile register_value_type* p_addr = reinterpret_cast(address); *p_addr = static_cast(*p_addr & value); } + static auto reg_or () -> void { volatile register_value_type* p_addr = reinterpret_cast(address); *p_addr = static_cast(*p_addr | value); } + static auto reg_not() -> void { volatile register_value_type* p_addr = reinterpret_cast(address); *p_addr = static_cast(*p_addr & static_cast(~value)); } template static auto reg_msk() -> void { - volatile register_value_type* pa = reinterpret_cast(address); + volatile register_value_type* p_addr = reinterpret_cast(address); - *pa = + *p_addr = static_cast ( static_cast(reg_get() & static_cast(~mask_value)) @@ -45,9 +45,9 @@ ); } - static auto bit_set() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa | static_cast(1ULL << value)); } - static auto bit_clr() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa & static_cast(~static_cast(1ULL << value))); } - static auto bit_not() -> void { volatile register_value_type* pa = reinterpret_cast(address); *pa = static_cast(*pa ^ static_cast(1ULL << value)); } + static auto bit_set() -> void { volatile register_value_type* p_addr = reinterpret_cast(address); *p_addr = static_cast(*p_addr | static_cast(1ULL << value)); } + static auto bit_clr() -> void { volatile register_value_type* p_addr = reinterpret_cast(address); *p_addr = static_cast(*p_addr & static_cast(~static_cast(1ULL << value))); } + static auto bit_not() -> void { volatile register_value_type* p_addr = reinterpret_cast(address); *p_addr = static_cast(*p_addr ^ static_cast(1ULL << value)); } static auto bit_get() -> bool { return (static_cast(reg_get() & static_cast(1ULL << value)) != static_cast(0U)); } }; } diff --git a/examples/chapter09_08b/src/mcal/stm32f100/mcal_led_rgb_ws2812.h b/examples/chapter09_08b/src/mcal/stm32f100/mcal_led_rgb_ws2812.h index e8f441a8d..eb8fdbf19 100644 --- a/examples/chapter09_08b/src/mcal/stm32f100/mcal_led_rgb_ws2812.h +++ b/examples/chapter09_08b/src/mcal/stm32f100/mcal_led_rgb_ws2812.h @@ -45,25 +45,26 @@ } }; - // Timing of WS2812. + // Timing of WS2812B. // Next bit is 0: - // T0H = 0.35us - // T0L = 0.80us + // T0H = 220-380ns + // T0L = 580ns - 1us // Next bit is 1: - // T1H = 0.70us - // T1L = 0.60us + // T1H = 580ns - 1us + // T1L = 220-420ns #define MCAL_LED_RGB_WS2812_NOPS_01 { asm volatile("nop"); } #define MCAL_LED_RGB_WS2812_NOPS_02 { MCAL_LED_RGB_WS2812_NOPS_01 MCAL_LED_RGB_WS2812_NOPS_01 } - #define MCAL_LED_RGB_WS2812_NOPS_05 { MCAL_LED_RGB_WS2812_NOPS_02 MCAL_LED_RGB_WS2812_NOPS_02 MCAL_LED_RGB_WS2812_NOPS_01 } - #define MCAL_LED_RGB_WS2812_NOPS_06 { MCAL_LED_RGB_WS2812_NOPS_02 MCAL_LED_RGB_WS2812_NOPS_02 MCAL_LED_RGB_WS2812_NOPS_02 } - #define MCAL_LED_RGB_WS2812_NOPS_10 { MCAL_LED_RGB_WS2812_NOPS_05 MCAL_LED_RGB_WS2812_NOPS_05 } + #define MCAL_LED_RGB_WS2812_NOPS_03 { MCAL_LED_RGB_WS2812_NOPS_02 MCAL_LED_RGB_WS2812_NOPS_01 } + #define MCAL_LED_RGB_WS2812_NOPS_09 { MCAL_LED_RGB_WS2812_NOPS_03 MCAL_LED_RGB_WS2812_NOPS_03 MCAL_LED_RGB_WS2812_NOPS_03 } + #define MCAL_LED_RGB_WS2812_NOPS_12 { MCAL_LED_RGB_WS2812_NOPS_09 MCAL_LED_RGB_WS2812_NOPS_03 } - #define MCAL_LED_RGB_WS2812_PUSH_DATA(next_bit_is_zero) port_pin_type::set_pin_high(); \ - if (next_bit_is_zero) { port_pin_type::set_pin_low(); MCAL_LED_RGB_WS2812_NOPS_10 MCAL_LED_RGB_WS2812_NOPS_02 } \ - else { MCAL_LED_RGB_WS2812_NOPS_06 MCAL_LED_RGB_WS2812_NOPS_02 port_pin_type::set_pin_low(); MCAL_LED_RGB_WS2812_NOPS_05 } + #define MCAL_LED_RGB_WS2812_PUSH_DATA(next_bit_is_zero) \ + port_pin_type::set_pin_high(); \ + if (next_bit_is_zero) { port_pin_type::set_pin_low(); MCAL_LED_RGB_WS2812_NOPS_12 } \ + else { MCAL_LED_RGB_WS2812_NOPS_09 port_pin_type::set_pin_low(); } template auto led_rgb_ws2812::push_color() -> void @@ -106,29 +107,11 @@ mcal::irq::enable_all(); } - #if defined(MCAL_LED_RGB_WS2812_PUSH_DATA) - #undef MCAL_LED_RGB_WS2812_PUSH_DATA - #endif - - #if defined(MCAL_LED_RGB_WS2812_NOPS_01) #undef MCAL_LED_RGB_WS2812_NOPS_01 - #endif - - #if defined(MCAL_LED_RGB_WS2812_NOPS_02) #undef MCAL_LED_RGB_WS2812_NOPS_02 - #endif - - #if defined(MCAL_LED_RGB_WS2812_NOPS_05) - #undef MCAL_LED_RGB_WS2812_NOPS_05 - #endif - - #if defined(MCAL_LED_RGB_WS2812_NOPS_06) - #undef MCAL_LED_RGB_WS2812_NOPS_06 - #endif - - #if defined(MCAL_LED_RGB_WS2812_NOPS_10) - #undef MCAL_LED_RGB_WS2812_NOPS_10 - #endif + #undef MCAL_LED_RGB_WS2812_NOPS_03 + #undef MCAL_LED_RGB_WS2812_NOPS_09 + #undef MCAL_LED_RGB_WS2812_NOPS_12 } } // namespace mcal::led