1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-29 12:50:28 +00:00

Implements the Command side of the line command.

This commit is contained in:
Thomas Harte 2023-01-26 21:17:11 -05:00
parent 1c6a0ad3f7
commit baa6f9b3cd

View File

@ -46,11 +46,14 @@ struct Command {
// This command is blocked until @c access has been performed, reading // This command is blocked until @c access has been performed, reading
// from or writing to @c value. It should not be performed until at least // from or writing to @c value. It should not be performed until at least
// @c cycles have passed. // @c cycles have passed.
MemoryAccess access = MemoryAccess::None; enum class AccessType {
/// Plots a single pixel of the current contextual colour at @c location,
/// which occurs as a read, then a 24-cycle pause, then a write.
PlotPoint
};
AccessType access = AccessType::PlotPoint;
int cycles = 0; int cycles = 0;
uint8_t value = 0; Vector location;
// TODO: how best to describe access destination? Probably as (x, y) and logical/fast?
/// Current command parameters. /// Current command parameters.
CommandContext &context; CommandContext &context;
@ -67,21 +70,59 @@ struct Command {
namespace Commands { namespace Commands {
/// Implements the line command, which is plain-old Bresenham.
///
/// Per Grauw timing is:
///
/// * 88 cycles between every pixel plot;
/// * plus an additional 32 cycles if a step along the minor axis is taken.
struct Line: public Command { struct Line: public Command {
public: public:
Line(CommandContext &context) : Command(context) { Line(CommandContext &context) : Command(context) {
// Set up Bresenham constants. // Set up Bresenham constants.
if(abs(context.size.v[0]) > abs(context.size.v[1])) {
major_.v[0] = context.size.v[0] < 0 ? -1 : 1;
minor_.v[1] = context.size.v[1] < 0 ? -1 : 1;
major_.v[1] = minor_.v[0] = 0;
position_ = abs(context.size.v[1]);
duration_ = abs(context.size.v[0]);
} else {
major_.v[1] = context.size.v[1] < 0 ? -1 : 1;
minor_.v[0] = context.size.v[0] < 0 ? -1 : 1;
major_.v[0] = minor_.v[1] = 0;
position_ = abs(context.size.v[0]);
duration_ = abs(context.size.v[1]);
}
numerator_ = position_ << 1;
denominator_ = duration_ << 1;
cycles = 0;
access = AccessType::PlotPoint;
location = context.destination;
} }
bool next() { bool next() {
// Should implement Bresenham with cadence: if(!duration_) return false;
//
// 88 cycles before the next read; 24 to write. --duration_;
// Add 32 extra cycles if a minor-axis step occurs. cycles = 88;
return false; location += major_;
position_ -= numerator_;
if(position_ < 0) {
cycles += 32;
location += minor_;
position_ += denominator_;
}
return true;
} }
private: private:
int position_, numerator_, denominator_, duration_;
Vector major_, minor_;
}; };
} }