mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 01:31:42 +00:00
Attempts to respond more sensibly to various queries.
Including adding a 1-second delay on motor off.
This commit is contained in:
parent
983407896c
commit
48d837c636
@ -24,7 +24,12 @@ namespace {
|
|||||||
const int SEL = 1 << 8; /* This is an additional input, not available on a Disk II, with a confusingly-similar name to SELECT but a distinct purpose. */
|
const int SEL = 1 << 8; /* This is an additional input, not available on a Disk II, with a confusingly-similar name to SELECT but a distinct purpose. */
|
||||||
}
|
}
|
||||||
|
|
||||||
IWM::IWM(int clock_rate) {}
|
IWM::IWM(int clock_rate) :
|
||||||
|
clock_rate_(clock_rate),
|
||||||
|
drives_{
|
||||||
|
{static_cast<unsigned int>(clock_rate), 300, 2},
|
||||||
|
{static_cast<unsigned int>(clock_rate), 300, 2}
|
||||||
|
} {}
|
||||||
|
|
||||||
// MARK: - Bus accessors
|
// MARK: - Bus accessors
|
||||||
|
|
||||||
@ -59,13 +64,13 @@ uint8_t IWM::read(int address) {
|
|||||||
|
|
||||||
case ENABLE: /* Read data register. */
|
case ENABLE: /* Read data register. */
|
||||||
printf("Reading data register\n");
|
printf("Reading data register\n");
|
||||||
return 0x00;
|
return 0xff;
|
||||||
|
|
||||||
case Q6: case Q6|ENABLE: {
|
case Q6: case Q6|ENABLE: {
|
||||||
/*
|
/*
|
||||||
[If A = 0], Read status register:
|
[If A = 0], Read status register:
|
||||||
|
|
||||||
bits 0-3: same as mode register.
|
bits 0-4: same as mode register.
|
||||||
bit 5: 1 = either /ENBL1 or /ENBL2 is currently low.
|
bit 5: 1 = either /ENBL1 or /ENBL2 is currently low.
|
||||||
bit 6: 1 = MZ (reserved for future compatibility; should always be read as 0).
|
bit 6: 1 = MZ (reserved for future compatibility; should always be read as 0).
|
||||||
bit 7: 1 = SENSE input high; 0 = SENSE input low.
|
bit 7: 1 = SENSE input high; 0 = SENSE input low.
|
||||||
@ -73,10 +78,10 @@ uint8_t IWM::read(int address) {
|
|||||||
(/ENBL1 is low when the first drive's motor is on; /ENBL2 is low when the second drive's motor is on.
|
(/ENBL1 is low when the first drive's motor is on; /ENBL2 is low when the second drive's motor is on.
|
||||||
If the 1-second timer is enabled, motors remain on for one second after being programmatically disabled.)
|
If the 1-second timer is enabled, motors remain on for one second after being programmatically disabled.)
|
||||||
*/
|
*/
|
||||||
printf("Reading status ([%d] including ", (state_&DRIVESEL) ? 2 : 1);
|
printf("Reading status (including ");
|
||||||
|
|
||||||
// Determine the SENSE input.
|
// Determine the SENSE input.
|
||||||
uint8_t sense = 0x80;
|
uint8_t sense = 0x00;
|
||||||
switch(state_ & (CA2 | CA1 | CA0 | SEL)) {
|
switch(state_ & (CA2 | CA1 | CA0 | SEL)) {
|
||||||
default:
|
default:
|
||||||
printf("unknown)\n");
|
printf("unknown)\n");
|
||||||
@ -88,6 +93,7 @@ uint8_t IWM::read(int address) {
|
|||||||
|
|
||||||
case SEL: // Disk in place.
|
case SEL: // Disk in place.
|
||||||
printf("disk in place)\n");
|
printf("disk in place)\n");
|
||||||
|
sense = drives_[active_drive_].has_disk() ? 0x00 : 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CA0: // Disk head stepping.
|
case CA0: // Disk head stepping.
|
||||||
@ -100,10 +106,12 @@ uint8_t IWM::read(int address) {
|
|||||||
|
|
||||||
case CA1: // Disk motor running.
|
case CA1: // Disk motor running.
|
||||||
printf("disk motor running)\n");
|
printf("disk motor running)\n");
|
||||||
|
sense = drives_[active_drive_].get_motor_on() ? 0x00 : 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CA1|SEL: // Head at track 0.
|
case CA1|SEL: // Head at track 0.
|
||||||
printf("head at track 0)\n");
|
printf("head at track 0)\n");
|
||||||
|
sense = drives_[active_drive_].get_is_track_zero() ? 0x00 : 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CA1|CA0|SEL: // Tachometer (?)
|
case CA1|CA0|SEL: // Tachometer (?)
|
||||||
@ -127,7 +135,10 @@ uint8_t IWM::read(int address) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (mode_&0x1f) | sense;
|
return
|
||||||
|
(mode_&0x1f) |
|
||||||
|
(drives_[active_drive_].get_motor_on() ? 0x20 : 0x00) |
|
||||||
|
sense;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Q7: case Q7|ENABLE:
|
case Q7: case Q7|ENABLE:
|
||||||
@ -188,6 +199,33 @@ void IWM::access(int address) {
|
|||||||
} else {
|
} else {
|
||||||
state_ &= ~mask;
|
state_ &= ~mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// React appropriately to motor requests.
|
||||||
|
switch(address >> 1) {
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if(address & 1) {
|
||||||
|
drives_[active_drive_].set_motor_on(true);
|
||||||
|
} else {
|
||||||
|
// If the 1-second delay is enabled, set up a timer for that.
|
||||||
|
if(!(mode_ & 4)) {
|
||||||
|
cycles_until_motor_off_ = Cycles(clock_rate_);
|
||||||
|
} else {
|
||||||
|
drives_[active_drive_].set_motor_on(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: {
|
||||||
|
const int new_drive = address & 1;
|
||||||
|
if(new_drive != active_drive_) {
|
||||||
|
drives_[new_drive].set_motor_on(drives_[active_drive_].get_motor_on());
|
||||||
|
drives_[active_drive_].set_motor_on(false);
|
||||||
|
active_drive_ = new_drive;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IWM::set_select(bool enabled) {
|
void IWM::set_select(bool enabled) {
|
||||||
@ -201,4 +239,10 @@ void IWM::set_select(bool enabled) {
|
|||||||
// MARK: - Active logic
|
// MARK: - Active logic
|
||||||
|
|
||||||
void IWM::run_for(const Cycles cycles) {
|
void IWM::run_for(const Cycles cycles) {
|
||||||
|
if(cycles_until_motor_off_ > Cycles(0)) {
|
||||||
|
cycles_until_motor_off_ -= cycles;
|
||||||
|
if(cycles_until_motor_off_ <= Cycles(0)) {
|
||||||
|
drives_[active_drive_].set_motor_on(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define IWM_hpp
|
#define IWM_hpp
|
||||||
|
|
||||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||||
|
#include "../../Storage/Disk/Drive.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@ -38,12 +39,19 @@ class IWM {
|
|||||||
void run_for(const Cycles cycles);
|
void run_for(const Cycles cycles);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const int clock_rate_;
|
||||||
|
|
||||||
uint8_t mode_ = 0;
|
uint8_t mode_ = 0;
|
||||||
bool read_write_ready_ = true;
|
bool read_write_ready_ = true;
|
||||||
bool write_overran_ = false;
|
bool write_overran_ = false;
|
||||||
|
|
||||||
int state_ = 0;
|
int state_ = 0;
|
||||||
|
|
||||||
|
int active_drive_ = 0;
|
||||||
|
Storage::Disk::Drive drives_[2];
|
||||||
|
|
||||||
|
Cycles cycles_until_motor_off_;
|
||||||
|
|
||||||
void access(int address);
|
void access(int address);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user