mirror of
https://github.com/TomHarte/CLK.git
synced 2025-09-25 08:25:09 +00:00
Attmept full ADC implementation.
This commit is contained in:
@@ -10,22 +10,61 @@
|
||||
|
||||
using namespace NEC;
|
||||
|
||||
uPD7002::uPD7002(HalfCycles) {
|
||||
uPD7002::uPD7002(const HalfCycles clock_rate) {
|
||||
// Per the BBC AUG: "8 bit conversions typically take 4 ms to complete whereas 10 bit
|
||||
// conversions typically take 10 ms to complete".
|
||||
fast_period_ = clock_rate / 250;
|
||||
slow_period_ = clock_rate / 100;
|
||||
}
|
||||
|
||||
void uPD7002::run_for(HalfCycles) {
|
||||
void uPD7002::run_for(const HalfCycles count) {
|
||||
if(!conversion_time_remaining_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(count >= conversion_time_remaining_) {
|
||||
conversion_time_remaining_ = HalfCycles(0);
|
||||
interrupt_ = true;
|
||||
result_ = uint16_t(inputs_[channel_] * 65535.0f) & (high_precision_ ? 0xfff0 : 0xff00);
|
||||
if(delegate_) delegate_->did_change_interrupt_status(*this);
|
||||
return;
|
||||
}
|
||||
|
||||
conversion_time_remaining_ -= count;
|
||||
}
|
||||
|
||||
bool uPD7002::interrupt() const {
|
||||
return false;
|
||||
return interrupt_;
|
||||
}
|
||||
|
||||
void uPD7002::write(const uint16_t address, const uint8_t value) {
|
||||
(void)address;
|
||||
(void)value;
|
||||
if(!address) {
|
||||
channel_ = value & 3;
|
||||
high_precision_ = value & 8;
|
||||
conversion_time_remaining_ = high_precision_ ? slow_period_ : fast_period_;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t uPD7002::read(const uint16_t address) {
|
||||
(void)address;
|
||||
return 0xff;
|
||||
if(!address) {
|
||||
return status();
|
||||
}
|
||||
|
||||
if(address & 1) {
|
||||
interrupt_ = false;
|
||||
if(delegate_) delegate_->did_change_interrupt_status(*this);
|
||||
return uint8_t(result_ >> 8);
|
||||
} else {
|
||||
return uint8_t(result_);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t uPD7002::status() const {
|
||||
return
|
||||
channel_ |
|
||||
(high_precision_ ? 8 : 0) |
|
||||
((result_ >> 10) & 0x30) |
|
||||
(conversion_time_remaining_ > HalfCycles(0) ? 0x00 : 0x40) |
|
||||
(interrupt_ ? 0x00 : 0x80);
|
||||
}
|
||||
|
@@ -18,13 +18,28 @@ public:
|
||||
bool interrupt() const;
|
||||
|
||||
struct Delegate {
|
||||
virtual void did_change_interrupt_status(uPD7002 &);
|
||||
virtual void did_change_interrupt_status(uPD7002 &) = 0;
|
||||
};
|
||||
void set_delegate(Delegate *);
|
||||
|
||||
void write(uint16_t address, uint8_t value);
|
||||
uint8_t read(uint16_t address);
|
||||
|
||||
void set_input(int channel, float value);
|
||||
|
||||
private:
|
||||
float inputs_[4]{};
|
||||
uint16_t result_ = 0;
|
||||
bool interrupt_ = false;
|
||||
|
||||
uint8_t channel_ = 0;
|
||||
bool high_precision_ = false;
|
||||
|
||||
HalfCycles conversion_time_remaining_;
|
||||
HalfCycles fast_period_, slow_period_;
|
||||
|
||||
uint8_t status() const;
|
||||
Delegate *delegate_ = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -440,7 +440,8 @@ class ConcreteMachine:
|
||||
public MachineTypes::MappedKeyboardMachine,
|
||||
public MachineTypes::ScanProducer,
|
||||
public MachineTypes::TimedMachine,
|
||||
public MOS::MOS6522::IRQDelegatePortHandler::Delegate
|
||||
public MOS::MOS6522::IRQDelegatePortHandler::Delegate,
|
||||
public NEC::uPD7002::Delegate
|
||||
{
|
||||
public:
|
||||
ConcreteMachine(
|
||||
@@ -615,10 +616,8 @@ public:
|
||||
}
|
||||
} else if(address >= 0xfec0 && address < 0xfee0) {
|
||||
if(is_read(operation)) {
|
||||
// Logger::info().append("ACIA read");
|
||||
*value = adc_.read(address);
|
||||
} else {
|
||||
// Logger::info().append("ACIA write: %02x", *value);
|
||||
adc_.write(address, *value);
|
||||
}
|
||||
}
|
||||
@@ -698,6 +697,11 @@ private:
|
||||
update_irq_line();
|
||||
}
|
||||
|
||||
// MARK: - uPD7002::Delegate.
|
||||
void did_change_interrupt_status(NEC::uPD7002 &) override {
|
||||
update_irq_line();
|
||||
}
|
||||
|
||||
// MARK: - Clock phase.
|
||||
int phase_ = 0;
|
||||
|
||||
|
Reference in New Issue
Block a user