2021-07-18 16:23:47 +00:00
|
|
|
//
|
|
|
|
// 6526Storage.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 18/07/2021.
|
|
|
|
// Copyright © 2021 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef _526Storage_h
|
|
|
|
#define _526Storage_h
|
|
|
|
|
|
|
|
namespace MOS {
|
|
|
|
namespace MOS6526 {
|
|
|
|
|
|
|
|
struct MOS6526Storage {
|
2021-07-24 01:24:07 +00:00
|
|
|
HalfCycles half_divider_;
|
2021-07-18 16:23:47 +00:00
|
|
|
|
2021-07-24 01:24:07 +00:00
|
|
|
uint8_t output_[2] = {0, 0};
|
|
|
|
uint8_t data_direction_[2] = {0, 0};
|
2021-07-24 01:58:52 +00:00
|
|
|
|
2021-07-24 01:24:07 +00:00
|
|
|
uint8_t interrupt_control_ = 0;
|
2021-07-24 01:58:52 +00:00
|
|
|
uint8_t interrupt_state_ = 0;
|
|
|
|
|
2021-07-24 01:24:07 +00:00
|
|
|
uint32_t tod_increment_mask_ = uint32_t(~0);
|
|
|
|
uint32_t tod_latch_ = 0;
|
|
|
|
uint32_t tod_ = 0;
|
|
|
|
uint32_t tod_alarm_ = 0;
|
|
|
|
|
|
|
|
struct Counter {
|
|
|
|
uint16_t reload = 0;
|
|
|
|
uint16_t value = 0;
|
2021-07-24 02:43:47 +00:00
|
|
|
uint8_t control = 0;
|
2021-08-01 22:14:10 +00:00
|
|
|
bool hit_zero = false;
|
2021-07-24 02:43:47 +00:00
|
|
|
|
2021-07-24 20:06:49 +00:00
|
|
|
template <int shift> void set_reload(uint8_t v) {
|
|
|
|
reload = (reload & (0xff00 >> shift)) | uint16_t(v << shift);
|
|
|
|
|
2021-08-01 22:14:10 +00:00
|
|
|
// if constexpr (shift == 8) {
|
|
|
|
// if(!(control&1)) {
|
|
|
|
// value = reload;
|
|
|
|
// }
|
|
|
|
// }
|
2021-07-24 20:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <bool is_counter_2> void set_control(uint8_t v) {
|
|
|
|
control = v & 0xef;
|
|
|
|
if(v & 0x10) {
|
2021-08-01 22:14:10 +00:00
|
|
|
pending |= ReloadInTwo;
|
2021-07-24 20:06:49 +00:00
|
|
|
}
|
2021-08-01 22:14:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void advance(bool chained_input) {
|
|
|
|
// TODO: remove most of the conditionals here.
|
2021-07-26 21:02:30 +00:00
|
|
|
|
2021-08-01 22:14:10 +00:00
|
|
|
pending <<= 1;
|
|
|
|
|
|
|
|
if(hit_zero && pending&(OneShotInOne | OneShotNow)) {
|
|
|
|
control &= ~1;
|
2021-07-26 21:02:30 +00:00
|
|
|
}
|
2021-07-24 20:06:49 +00:00
|
|
|
|
2021-08-01 22:14:10 +00:00
|
|
|
if((control & 0x01) || chained_input) {
|
|
|
|
pending |= ApplyClockInTwo;
|
|
|
|
}
|
|
|
|
if(control & 0x08) {
|
|
|
|
pending |= OneShotInOne;
|
|
|
|
}
|
2021-07-24 02:43:47 +00:00
|
|
|
|
2021-08-01 22:14:10 +00:00
|
|
|
if((pending & ReloadNow) || (hit_zero && (pending & ApplyClockInTwo))) {
|
|
|
|
value = reload;
|
|
|
|
pending &= ~ApplyClockInTwo;
|
|
|
|
}
|
|
|
|
|
|
|
|
pending &= PendingClearMask;
|
2021-07-24 02:43:47 +00:00
|
|
|
|
2021-08-01 22:14:10 +00:00
|
|
|
if(pending & ApplyClockNow) {
|
|
|
|
--value;
|
|
|
|
hit_zero = !value;
|
|
|
|
} else {
|
|
|
|
hit_zero = false;
|
2021-07-24 02:43:47 +00:00
|
|
|
}
|
|
|
|
}
|
2021-08-01 22:14:10 +00:00
|
|
|
|
|
|
|
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;
|
2021-07-24 02:43:47 +00:00
|
|
|
} counter_[2];
|
2021-07-18 16:23:47 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* _526Storage_h */
|