1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Implements motor latching, drive ID shift registers.

This commit is contained in:
Thomas Harte 2021-10-05 05:12:01 -07:00
parent e47bec2e65
commit 647ec770ce
2 changed files with 86 additions and 25 deletions

View File

@ -950,8 +950,8 @@ uint8_t Chipset::CIAAHandler::get_port_input(MOS::MOS6526::Port port) {
} else {
LOG("TODO: CIA A, port A input — FIR, RDY, TRK0, etc");
// Announce that TRK0 is upon us.
return 0xef;
// TODO: add in FIR1, FIR0.
return controller_.get_rdy_trk0_wpro_chng();
}
return 0xff;
}
@ -973,24 +973,7 @@ void Chipset::CIABHandler::set_port_output(MOS::MOS6526::Port port, uint8_t valu
//
// Disk motor control, drive and head selection,
// and stepper control:
//
// b7: /MTR
// b6: /SEL3
// b5: /SEL2
// b4: /SEL1
// b3: /SEL0
// b2: /SIDE
// b1: DIR
// b0: /STEP
LOG("TODO: Stepping, etc; " << PADHEX(2) << +value);
controller_.set_drive((value >> 3) & 0xf);
// "[The MTR] signal is nonstandard on the Amiga system.
// Each drive will latch the motor signal at the time its
// select signal turns on." — The Hardware Reference Manual.
previous_select_ = value;
controller_.set_mtr_sel_side_dir_step(value);
} else {
// CIA B, Port A: Serial port control.
//
@ -1006,7 +989,7 @@ void Chipset::CIABHandler::set_port_output(MOS::MOS6526::Port port, uint8_t valu
}
}
uint8_t Chipset::CIABHandler::get_port_input(MOS::MOS6526::Port port) {
uint8_t Chipset::CIABHandler::get_port_input(MOS::MOS6526::Port) {
LOG("Unexpected input for CIA B");
return 0xff;
}
@ -1030,3 +1013,78 @@ void Chipset::DiskController::process_input_bit(int value) {
void Chipset::DiskController::process_index_hole() {
// TODO: does the Amiga care?
}
void Chipset::DiskController::set_mtr_sel_side_dir_step(uint8_t value) {
// b7: /MTR
// b6: /SEL3
// b5: /SEL2
// b4: /SEL1
// b3: /SEL0
// b2: /SIDE
// b1: DIR
// b0: /STEP
// Select active drive.
set_drive((value >> 3) & 0xf);
// "[The MTR] signal is nonstandard on the Amiga system.
// Each drive will latch the motor signal at the time its
// select signal turns on." — The Hardware Reference Manual.
const auto difference = int(previous_select_ ^ value);
previous_select_ = value;
// Check for changes in the SEL line per drive.
const bool motor_on = !(value & 0x80);
for(int c = 0; c < 4; c++) {
// If drive went from unselected to selected, latch
// the new motor value; if the motor goes active,
// reset the drive ID shift register.
const int select_mask = 0x08 << c;
if(difference & value & select_mask) {
auto drive = get_drive(size_t(c));
// Shift the drive ID value.
drive_ids_[c] <<= 1;
LOG("Shifted drive ID shift register for drive " << +c);
// Motor transition off -> on => reload register.
if(motor_on && !drive.get_motor_on()) {
// NB:
// 0xffff'ffff = 3.5" drive;
// 0x5555'5555 = 5.25" drive;
// 0x0000'0000 = no drive.
drive_ids_[c] = 0xffff'ffff;
LOG("Reloaded drive ID shift register for drive " << +c);
}
// Also latch the new motor state.
drive.set_motor_on(motor_on);
}
}
}
uint8_t Chipset::DiskController::get_rdy_trk0_wpro_chng() {
// b5: /RDY
// b4: /TRK0
// b3: /WPRO
// b2: /CHNG
// My interpretation:
//
// RDY isn't RDY, it's a shift value as described above.
// CHNG is what is normally RDY.
const uint32_t combined_id =
((previous_select_ & 0x40) ? drive_ids_[3] : 0) |
((previous_select_ & 0x20) ? drive_ids_[2] : 0) |
((previous_select_ & 0x10) ? drive_ids_[1] : 0) |
((previous_select_ & 0x08) ? drive_ids_[0] : 0);
auto drive = get_drive();
const uint8_t active_high =
((combined_id & 0x8000) >> 11) |
(drive.get_is_ready() ? 0x02 : 0x00) |
(drive.get_is_track_zero() ? 0x10 : 0x00) |
(drive.get_is_read_only() ? 0x08 : 0x00);
return 0xff & ~active_high;
}

View File

@ -222,14 +222,18 @@ class Chipset {
public:
DiskController(Cycles clock_rate);
void set_drive(int index_mask) {
Storage::Disk::Controller::set_drive(index_mask);
}
void set_mtr_sel_side_dir_step(uint8_t);
uint8_t get_rdy_trk0_wpro_chng();
private:
void process_input_bit(int value) final;
void process_index_hole() final;
// Implement the Amiga's drive ID shift registers
// directly in the controller for now.
uint32_t drive_ids_[4]{};
uint32_t previous_select_ = 0;
} disk_controller_;
class DiskDMA: public DMADevice<1> {
@ -284,7 +288,6 @@ class Chipset {
private:
DiskController &controller_;
uint8_t previous_select_ = 0;
} cia_b_handler_;
public: