mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +00:00
Attempts a more literal implementation.
This commit is contained in:
parent
26aaddaa33
commit
460a6cb6fe
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user