Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 26 additions & 28 deletions examples/chapter09_08a/src/app/led/app_led.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,25 @@ namespace app
}
}

namespace
{
using app_led_monochrome_timer_type = util::timer<std::uint32_t>;
using app_led_rgb_timer_type = util::timer<std::uint16_t>;

auto app_led_monochrome_timer = static_cast<app_led_monochrome_timer_type>(app_led_monochrome_timer_type::seconds(UINT8_C(1)));
auto app_led_rgb_timer = static_cast<app_led_rgb_timer_type>(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<std::uint32_t>;
using app_led_rgb_timer_type = util::timer<std::uint16_t>;

static auto app_led_monochrome_timer = static_cast<app_led_monochrome_timer_type>(app_led_monochrome_timer_type::seconds(UINT8_C(1)));
static auto app_led_rgb_timer = static_cast<app_led_rgb_timer_type>(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.
Expand All @@ -52,27 +49,28 @@ 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.

// 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<std::uint_fast16_t>
(
Expand Down
34 changes: 15 additions & 19 deletions examples/chapter09_08a/src/mcal/avr/mcal_led_rgb_ws2812.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<typename PortPinType,
const unsigned LedCount> auto led_rgb_ws2812<PortPinType, LedCount>::push_color() -> void
Expand Down Expand Up @@ -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

Expand Down
27 changes: 0 additions & 27 deletions examples/chapter09_08a/src/mcal/mcal_gcc_cxx_completion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<high_resolution_clock,
std::chrono::microseconds>;

// 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<duration>(time_point_in_microseconds);
}
}
}

void* operator new(std::size_t size)
{
// This is a naive and not completely functional
Expand Down
9 changes: 6 additions & 3 deletions examples/chapter09_08b/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}$.
22 changes: 11 additions & 11 deletions examples/chapter09_08b/src/mcal/mcal_reg_access_static.h
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -26,28 +26,28 @@
using register_value_type = RegisterValueType;
using register_address_type = RegisterAddressType;

static auto reg_get() -> register_value_type { volatile register_value_type* pa = reinterpret_cast<register_value_type*>(address); return *pa; }
static auto reg_set() -> void { volatile register_value_type* pa = reinterpret_cast<volatile register_value_type*>(address); *pa = value; }
static auto reg_and() -> void { volatile register_value_type* pa = reinterpret_cast<volatile register_value_type*>(address); *pa = static_cast<register_value_type>(*pa & value); }
static auto reg_or () -> void { volatile register_value_type* pa = reinterpret_cast<volatile register_value_type*>(address); *pa = static_cast<register_value_type>(*pa | value); }
static auto reg_not() -> void { volatile register_value_type* pa = reinterpret_cast<volatile register_value_type*>(address); *pa = static_cast<register_value_type>(*pa & static_cast<register_value_type>(~value)); }
static auto reg_get() -> register_value_type { volatile register_value_type* p_addr = reinterpret_cast<register_value_type*>(address); return *p_addr; }
static auto reg_set() -> void { volatile register_value_type* p_addr = reinterpret_cast<volatile register_value_type*>(address); *p_addr = value; }
static auto reg_and() -> void { volatile register_value_type* p_addr = reinterpret_cast<volatile register_value_type*>(address); *p_addr = static_cast<register_value_type>(*p_addr & value); }
static auto reg_or () -> void { volatile register_value_type* p_addr = reinterpret_cast<volatile register_value_type*>(address); *p_addr = static_cast<register_value_type>(*p_addr | value); }
static auto reg_not() -> void { volatile register_value_type* p_addr = reinterpret_cast<volatile register_value_type*>(address); *p_addr = static_cast<register_value_type>(*p_addr & static_cast<register_value_type>(~value)); }

template<const register_value_type mask_value>
static auto reg_msk() -> void
{
volatile register_value_type* pa = reinterpret_cast<volatile register_value_type*>(address);
volatile register_value_type* p_addr = reinterpret_cast<volatile register_value_type*>(address);

*pa =
*p_addr =
static_cast<register_value_type>
(
static_cast<register_value_type>(reg_get() & static_cast<register_value_type>(~mask_value))
| value
);
}

static auto bit_set() -> void { volatile register_value_type* pa = reinterpret_cast<volatile register_value_type*>(address); *pa = static_cast<register_value_type>(*pa | static_cast<register_value_type>(1ULL << value)); }
static auto bit_clr() -> void { volatile register_value_type* pa = reinterpret_cast<volatile register_value_type*>(address); *pa = static_cast<register_value_type>(*pa & static_cast<register_value_type>(~static_cast<register_value_type>(1ULL << value))); }
static auto bit_not() -> void { volatile register_value_type* pa = reinterpret_cast<volatile register_value_type*>(address); *pa = static_cast<register_value_type>(*pa ^ static_cast<register_value_type>(1ULL << value)); }
static auto bit_set() -> void { volatile register_value_type* p_addr = reinterpret_cast<volatile register_value_type*>(address); *p_addr = static_cast<register_value_type>(*p_addr | static_cast<register_value_type>(1ULL << value)); }
static auto bit_clr() -> void { volatile register_value_type* p_addr = reinterpret_cast<volatile register_value_type*>(address); *p_addr = static_cast<register_value_type>(*p_addr & static_cast<register_value_type>(~static_cast<register_value_type>(1ULL << value))); }
static auto bit_not() -> void { volatile register_value_type* p_addr = reinterpret_cast<volatile register_value_type*>(address); *p_addr = static_cast<register_value_type>(*p_addr ^ static_cast<register_value_type>(1ULL << value)); }
static auto bit_get() -> bool { return (static_cast<register_value_type>(reg_get() & static_cast<register_value_type>(1ULL << value)) != static_cast<register_value_type>(0U)); }
};
}
Expand Down
47 changes: 15 additions & 32 deletions examples/chapter09_08b/src/mcal/stm32f100/mcal_led_rgb_ws2812.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<typename PortPinType,
const unsigned LedCount> auto led_rgb_ws2812<PortPinType, LedCount>::push_color() -> void
Expand Down Expand Up @@ -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

Expand Down