1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

Attempts a more literal implementation.

This commit is contained in:
Thomas Harte 2021-08-01 18:14:10 -04:00
parent 26aaddaa33
commit 460a6cb6fe
3 changed files with 73 additions and 42 deletions

View File

@ -67,6 +67,7 @@ template <typename PortHandlerT, Personality personality> class MOS6526:
template <int port> uint8_t get_port_input();
void update_interrupts();
void posit_interrupt(uint8_t mask);
void advance_counters(int);
};
}

View File

@ -234,18 +234,29 @@ uint8_t MOS6526<BusHandlerT, personality>::read(int address) {
template <typename BusHandlerT, Personality personality>
void MOS6526<BusHandlerT, personality>::run_for(const HalfCycles half_cycles) {
half_divider_ += half_cycles;
const int sub = half_divider_.divide_cycles().template as<int>();
if(!sub) return;
int sub = half_divider_.divide_cycles().template as<int>();
while(sub--) {
// TODO: use CNT potentially to clock timer A.
counter_[0].advance(false);
counter_[1].advance(counter_[0].hit_zero);
posit_interrupt((counter_[0].hit_zero ? 0x01 : 0x00) | (counter_[1].hit_zero ? 0x02 : 0x00));
}
}
/*template <typename BusHandlerT, Personality personality>
void MOS6526<BusHandlerT, personality>::advance_counters(int sub) {
// Is counter A running and linked to the clock input?
int counter_a_underflows = 0;
if((counter_[0].control & 0x21) == 0x01) {
if(counter_[0].control & 0x20) {
printf("Unimplemented: Timer A CNT \n");
} else {
counter_a_underflows = counter_[0].subtract(sub);
}
// This might be clocking the serial output too.
if(counter_[0].control & 0x40) {
printf("Unimplemented shift register clocking\n");
}
// Counter A might be clocking the shift register.
if(counter_a_underflows && counter_[0].control & 0x40) {
printf("Unimplemented shift register clocking\n");
}
// Update counter B.
@ -267,7 +278,7 @@ void MOS6526<BusHandlerT, personality>::run_for(const HalfCycles half_cycles) {
// Apply interrupts.
posit_interrupt((counter_a_underflows ? 0x01 : 0x00) | (counter_b_underflows ? 0x02 : 0x00));
}
}*/
template <typename BusHandlerT, Personality personality>
void MOS6526<BusHandlerT, personality>::advance_tod(int count) {

View File

@ -30,56 +30,75 @@ struct MOS6526Storage {
uint16_t reload = 0;
uint16_t value = 0;
uint8_t control = 0;
bool hit_zero = false;
template <int shift> void set_reload(uint8_t v) {
reload = (reload & (0xff00 >> shift)) | uint16_t(v << shift);
if constexpr (shift == 8) {
if(!(control&1)) {
value = reload;
if(control&8) {
control |= 1; // At a guess: start one-shot automatically (?)
}
}
}
// if constexpr (shift == 8) {
// if(!(control&1)) {
// value = reload;
// }
// }
}
template <bool is_counter_2> void set_control(uint8_t v) {
control = v & 0xef;
if(v & 0x10) {
pending |= ReloadInTwo;
}
}
void advance(bool chained_input) {
// TODO: remove most of the conditionals here.
pending <<= 1;
if(hit_zero && pending&(OneShotInOne | OneShotNow)) {
control &= ~1;
}
if((control & 0x01) || chained_input) {
pending |= ApplyClockInTwo;
}
if(control & 0x08) {
pending |= OneShotInOne;
}
if((pending & ReloadNow) || (hit_zero && (pending & ApplyClockInTwo))) {
value = reload;
pending &= ~ApplyClockInTwo;
}
// Force reload + one-shot => start counting (?)
if((v & 0x18) == 0x18) {
control |= 1;
}
}
pending &= PendingClearMask;
int subtract(int count) {
if(control & 8) {
// One-shot.
if(value < count) {
value = reload;
control &= 0xfe;
return 1;
} else {
value -= count;
}
return 0;
if(pending & ApplyClockNow) {
--value;
hit_zero = !value;
} else {
// Continuous.
value -= count;
value -= (reload + 1);
const int underflows = -value / (reload + 1);
value %= (reload + 1);
value += (reload + 1);
return underflows;
hit_zero = false;
}
}
private:
int pending = 0;
static constexpr int ReloadInThree = 1 << 0;
static constexpr int ReloadInTwo = 1 << 1;
static constexpr int ReloadInOne = 1 << 2;
static constexpr int ReloadNow = 1 << 3;
static constexpr int OneShotInOne = 1 << 4;
static constexpr int OneShotNow = 1 << 5;
static constexpr int ApplyClockInThree = 1 << 6;
static constexpr int ApplyClockInTwo = 1 << 7;
static constexpr int ApplyClockInOne = 1 << 8;
static constexpr int ApplyClockNow = 1 << 9;
static constexpr int PendingClearMask = ~(ReloadNow | OneShotNow);
bool active_ = false;
} counter_[2];
};