mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-12 00:30:31 +00:00
Numerous IWM fixes: the machine now seems to be trying to measure the tachometer.
This commit is contained in:
parent
08671ed69c
commit
7591906777
@ -92,7 +92,7 @@ static Media GetMediaAndPlatforms(const std::string &file_name, TargetPlatform::
|
|||||||
Format("81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 81
|
Format("81", result.tapes, Tape::ZX80O81P, TargetPlatform::ZX8081) // 81
|
||||||
Format("a26", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26
|
Format("a26", result.cartridges, Cartridge::BinaryDump, TargetPlatform::Atari2600) // A26
|
||||||
Format("adf", result.disks, Disk::DiskImageHolder<Storage::Disk::AcornADF>, TargetPlatform::Acorn) // ADF
|
Format("adf", result.disks, Disk::DiskImageHolder<Storage::Disk::AcornADF>, TargetPlatform::Acorn) // ADF
|
||||||
Format("bin", result.cartridges, Cartridge::BinaryDump, TargetPlatform::AllCartridge) // BIN (cartridge dump)
|
// Format("bin", result.cartridges, Cartridge::BinaryDump, TargetPlatform::AllCartridge) // BIN (cartridge dump)
|
||||||
Format("bin", result.disks, Disk::DiskImageHolder<Storage::Disk::PlusTooBIN>, TargetPlatform::Macintosh) // BIN (PlusToo disk image)
|
Format("bin", result.disks, Disk::DiskImageHolder<Storage::Disk::PlusTooBIN>, TargetPlatform::Macintosh) // BIN (PlusToo disk image)
|
||||||
Format("cas", result.tapes, Tape::CAS, TargetPlatform::MSX) // CAS
|
Format("cas", result.tapes, Tape::CAS, TargetPlatform::MSX) // CAS
|
||||||
Format("cdt", result.tapes, Tape::TZX, TargetPlatform::AmstradCPC) // CDT
|
Format("cdt", result.tapes, Tape::TZX, TargetPlatform::AmstradCPC) // CDT
|
||||||
|
@ -54,10 +54,10 @@ uint8_t IWM::read(int address) {
|
|||||||
return 0xff;
|
return 0xff;
|
||||||
|
|
||||||
// "Read all 1s".
|
// "Read all 1s".
|
||||||
case 0:
|
// printf("Reading all 1s\n");
|
||||||
printf("Reading all 1s\n");
|
// return 0xff;
|
||||||
return 0xff;
|
|
||||||
|
|
||||||
|
case 0:
|
||||||
case ENABLE: /* Read data register. */
|
case ENABLE: /* Read data register. */
|
||||||
if(data_register_ & 0x80) {
|
if(data_register_ & 0x80) {
|
||||||
printf("[%02x] ", data_register_);
|
printf("[%02x] ", data_register_);
|
||||||
@ -78,30 +78,37 @@ 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 (including [%d] ", active_drive_);
|
printf("Reading status (including [%d][%c%c%c%c] ", active_drive_, (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-');
|
||||||
|
|
||||||
// Determine the SENSE input.
|
// Determine the SENSE input.
|
||||||
uint8_t sense = 0x00;
|
uint8_t sense = 0x00;
|
||||||
switch(state_ & (CA2 | CA1 | CA0 | SEL)) {
|
switch(state_ & (CA2 | CA1 | CA0 | SEL)) {
|
||||||
default:
|
default:
|
||||||
printf("unknown [%c%c%c%c])\n", (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-');
|
printf("unknown)\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0: // Head step direction.
|
// 4 = step finished (0 = done)
|
||||||
printf("head step direction)\n");
|
// B = ready (0 = ready)
|
||||||
break;
|
// 8 = motor on
|
||||||
|
//
|
||||||
|
// {CA1,CA0,SEL,CA2}
|
||||||
|
|
||||||
|
// case 0: // Head step direction.
|
||||||
|
// printf("head step direction)\n");
|
||||||
|
// break;
|
||||||
|
|
||||||
case SEL: // Disk in place.
|
case SEL: // Disk in place.
|
||||||
printf("disk in place)\n");
|
printf("disk in place)\n");
|
||||||
sense = drives_[active_drive_] && drives_[active_drive_]->has_disk() ? 0x00 : 0x80;
|
sense = drives_[active_drive_] && drives_[active_drive_]->has_disk() ? 0x00 : 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CA0: // Disk head stepping.
|
// case CA0: // Disk head step completed (1 = still stepping?).
|
||||||
printf("head stepping)\n");
|
// printf("head stepping)\n");
|
||||||
break;
|
// break;
|
||||||
|
//
|
||||||
case CA0|SEL: // Disk locked (i.e. write-protect tab).
|
case CA0|SEL: // Disk locked (i.e. write-protect tab).
|
||||||
printf("disk locked)\n");
|
printf("disk locked)\n");
|
||||||
|
sense = drives_[active_drive_] && drives_[active_drive_]->get_is_read_only() ? 0x00 : 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CA1: // Disk motor running.
|
case CA1: // Disk motor running.
|
||||||
@ -116,21 +123,24 @@ uint8_t IWM::read(int address) {
|
|||||||
|
|
||||||
case CA1|CA0|SEL: // Tachometer (?)
|
case CA1|CA0|SEL: // Tachometer (?)
|
||||||
printf("tachometer)\n");
|
printf("tachometer)\n");
|
||||||
|
sense = drives_[active_drive_] && drives_[active_drive_]->get_tachometer() ? 0x00 : 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CA2: // Read data, lower head.
|
// case CA2: // Read data, lower head.
|
||||||
printf("data, lower head)\n");
|
// printf("data, lower head)\n");
|
||||||
break;
|
// break;
|
||||||
|
//
|
||||||
case CA2|SEL: // Read data, upper head.
|
// case CA2|SEL: // Read data, upper head.
|
||||||
printf("data, upper head)\n");
|
// printf("data, upper head)\n");
|
||||||
break;
|
// break;
|
||||||
|
//
|
||||||
case CA2|CA1: // Single- or double-sided drive.
|
case CA2|CA1: // Single- or double-sided drive.
|
||||||
printf("single- or double-sided drive)\n");
|
printf("single- or double-sided drive)\n");
|
||||||
|
sense = drives_[active_drive_] && (drives_[active_drive_]->get_head_count() == 1) ? 0x00 : 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CA2|CA1|CA0|SEL: // Drive installed.
|
case CA2|CA1|CA0: // Drive installed. (per the Mac Plus ROM)
|
||||||
|
case CA2|CA1|CA0|SEL: // Drive installed. (per Inside Macintosh)
|
||||||
printf("drive installed)\n");
|
printf("drive installed)\n");
|
||||||
sense = drives_[active_drive_] ? 0x00 : 0x80;
|
sense = drives_[active_drive_] ? 0x00 : 0x80;
|
||||||
break;
|
break;
|
||||||
@ -151,7 +161,7 @@ uint8_t IWM::read(int address) {
|
|||||||
bit 7: 1 = write data buffer ready for data.
|
bit 7: 1 = write data buffer ready for data.
|
||||||
*/
|
*/
|
||||||
printf("Reading write handshake\n");
|
printf("Reading write handshake\n");
|
||||||
return 0x1f;
|
return 0x1f | 0x80 | 0x40;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0xff;
|
return 0xff;
|
||||||
@ -203,11 +213,13 @@ void IWM::access(int address) {
|
|||||||
address &= 0xf;
|
address &= 0xf;
|
||||||
const auto mask = 1 << (address >> 1);
|
const auto mask = 1 << (address >> 1);
|
||||||
|
|
||||||
|
// printf("[(%02x) %c%c%c%c ", mask, (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-');
|
||||||
if(address & 1) {
|
if(address & 1) {
|
||||||
state_ |= mask;
|
state_ |= mask;
|
||||||
} else {
|
} else {
|
||||||
state_ &= ~mask;
|
state_ &= ~mask;
|
||||||
}
|
}
|
||||||
|
// printf("-> %c%c%c%c] ", (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-');
|
||||||
|
|
||||||
// React appropriately to motor requests.
|
// React appropriately to motor requests.
|
||||||
switch(address >> 1) {
|
switch(address >> 1) {
|
||||||
@ -229,7 +241,7 @@ void IWM::access(int address) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: {
|
case 5: {
|
||||||
const int new_drive = address & 1;
|
const int new_drive = (address & 1)^1;
|
||||||
if(new_drive != active_drive_) {
|
if(new_drive != active_drive_) {
|
||||||
if(drives_[active_drive_]) drives_[active_drive_]->set_motor_on(false);
|
if(drives_[active_drive_]) drives_[active_drive_]->set_motor_on(false);
|
||||||
active_drive_ = new_drive;
|
active_drive_ = new_drive;
|
||||||
@ -240,11 +252,11 @@ void IWM::access(int address) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IWM::set_select(bool enabled) {
|
void IWM::set_select(bool enabled) {
|
||||||
// Augment switch state with the value of the SEL line;
|
// Store SEL as an extra state bit.
|
||||||
// it's active low, which is implicitly inverted here for
|
// printf("[%c%c%c%c ", (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-');
|
||||||
// consistency in the meaning of state_ bits.
|
if(enabled) state_ |= SEL;
|
||||||
if(!enabled) state_ |= 0x100;
|
else state_ &= ~SEL;
|
||||||
else state_ &= ~0x100;
|
// printf("-> %c%c%c%c] ", (state_ & CA2) ? '2' : '-', (state_ & CA1) ? '1' : '-', (state_ & CA0) ? '0' : '-', (state_ & SEL) ? 'S' : '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Active logic
|
// MARK: - Active logic
|
||||||
@ -264,6 +276,7 @@ void IWM::run_for(const Cycles cycles) {
|
|||||||
const bool run_disk = drive_motor_on_ && drives_[active_drive_];
|
const bool run_disk = drive_motor_on_ && drives_[active_drive_];
|
||||||
int integer_cycles = cycles.as_int();
|
int integer_cycles = cycles.as_int();
|
||||||
switch(state_ & (Q6 | Q7 | ENABLE)) {
|
switch(state_ & (Q6 | Q7 | ENABLE)) {
|
||||||
|
case 0:
|
||||||
case ENABLE: // i.e. read mode.
|
case ENABLE: // i.e. read mode.
|
||||||
while(integer_cycles--) {
|
while(integer_cycles--) {
|
||||||
if(run_disk) {
|
if(run_disk) {
|
||||||
@ -306,4 +319,3 @@ void IWM::set_drive(int slot, Storage::Disk::Drive *drive) {
|
|||||||
drives_[slot] = drive;
|
drives_[slot] = drive;
|
||||||
drive->set_event_delegate(this);
|
drive->set_event_delegate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,6 +187,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
|
|
||||||
case 0x68f000:
|
case 0x68f000:
|
||||||
// The IWM; this is a purely polled device, so can be run on demand.
|
// The IWM; this is a purely polled device, so can be run on demand.
|
||||||
|
// printf("[%06x]: ", mc68000_.get_state().program_counter);
|
||||||
iwm_.flush();
|
iwm_.flush();
|
||||||
if(cycle.operation & Microcycle::Read) {
|
if(cycle.operation & Microcycle::Read) {
|
||||||
cycle.value->halves.low = iwm_.iwm.read(register_address);
|
cycle.value->halves.low = iwm_.iwm.read(register_address);
|
||||||
@ -368,7 +369,8 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
b2–b0: audio output volume
|
b2–b0: audio output volume
|
||||||
*/
|
*/
|
||||||
iwm_.flush();
|
iwm_.flush();
|
||||||
iwm_.iwm.set_select(!(value & 0x20));
|
printf("{SEL: %c} ", (value & 0x20) ? 't' : 'f');
|
||||||
|
iwm_.iwm.set_select(!!(value & 0x20));
|
||||||
|
|
||||||
machine_.set_use_alternate_buffers(!(value & 0x40), !(value&0x08));
|
machine_.set_use_alternate_buffers(!(value & 0x40), !(value&0x08));
|
||||||
machine_.set_rom_is_overlay(!!(value & 0x10));
|
machine_.set_rom_is_overlay(!!(value & 0x10));
|
||||||
@ -406,6 +408,7 @@ template <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
|
|||||||
|
|
||||||
case Port::B:
|
case Port::B:
|
||||||
return
|
return
|
||||||
|
0x08 | // Mouse button not down.
|
||||||
(clock_.get_data() ? 0x02 : 0x00) |
|
(clock_.get_data() ? 0x02 : 0x00) |
|
||||||
(video_.is_outputting() ? 0x00 : 0x40);
|
(video_.is_outputting() ? 0x00 : 0x40);
|
||||||
// TODO: mouse button, y2, x2
|
// TODO: mouse button, y2, x2
|
||||||
|
@ -216,7 +216,7 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
|||||||
|
|
||||||
case ExecutionState::BeginInterrupt:
|
case ExecutionState::BeginInterrupt:
|
||||||
#ifdef LOG_TRACE
|
#ifdef LOG_TRACE
|
||||||
should_log = true;
|
// should_log = true;
|
||||||
#endif
|
#endif
|
||||||
active_program_ = nullptr;
|
active_program_ = nullptr;
|
||||||
active_micro_op_ = interrupt_micro_ops_;
|
active_micro_op_ = interrupt_micro_ops_;
|
||||||
@ -284,7 +284,8 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOG_TRACE
|
#ifdef LOG_TRACE
|
||||||
should_log |= (program_counter_.full - 4) == 0x00400690;
|
should_log |= (program_counter_.full - 4) == 0x004006F4;
|
||||||
|
// should_log = ((program_counter_.full - 4) >= 0x417D9E) && ((program_counter_.full - 4) <= 0x419D96);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(instructions[decoded_instruction_.full].micro_operations) {
|
if(instructions[decoded_instruction_.full].micro_operations) {
|
||||||
|
@ -112,6 +112,15 @@ int Drive::get_head_count() {
|
|||||||
return available_heads_;
|
return available_heads_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Drive::get_tachometer() {
|
||||||
|
// First guess: the tachometer ticks once per rotation.
|
||||||
|
return get_rotation() > 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Drive::get_rotation() {
|
||||||
|
return get_time_into_track().get<float>();
|
||||||
|
}
|
||||||
|
|
||||||
Storage::Time Drive::get_time_into_track() {
|
Storage::Time Drive::get_time_into_track() {
|
||||||
// `result` will initially be amount of time since the index hole was seen as a
|
// `result` will initially be amount of time since the index hole was seen as a
|
||||||
// proportion of a second; convert it into proportion of a rotation, simplify and return.
|
// proportion of a second; convert it into proportion of a rotation, simplify and return.
|
||||||
|
@ -149,9 +149,23 @@ class Drive: public ClockingHint::Source, public TimedEventLoop {
|
|||||||
*/
|
*/
|
||||||
void set_rotation_speed(float revolutions_per_minute);
|
void set_rotation_speed(float revolutions_per_minute);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@returns the current value of the tachometer pulse offered by some drives.
|
||||||
|
*/
|
||||||
|
bool get_tachometer();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/*!
|
||||||
|
Announces the result of a step.
|
||||||
|
*/
|
||||||
virtual void did_step(HeadPosition to_position) {}
|
virtual void did_step(HeadPosition to_position) {}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@returns the current rotation of the disk, a float in the half-open range
|
||||||
|
0.0 (the index hole) to 1.0 (back to the index hole, a whole rotation later).
|
||||||
|
*/
|
||||||
|
float get_rotation();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Drives contain an entire disk; from that a certain track
|
// Drives contain an entire disk; from that a certain track
|
||||||
// will be currently under the head.
|
// will be currently under the head.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user