1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-11-24 13:17:41 +00:00
Files
CLK/Components/uPD7002/uPD7002.cpp
2025-10-02 17:10:27 -04:00

86 lines
2.0 KiB
C++

//
// uPD7002.cpp
// Clock Signal
//
// Created by Thomas Harte on 17/09/2025.
// Copyright © 2025 Thomas Harte. All rights reserved.
//
#include "uPD7002.hpp"
using namespace NEC;
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(const HalfCycles count) {
if(!conversion_time_remaining_) {
return;
}
if(count >= conversion_time_remaining_) {
conversion_time_remaining_ = HalfCycles(0);
result_ = uint16_t(inputs_[channel_] * 65535.0f) & (high_precision_ ? 0xfff0 : 0xff00);
set_interrupt(true);
return;
}
conversion_time_remaining_ -= count;
}
bool uPD7002::interrupt() const {
return interrupt_;
}
void uPD7002::write(const uint16_t address, const uint8_t value) {
const auto local_address = address & 3;
if(!local_address) {
channel_ = value & 0b0000'0011;
spare_ = value & 0b0000'0100;
high_precision_ = value & 0b0000'1000;
conversion_time_remaining_ = high_precision_ ? slow_period_ : fast_period_;
set_interrupt(false);
return;
}
}
uint8_t uPD7002::read(const uint16_t address) {
switch(address & 3) {
default:
case 0: return status();
case 1:
set_interrupt(false);
return uint8_t(result_ >> 8);
case 2: return uint8_t(result_);
case 3: return 0xff;
}
}
uint8_t uPD7002::status() const {
return
channel_ |
spare_ |
(high_precision_ ? 0x08 : 0) |
((result_ >> 14) & 0x30) |
(conversion_time_remaining_ > HalfCycles(0) ? 0x00 : 0x40) |
(interrupt_ ? 0x00 : 0x80);
}
void uPD7002::set_delegate(Delegate *const delegate) {
delegate_ = delegate;
}
void uPD7002::set_interrupt(const bool value) {
if(interrupt_ == value) return;
interrupt_ = value;
if(delegate_) delegate_->did_change_interrupt_status(*this);
}
void uPD7002::set_input(const int channel, const float value) {
inputs_[channel] = value;
}