mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-19 23:29:05 +00:00
Adds an extended rationale for current implementation.
Also strips some cruft of prior guesses.
This commit is contained in:
parent
1ae3799aee
commit
9bbccd89d3
@ -63,6 +63,7 @@ uint8_t IWM::read(int address) {
|
|||||||
|
|
||||||
if(data_register_ & 0x80) {
|
if(data_register_ & 0x80) {
|
||||||
// printf("\n\nIWM:%02x\n\n", data_register_);
|
// printf("\n\nIWM:%02x\n\n", data_register_);
|
||||||
|
// printf(".");
|
||||||
data_register_ = 0;
|
data_register_ = 0;
|
||||||
}
|
}
|
||||||
// LOG("Reading data register: " << PADHEX(2) << int(result));
|
// LOG("Reading data register: " << PADHEX(2) << int(result));
|
||||||
|
@ -23,26 +23,37 @@ void DriveSpeedAccumulator::post_sample(uint8_t sample) {
|
|||||||
if(sample_pointer_ == samples_.size()) {
|
if(sample_pointer_ == samples_.size()) {
|
||||||
sample_pointer_ = 0;
|
sample_pointer_ = 0;
|
||||||
|
|
||||||
// Treat 33 as a zero point and count zero crossings; then approximate
|
// The below fits for a function like `a + bc`; it encapsultes the following
|
||||||
// the RPM from the frequency of those.
|
// beliefs:
|
||||||
int samples_over = 0;
|
//
|
||||||
int sum = 0;
|
// (i) motor speed is proportional to voltage supplied;
|
||||||
const uint8_t centre = 33;
|
// (ii) with pulse-width modulation it's therefore proportional to the duty cycle;
|
||||||
for(size_t c = 0; c < 512; ++c) {
|
// (iii) the Mac pulse-width modulates whatever it reads from the disk speed buffer;
|
||||||
if(samples_[c] > centre) ++ samples_over;
|
// (iv) ... subject to software pulse-width modulation of that pulse-width modulation.
|
||||||
sum += samples_[c];
|
//
|
||||||
}
|
// So, I believe current motor speed is proportional to a low-pass filtering of
|
||||||
|
// the speed buffer. Which I've implemented very coarsely via 'large' bucketed-averages,
|
||||||
|
// noting also that exact disk motor speed is always a little approximate.
|
||||||
|
|
||||||
|
// Sum all samples.
|
||||||
// TODO: if the above is the correct test, do it on sample receipt rather than
|
// TODO: if the above is the correct test, do it on sample receipt rather than
|
||||||
// bothering with an intermediate buffer.
|
// bothering with an intermediate buffer.
|
||||||
|
int sum = 0;
|
||||||
|
for(auto s: samples_) {
|
||||||
|
sum += s;
|
||||||
|
}
|
||||||
|
|
||||||
// The below fits for a function like `a + bc`.
|
// The formula below was derived from observing values the Mac wrote into its
|
||||||
const float rotation_speed = (float(sum) * 0.052896440564137f) - 259.0f;
|
// disk-speed buffer. Given that it runs a calibration loop before doing so,
|
||||||
|
// I cannot guarantee the accuracy of these numbers beyond being within the
|
||||||
|
// range that the computer would accept.
|
||||||
|
const float normalised_sum = float(sum) / float(samples_.size());
|
||||||
|
const float rotation_speed = (normalised_sum * 27.08f) - 259.0f;
|
||||||
|
|
||||||
for(int c = 0; c < number_of_drives_; ++c) {
|
for(int c = 0; c < number_of_drives_; ++c) {
|
||||||
drives_[c]->set_rotation_speed(rotation_speed);
|
drives_[c]->set_rotation_speed(rotation_speed);
|
||||||
}
|
}
|
||||||
// printf("RPM: %0.2f (%d over; %d sum)\n", rotation_speed, samples_over, sum);
|
// printf("RPM: %0.2f (%d sum)\n", rotation_speed, sum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class DriveSpeedAccumulator {
|
|||||||
void add_drive(Apple::Macintosh::DoubleDensityDrive *drive);
|
void add_drive(Apple::Macintosh::DoubleDensityDrive *drive);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<uint8_t, 512> samples_;
|
std::array<uint8_t, 20> samples_;
|
||||||
std::size_t sample_pointer_ = 0;
|
std::size_t sample_pointer_ = 0;
|
||||||
Apple::Macintosh::DoubleDensityDrive *drives_[2] = {nullptr, nullptr};
|
Apple::Macintosh::DoubleDensityDrive *drives_[2] = {nullptr, nullptr};
|
||||||
int number_of_drives_ = 0;
|
int number_of_drives_ = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user