From f102d8a4b43256cecdf529482e8004c82fab0367 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 6 Nov 2021 12:01:32 -0700 Subject: [PATCH] Extend to allow full-[byte/word/dword] writes, in LSB or MSB order. --- Components/Serial/Line.cpp | 34 +++++++++++++++++++++++++++++++--- Components/Serial/Line.hpp | 7 +++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Components/Serial/Line.cpp b/Components/Serial/Line.cpp index b46cf72ae..16623cd97 100644 --- a/Components/Serial/Line.cpp +++ b/Components/Serial/Line.cpp @@ -8,6 +8,8 @@ #include "Line.hpp" +#include + using namespace Serial; void Line::set_writer_clock_rate(HalfCycles clock_rate) { @@ -70,7 +72,7 @@ void Line::write(bool level) { } } -void Line::write(HalfCycles cycles, int count, int levels) { +template void Line::write_internal(HalfCycles cycles, int count, IntT levels) { remaining_delays_ += count * cycles.as_integral(); auto event = events_.size(); @@ -78,12 +80,38 @@ void Line::write(HalfCycles cycles, int count, int levels) { while(count--) { events_[event].type = Event::Delay; events_[event].delay = int(cycles.as_integral()); - events_[event+1].type = (levels&1) ? Event::SetHigh : Event::SetLow; - levels >>= 1; + IntT bit; + if constexpr (lsb_first) { + bit = levels & 1; + levels >>= 1; + } else { + constexpr auto top_bit = std::numeric_limits::max() - (std::numeric_limits::max() >> 1); + bit = levels & top_bit; + levels <<= 1; + } + + events_[event+1].type = bit ? Event::SetHigh : Event::SetLow; event += 2; } } +void Line::write(HalfCycles cycles, int count, int levels) { + write_internal(cycles, count, levels); +} + +template void Line::write(HalfCycles cycles, IntT value) { + write_internal(cycles, 8 * sizeof(IntT), value); +} + +template void Line::write(HalfCycles, uint8_t); +template void Line::write(HalfCycles, uint8_t); +template void Line::write(HalfCycles, uint16_t); +template void Line::write(HalfCycles, uint16_t); +template void Line::write(HalfCycles, uint32_t); +template void Line::write(HalfCycles, uint32_t); +template void Line::write(HalfCycles, uint64_t); +template void Line::write(HalfCycles, uint64_t); + void Line::reset_writing() { remaining_delays_ = 0; events_.clear(); diff --git a/Components/Serial/Line.hpp b/Components/Serial/Line.hpp index 3829b4483..2c2952f51 100644 --- a/Components/Serial/Line.hpp +++ b/Components/Serial/Line.hpp @@ -44,6 +44,10 @@ class Line { /// relative to the writer's clock rate. void write(HalfCycles cycles, int count, int levels); + /// Enqueus every bit from @c value as per the rules of write(HalfCycles, int, int), + /// either in LSB or MSB order as per the @c lsb_first template flag. + template void write(HalfCycles cycles, IntT value); + /// @returns the number of cycles until currently enqueued write data is exhausted. forceinline HalfCycles write_data_time_remaining() const { return HalfCycles(remaining_delays_); @@ -98,6 +102,9 @@ class Line { void update_delegate(bool level); HalfCycles::IntType minimum_write_cycles_for_read_delegate_bit(); + + template void + write_internal(HalfCycles, int, IntT); }; /*!