mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-10 22:37:30 +00:00
Merge pull request #630 from TomHarte/IWMWrites
Makes various fixes to `Drive` and `Track`.
This commit is contained in:
commit
4033c0c754
@ -54,8 +54,8 @@
|
||||
*/
|
||||
template <class T> class WrappedInt {
|
||||
public:
|
||||
forceinline constexpr WrappedInt(int l) : length_(l) {}
|
||||
forceinline constexpr WrappedInt() : length_(0) {}
|
||||
forceinline constexpr WrappedInt(int l) noexcept : length_(l) {}
|
||||
forceinline constexpr WrappedInt() noexcept : length_(0) {}
|
||||
|
||||
forceinline T &operator =(const T &rhs) {
|
||||
length_ = rhs.length_;
|
||||
@ -165,19 +165,19 @@ template <class T> class WrappedInt {
|
||||
/// Describes an integer number of whole cycles: pairs of clock signal transitions.
|
||||
class Cycles: public WrappedInt<Cycles> {
|
||||
public:
|
||||
forceinline constexpr Cycles(int l) : WrappedInt<Cycles>(l) {}
|
||||
forceinline constexpr Cycles() : WrappedInt<Cycles>() {}
|
||||
forceinline constexpr Cycles(const Cycles &cycles) : WrappedInt<Cycles>(cycles.length_) {}
|
||||
forceinline constexpr Cycles(int l) noexcept : WrappedInt<Cycles>(l) {}
|
||||
forceinline constexpr Cycles() noexcept : WrappedInt<Cycles>() {}
|
||||
forceinline constexpr Cycles(const Cycles &cycles) noexcept : WrappedInt<Cycles>(cycles.length_) {}
|
||||
};
|
||||
|
||||
/// Describes an integer number of half cycles: single clock signal transitions.
|
||||
class HalfCycles: public WrappedInt<HalfCycles> {
|
||||
public:
|
||||
forceinline constexpr HalfCycles(int l) : WrappedInt<HalfCycles>(l) {}
|
||||
forceinline constexpr HalfCycles() : WrappedInt<HalfCycles>() {}
|
||||
forceinline constexpr HalfCycles(int l) noexcept : WrappedInt<HalfCycles>(l) {}
|
||||
forceinline constexpr HalfCycles() noexcept : WrappedInt<HalfCycles>() {}
|
||||
|
||||
forceinline constexpr HalfCycles(const Cycles cycles) : WrappedInt<HalfCycles>(cycles.as_int() * 2) {}
|
||||
forceinline constexpr HalfCycles(const HalfCycles &half_cycles) : WrappedInt<HalfCycles>(half_cycles.length_) {}
|
||||
forceinline constexpr HalfCycles(const Cycles cycles) noexcept : WrappedInt<HalfCycles>(cycles.as_int() * 2) {}
|
||||
forceinline constexpr HalfCycles(const HalfCycles &half_cycles) noexcept : WrappedInt<HalfCycles>(half_cycles.length_) {}
|
||||
|
||||
/// @returns The number of whole cycles completely covered by this span of half cycles.
|
||||
forceinline constexpr Cycles cycles() const {
|
||||
|
@ -97,7 +97,7 @@ class IWM:
|
||||
|
||||
void propose_shift(uint8_t bit);
|
||||
Cycles cycles_since_shift_;
|
||||
Cycles bit_length_;
|
||||
Cycles bit_length_ = Cycles(16);
|
||||
|
||||
void push_drive_state();
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "../../MouseMachine.hpp"
|
||||
|
||||
#include "../../../Inputs/QuadratureMouse/QuadratureMouse.hpp"
|
||||
#include "../../../Outputs/Log.hpp"
|
||||
|
||||
//#define LOG_TRACE
|
||||
|
||||
@ -288,10 +289,10 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
||||
|
||||
default:
|
||||
if(cycle.operation & Microcycle::Read) {
|
||||
printf("Unrecognised read %06x\n", *cycle.address & 0xffffff);
|
||||
LOG("Unrecognised read " << PADHEX(6) << (*cycle.address & 0xffffff));
|
||||
cycle.value->halves.low = 0x00;
|
||||
} else {
|
||||
printf("Unrecognised write %06x\n", *cycle.address & 0xffffff);
|
||||
LOG("Unrecognised write %06x" << PADHEX(6) << (*cycle.address & 0xffffff));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -560,7 +561,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
||||
if(port == Port::B && line == Line::Two) {
|
||||
keyboard_.set_input(value);
|
||||
}
|
||||
else printf("Unhandled control line output: %c %d\n", port ? 'B' : 'A', int(line));
|
||||
else LOG("Unhandled control line output: " << (port ? 'B' : 'A') << int(line));
|
||||
}
|
||||
|
||||
void run_for(HalfCycles duration) {
|
||||
|
@ -3013,7 +3013,7 @@ struct ProcessorStorageConstructor {
|
||||
}
|
||||
|
||||
if(storage_.all_micro_ops_[index].is_terminal()) {
|
||||
storage_.all_micro_ops_[index].bus_program = seq("");
|
||||
storage_.all_micro_ops_[index].bus_program = uint16_t(seq(""));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3259,10 +3259,10 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() {
|
||||
|
||||
// Complete linkage of the exception micro program.
|
||||
short_exception_micro_ops_ = &all_micro_ops_[short_exception_offset];
|
||||
short_exception_micro_ops_->bus_program = trap_offset;
|
||||
short_exception_micro_ops_->bus_program = uint16_t(trap_offset);
|
||||
|
||||
long_exception_micro_ops_ = &all_micro_ops_[long_exception_offset];
|
||||
long_exception_micro_ops_->bus_program = bus_error_offset;
|
||||
long_exception_micro_ops_->bus_program = uint16_t(bus_error_offset);
|
||||
|
||||
// Set initial state.
|
||||
active_step_ = reset_bus_steps_;
|
||||
|
@ -38,9 +38,15 @@ Drive::Drive(int input_clock_rate, int revolutions_per_minute, int number_of_hea
|
||||
Drive::Drive(int input_clock_rate, int number_of_heads) : Drive(input_clock_rate, 300, number_of_heads) {}
|
||||
|
||||
void Drive::set_rotation_speed(float revolutions_per_minute) {
|
||||
// TODO: probably I should look into
|
||||
// whether doing all this with quotients is really a good idea.
|
||||
rotational_multiplier_ = 60.0f / revolutions_per_minute;
|
||||
// Rationalise the supplied speed so that cycles_per_revolution_ is exact.
|
||||
cycles_per_revolution_ = int(0.5f + float(get_input_clock_rate()) * 60.0f / revolutions_per_minute);
|
||||
|
||||
// From there derive the appropriate rotational multiplier and possibly update the
|
||||
// count of cycles since the index hole proportionally.
|
||||
const float new_rotational_multiplier = float(cycles_per_revolution_) / float(get_input_clock_rate());
|
||||
cycles_since_index_hole_ *= new_rotational_multiplier / rotational_multiplier_;
|
||||
rotational_multiplier_ = new_rotational_multiplier;
|
||||
cycles_since_index_hole_ %= cycles_per_revolution_;
|
||||
}
|
||||
|
||||
Drive::~Drive() {
|
||||
@ -296,6 +302,10 @@ void Drive::setup_track() {
|
||||
offset = track_time_now - time_found;
|
||||
}
|
||||
|
||||
// Reseed cycles_since_index_hole_; 99.99% of the time it'll still be correct as is,
|
||||
// but if the track has rounded one way or the other it may now be very slightly adrift.
|
||||
cycles_since_index_hole_ = (int((time_found + offset) * cycles_per_revolution_)) % cycles_per_revolution_;
|
||||
|
||||
get_next_event(offset);
|
||||
}
|
||||
|
||||
@ -340,7 +350,10 @@ void Drive::write_bit(bool value) {
|
||||
void Drive::end_writing() {
|
||||
// If the user modifies a track, it's scaled up to a "high" resolution and modifications
|
||||
// are plotted on top of that.
|
||||
const size_t high_resolution_track_rate = 500000;
|
||||
//
|
||||
// "High" is defined as: two samples per clock relative to an idiomatic
|
||||
// 8Mhz disk controller and 300RPM disk speed.
|
||||
const size_t high_resolution_track_rate = 3200000;
|
||||
|
||||
if(!is_reading_) {
|
||||
is_reading_ = true;
|
||||
@ -354,7 +367,7 @@ void Drive::end_writing() {
|
||||
}
|
||||
}
|
||||
patched_track_->add_segment(write_start_time_, write_segment_, clamp_writing_to_index_hole_);
|
||||
cycles_since_index_hole_ %= get_input_clock_rate();
|
||||
cycles_since_index_hole_ %= cycles_per_revolution_;
|
||||
invalidate_track();
|
||||
}
|
||||
}
|
||||
|
@ -198,6 +198,10 @@ class Drive: public ClockingHint::Source, public TimedEventLoop {
|
||||
// a new track.
|
||||
int cycles_since_index_hole_ = 0;
|
||||
|
||||
// The number of cycles that should fall within one revolution at the
|
||||
// current rotation speed.
|
||||
int cycles_per_revolution_ = 1;
|
||||
|
||||
// A record of head position and active head.
|
||||
HeadPosition head_position_;
|
||||
int head_ = 0;
|
||||
|
@ -80,6 +80,8 @@ Storage::Disk::PCMSegment six_and_two_sync(int length);
|
||||
/*!
|
||||
Produces the data section of a five-and-three format sector; the segment returned
|
||||
will be 3,336 bits long, encoding the first 256 bytes from @c source.
|
||||
|
||||
(TODO).
|
||||
*/
|
||||
Storage::Disk::PCMSegment five_and_three_data(const uint8_t *source);
|
||||
|
||||
|
@ -264,7 +264,7 @@ struct Time {
|
||||
// If the mantissa is negative and its absolute value fits within a 64-bit integer,
|
||||
// just load up.
|
||||
if(relative_exponent <= 0 && relative_exponent > -64) {
|
||||
install_result(loaded_mantissa, uint64_t(1 << -relative_exponent));
|
||||
install_result(loaded_mantissa, uint64_t(1) << -relative_exponent);
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user