mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +00:00
Provide a loop count directly from the sequencer.
This avoids the caller having to take a guess at iterations.
This commit is contained in:
parent
d85d70a133
commit
1ac0a4e924
@ -49,40 +49,38 @@ class BlitterSequencer {
|
|||||||
/// Sets the current control value, which indicates which
|
/// Sets the current control value, which indicates which
|
||||||
/// channels are enabled.
|
/// channels are enabled.
|
||||||
void set_control(int control) {
|
void set_control(int control) {
|
||||||
control_ = control;
|
control_ = control & 0xf;
|
||||||
index_ = 0;
|
index_ = 0; // TODO: this probably isn't accurate; case caught is a change
|
||||||
|
// of control values during a blit.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates that blitting should conclude after this step, i.e.
|
/// Indicates that blitting should conclude after this step, i.e.
|
||||||
/// whatever is being fetched now is part of the final set of input data;
|
/// whatever is being fetched now is part of the final set of input data;
|
||||||
/// this is safe to call following a fetch request on any channel.
|
/// this is safe to call following a fetch request on any channel.
|
||||||
void complete() {
|
void complete() {
|
||||||
phase_ =
|
next_phase_ =
|
||||||
(control_ == 0x9 || control_ == 0xb || control_ == 0xd) ?
|
(control_ == 0x9 || control_ == 0xb || control_ == 0xd) ?
|
||||||
Phase::PauseAndComplete : Phase::Complete;
|
Phase::PauseAndComplete : Phase::Complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Begins a blit operation.
|
/// Begins a blit operation.
|
||||||
void begin() {
|
void begin() {
|
||||||
phase_ = Phase::Ongoing;
|
phase_ = next_phase_ = Phase::Ongoing;
|
||||||
index_ = 0;
|
index_ = loop_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides the next channel to fetch from, or that a write is required.
|
/// Provides the next channel to fetch from, or that a write is required,
|
||||||
Channel next() {
|
/// along with a count of complete channel iterations so far completed.
|
||||||
|
std::pair<Channel, int> next() {
|
||||||
switch(phase_) {
|
switch(phase_) {
|
||||||
default: break;
|
default: break;
|
||||||
|
|
||||||
case Phase::Complete:
|
case Phase::Complete:
|
||||||
if(!index_) return Channel::Write;
|
return std::make_pair(Channel::Write, loop_);
|
||||||
break;
|
|
||||||
|
|
||||||
case Phase::PauseAndComplete:
|
case Phase::PauseAndComplete:
|
||||||
if(!index_) {
|
phase_ = Phase::Complete;
|
||||||
phase_ = Phase::Complete;
|
return std::make_pair(Channel::None, loop_);
|
||||||
return Channel::None;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel next = Channel::None;
|
Channel next = Channel::None;
|
||||||
@ -107,7 +105,7 @@ class BlitterSequencer {
|
|||||||
case 15: next = next_channel(patternF); break;
|
case 15: next = next_channel(patternF); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return next;
|
return std::make_pair(next, loop_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -127,16 +125,40 @@ class BlitterSequencer {
|
|||||||
static constexpr std::array<Channel, 3> patternE = { Channel::A, Channel::B, Channel::C };
|
static constexpr std::array<Channel, 3> patternE = { Channel::A, Channel::B, Channel::C };
|
||||||
static constexpr std::array<Channel, 4> patternF = { Channel::A, Channel::B, Channel::C, Channel::Write };
|
static constexpr std::array<Channel, 4> patternF = { Channel::A, Channel::B, Channel::C, Channel::Write };
|
||||||
template <typename ArrayT> Channel next_channel(const ArrayT &list) {
|
template <typename ArrayT> Channel next_channel(const ArrayT &list) {
|
||||||
|
loop_ += index_ / list.size();
|
||||||
|
index_ %= list.size();
|
||||||
const Channel result = list[index_];
|
const Channel result = list[index_];
|
||||||
index_ = (index_ + 1) % list.size();
|
++index_;
|
||||||
|
if(index_ == list.size()) {
|
||||||
|
phase_ = next_phase_;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Current control flags, i.e. which channels are enabled.
|
||||||
int control_ = 0;
|
int control_ = 0;
|
||||||
|
|
||||||
|
// Index into the pattern table for this blit.
|
||||||
size_t index_ = 0;
|
size_t index_ = 0;
|
||||||
|
|
||||||
|
// Number of times the entire pattern table has been completed.
|
||||||
|
int loop_ = 0;
|
||||||
|
|
||||||
enum class Phase {
|
enum class Phase {
|
||||||
Ongoing, PauseAndComplete, Complete
|
/// Return the next thing in the pattern table and advance.
|
||||||
} phase_ = Phase::Complete;
|
/// If looping from the end of the pattern table to the start,
|
||||||
|
/// set phase_ to next_phase_.
|
||||||
|
Ongoing,
|
||||||
|
/// Return a Channel::None and advancce to phase_ = Phase::Complete.
|
||||||
|
PauseAndComplete,
|
||||||
|
/// Return Channel::Write indefinitely.
|
||||||
|
Complete
|
||||||
|
};
|
||||||
|
|
||||||
|
// Current sequencer pahse.
|
||||||
|
Phase phase_ = Phase::Complete;
|
||||||
|
// Phase to assume at the end of this iteration of the sequence table.
|
||||||
|
Phase next_phase_ = Phase::Complete;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Blitter: public DMADevice<4, 4> {
|
class Blitter: public DMADevice<4, 4> {
|
||||||
|
@ -294,13 +294,12 @@ using WriteVector = std::vector<std::pair<uint32_t, uint16_t>>;
|
|||||||
/* F */ @"A0 B0 C0 - A1 B1 C1 D0 A2 B2 C2 D1 D2",
|
/* F */ @"A0 B0 C0 - A1 B1 C1 D0 A2 B2 C2 D1 D2",
|
||||||
];
|
];
|
||||||
|
|
||||||
for(int c = 0; c < 16; c++) {
|
for(int c = 0; c < 16; c++) {
|
||||||
Amiga::BlitterSequencer sequencer;
|
Amiga::BlitterSequencer sequencer;
|
||||||
sequencer.set_control(c);
|
sequencer.set_control(c);
|
||||||
sequencer.begin();
|
sequencer.begin();
|
||||||
|
|
||||||
int counts[4]{};
|
int writes = 0;
|
||||||
const int writes = 2;
|
|
||||||
NSUInteger length = [[patterns[c] componentsSeparatedByString:@" "] count];
|
NSUInteger length = [[patterns[c] componentsSeparatedByString:@" "] count];
|
||||||
bool is_first_write = c > 1; // control = 1 is D only, in which case don't pipeline.
|
bool is_first_write = c > 1; // control = 1 is D only, in which case don't pipeline.
|
||||||
NSMutableArray<NSString *> *const components = [[NSMutableArray alloc] init];
|
NSMutableArray<NSString *> *const components = [[NSMutableArray alloc] init];
|
||||||
@ -309,24 +308,27 @@ using WriteVector = std::vector<std::pair<uint32_t, uint16_t>>;
|
|||||||
const auto next = sequencer.next();
|
const auto next = sequencer.next();
|
||||||
|
|
||||||
using Channel = Amiga::BlitterSequencer::Channel;
|
using Channel = Amiga::BlitterSequencer::Channel;
|
||||||
switch(next) {
|
switch(next.first) {
|
||||||
case Channel::None: [components addObject:@"-"]; break;
|
case Channel::None: [components addObject:@"-"]; break;
|
||||||
case Channel::A: [components addObject:[NSString stringWithFormat:@"A%d", counts[0]++]]; break;
|
case Channel::A: [components addObject:[NSString stringWithFormat:@"A%d", next.second]]; break;
|
||||||
case Channel::B: [components addObject:[NSString stringWithFormat:@"B%d", counts[1]++]]; break;
|
case Channel::B: [components addObject:[NSString stringWithFormat:@"B%d", next.second]]; break;
|
||||||
case Channel::C: [components addObject:[NSString stringWithFormat:@"C%d", counts[2]++]]; break;
|
case Channel::C: [components addObject:[NSString stringWithFormat:@"C%d", next.second]]; break;
|
||||||
|
|
||||||
case Channel::Write:
|
case Channel::Write:
|
||||||
if(is_first_write) {
|
if(is_first_write) {
|
||||||
is_first_write = false;
|
is_first_write = false;
|
||||||
[components addObject:@"-"];
|
[components addObject:@"-"];
|
||||||
} else {
|
} else {
|
||||||
[components addObject:[NSString stringWithFormat:@"D%d", counts[3]++]];
|
[components addObject:[NSString stringWithFormat:@"D%d", writes++]];
|
||||||
if(counts[3] == writes) sequencer.complete();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(next.second == 2) {
|
||||||
|
sequencer.complete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *pattern = [components componentsJoinedByString:@" "];
|
NSString *pattern = [components componentsJoinedByString:@" "];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user