1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Extend to allow full-[byte/word/dword] writes, in LSB or MSB order.

This commit is contained in:
Thomas Harte 2021-11-06 12:01:32 -07:00
parent 471e13efbc
commit f102d8a4b4
2 changed files with 38 additions and 3 deletions

View File

@ -8,6 +8,8 @@
#include "Line.hpp"
#include <limits>
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 <bool lsb_first, typename IntT> 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<IntT>::max() - (std::numeric_limits<IntT>::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<true, int>(cycles, count, levels);
}
template <bool lsb_first, typename IntT> void Line::write(HalfCycles cycles, IntT value) {
write_internal<lsb_first, IntT>(cycles, 8 * sizeof(IntT), value);
}
template void Line::write<true, uint8_t>(HalfCycles, uint8_t);
template void Line::write<false, uint8_t>(HalfCycles, uint8_t);
template void Line::write<true, uint16_t>(HalfCycles, uint16_t);
template void Line::write<false, uint16_t>(HalfCycles, uint16_t);
template void Line::write<true, uint32_t>(HalfCycles, uint32_t);
template void Line::write<false, uint32_t>(HalfCycles, uint32_t);
template void Line::write<true, uint64_t>(HalfCycles, uint64_t);
template void Line::write<false, uint64_t>(HalfCycles, uint64_t);
void Line::reset_writing() {
remaining_delays_ = 0;
events_.clear();

View File

@ -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 <bool lsb_first, typename IntT> 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 <bool lsb_first, typename IntT> void
write_internal(HalfCycles, int, IntT);
};
/*!