mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-29 12:50:28 +00:00
Separates the 8272's drive selection signalling from actual drive ownership.
Thereby returns working motor control to the CPC.
This commit is contained in:
parent
96bf133924
commit
d3c385b471
@ -119,11 +119,12 @@ void i8272::run_for(Cycles cycles) {
|
||||
// Perform a step.
|
||||
int direction = (drives_[c].target_head_position < drives_[c].head_position) ? -1 : 1;
|
||||
printf("Target %d versus believed %d\n", drives_[c].target_head_position, drives_[c].head_position);
|
||||
drives_[c].drive->step(direction);
|
||||
select_drive(c);
|
||||
get_drive().step(direction);
|
||||
if(drives_[c].target_head_position >= 0) drives_[c].head_position += direction;
|
||||
|
||||
// Check for completion.
|
||||
if(drives_[c].seek_is_satisfied()) {
|
||||
if(seek_is_satisfied(c)) {
|
||||
drives_[c].phase = Drive::CompletedSeeking;
|
||||
drives_seeking_--;
|
||||
break;
|
||||
@ -192,12 +193,6 @@ uint8_t i8272::get_register(int address) {
|
||||
}
|
||||
}
|
||||
|
||||
void i8272::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
|
||||
if(drive < 4 && drive >= 0) {
|
||||
drives_[drive].drive->set_disk(disk);
|
||||
}
|
||||
}
|
||||
|
||||
#define BEGIN_SECTION() switch(resume_point_) { default:
|
||||
#define END_SECTION() }
|
||||
|
||||
@ -235,7 +230,7 @@ void i8272::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
|
||||
#define SET_DRIVE_HEAD_MFM() \
|
||||
active_drive_ = command_[1]&3; \
|
||||
active_head_ = (command_[1] >> 2)&1; \
|
||||
set_drive(drives_[active_drive_].drive); \
|
||||
select_drive(active_drive_); \
|
||||
get_drive().set_head((unsigned int)active_head_); \
|
||||
set_is_double_density(command_[0] & 0x40);
|
||||
|
||||
@ -503,7 +498,7 @@ void i8272::posit_event(int event_type) {
|
||||
write_data:
|
||||
printf("Write [deleted] data [%02x %02x %02x %02x ... %02x %02x]\n", command_[2], command_[3], command_[4], command_[5], command_[6], command_[8]);
|
||||
|
||||
if(drives_[active_drive_].drive->get_is_read_only()) {
|
||||
if(get_drive().get_is_read_only()) {
|
||||
SetNotWriteable();
|
||||
goto abort;
|
||||
}
|
||||
@ -618,7 +613,7 @@ void i8272::posit_event(int event_type) {
|
||||
// Performs format [/write] track.
|
||||
format_track:
|
||||
printf("Format track\n");
|
||||
if(drives_[active_drive_].drive->get_is_read_only()) {
|
||||
if(get_drive().get_is_read_only()) {
|
||||
SetNotWriteable();
|
||||
goto abort;
|
||||
}
|
||||
@ -711,6 +706,7 @@ void i8272::posit_event(int event_type) {
|
||||
seek:
|
||||
{
|
||||
int drive = command_[1]&3;
|
||||
select_drive(drive);
|
||||
|
||||
// Increment the seeking count if this drive wasn't already seeking.
|
||||
if(drives_[drive].phase != Drive::Seeking) {
|
||||
@ -740,7 +736,7 @@ void i8272::posit_event(int event_type) {
|
||||
}
|
||||
|
||||
// Check whether any steps are even needed; if not then mark as completed already.
|
||||
if(drives_[drive].seek_is_satisfied()) {
|
||||
if(seek_is_satisfied(drive)) {
|
||||
drives_[drive].phase = Drive::CompletedSeeking;
|
||||
drives_seeking_--;
|
||||
}
|
||||
@ -792,12 +788,13 @@ void i8272::posit_event(int event_type) {
|
||||
printf("Sense drive status\n");
|
||||
{
|
||||
int drive = command_[1] & 3;
|
||||
select_drive(drive);
|
||||
result_stack_.push_back(
|
||||
(command_[1] & 7) | // drive and head number
|
||||
0x08 | // single sided
|
||||
(drives_[drive].drive->get_is_track_zero() ? 0x10 : 0x00) |
|
||||
(drives_[drive].drive->get_is_ready() ? 0x20 : 0x00) |
|
||||
(drives_[drive].drive->get_is_read_only() ? 0x40 : 0x00)
|
||||
(get_drive().get_is_track_zero() ? 0x10 : 0x00) |
|
||||
(get_drive().get_is_ready() ? 0x20 : 0x00) |
|
||||
(get_drive().get_is_read_only() ? 0x40 : 0x00)
|
||||
);
|
||||
}
|
||||
goto post_result;
|
||||
@ -852,9 +849,9 @@ void i8272::posit_event(int event_type) {
|
||||
END_SECTION()
|
||||
}
|
||||
|
||||
bool i8272::Drive::seek_is_satisfied() {
|
||||
return (target_head_position == head_position) ||
|
||||
(target_head_position == -1 && drive->get_is_track_zero());
|
||||
bool i8272::seek_is_satisfied(int drive) {
|
||||
return (drives_[drive].target_head_position == drives_[drive].head_position) ||
|
||||
(drives_[drive].target_head_position == -1 && get_drive().get_is_track_zero());
|
||||
}
|
||||
|
||||
void i8272::set_dma_acknowledge(bool dack) {
|
||||
|
@ -39,10 +39,11 @@ class i8272: public Storage::Disk::MFMController {
|
||||
void set_dma_acknowledge(bool dack);
|
||||
void set_terminal_count(bool tc);
|
||||
|
||||
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive);
|
||||
|
||||
bool is_sleeping();
|
||||
|
||||
protected:
|
||||
virtual void select_drive(int number) = 0;
|
||||
|
||||
private:
|
||||
// The bus handler, for interrupt and DMA-driven usage.
|
||||
BusHandler &bus_handler_;
|
||||
@ -91,24 +92,20 @@ class i8272: public Storage::Disk::MFMController {
|
||||
int steps_taken;
|
||||
int target_head_position; // either an actual number, or -1 to indicate to step until track zero
|
||||
|
||||
/// @returns @c true if the currently queued-up seek or recalibrate has reached where it should be.
|
||||
bool seek_is_satisfied();
|
||||
|
||||
// Head state.
|
||||
int head_unload_delay[2];
|
||||
bool head_is_loaded[2];
|
||||
|
||||
// The connected drive.
|
||||
std::shared_ptr<Storage::Disk::Drive> drive;
|
||||
|
||||
Drive() :
|
||||
head_position(0), phase(NotSeeking),
|
||||
drive(new Storage::Disk::Drive(8000000, 300)), // TODO: these constants can't live here.
|
||||
head_is_loaded{false, false},
|
||||
head_unload_delay{0, 0} {};
|
||||
} drives_[4];
|
||||
int drives_seeking_;
|
||||
|
||||
/// @returns @c true if the selected drive, which is number @c drive, can stop seeking.
|
||||
bool seek_is_satisfied(int drive);
|
||||
|
||||
// User-supplied parameters; as per the specify command.
|
||||
int step_rate_time_;
|
||||
int head_unload_time_;
|
||||
|
@ -582,13 +582,25 @@ class KeyboardState: public GI::AY38910::PortHandler {
|
||||
class FDC: public Intel::i8272::i8272 {
|
||||
private:
|
||||
Intel::i8272::BusHandler bus_handler_;
|
||||
std::shared_ptr<Storage::Disk::Drive> drive_;
|
||||
|
||||
public:
|
||||
FDC() : i8272(bus_handler_, Cycles(8000000)) {}
|
||||
FDC() :
|
||||
i8272(bus_handler_, Cycles(8000000)),
|
||||
drive_(new Storage::Disk::Drive(8000000, 300)) {
|
||||
set_drive(drive_);
|
||||
}
|
||||
|
||||
void set_motor_on(bool on) {
|
||||
// TODO: should set all motors on, not 8272.hjust the one active drive.
|
||||
get_drive().set_motor_on(on);
|
||||
drive_->set_motor_on(on);
|
||||
}
|
||||
|
||||
void select_drive(int c) {
|
||||
// TODO: support more than one drive.
|
||||
}
|
||||
|
||||
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
|
||||
drive_->set_disk(disk);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user