mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 01:31:42 +00:00
This is clearly the winning solution. Edited down.
This commit is contained in:
parent
07ff5138b7
commit
d50629e6aa
@ -73,201 +73,6 @@ void WD1770::run_for_cycles(unsigned int number_of_cycles)
|
||||
delay_time_ -= number_of_cycles;
|
||||
}
|
||||
}
|
||||
// perform one step every eight cycles, arbitrariy as I can find no timing documentation
|
||||
/* cycles += number_of_cycles;
|
||||
while(cycles > 8)
|
||||
{
|
||||
cycles -= 8;
|
||||
if(status_ & Flag::MotorOn) Storage::Disk::Drive::run_for_cycles(1);
|
||||
|
||||
switch(state_)
|
||||
{
|
||||
case State::Waiting:
|
||||
if(has_command_)
|
||||
{
|
||||
has_command_ = false;
|
||||
if(command_ & 0x80)
|
||||
state_ = (command_ & 0x40) ? State::BeginType3 : State::BeginType2;
|
||||
else
|
||||
state_ = State::BeginType1;
|
||||
}
|
||||
continue;
|
||||
|
||||
case State::WaitForSixIndexPulses:
|
||||
status_ |= Flag::MotorOn;
|
||||
// deliberately empty; logic is in ::process_index_hole
|
||||
continue;
|
||||
|
||||
#pragma mark - Type 1
|
||||
|
||||
case State::BeginType1:
|
||||
status_ |= Flag::Busy;
|
||||
status_ &= ~(Flag::DataRequest | Flag::CRCError);
|
||||
set_interrupt_request(false);
|
||||
state_ = State::BeginType1PostSpin;
|
||||
if(command_ & 0x08)
|
||||
{
|
||||
wait_six_index_pulses_.next_state = state_;
|
||||
index_hole_count_ = 0;
|
||||
state_ = State::WaitForSixIndexPulses;
|
||||
}
|
||||
continue;
|
||||
|
||||
case State::BeginType1PostSpin:
|
||||
switch(command_ >> 4)
|
||||
{
|
||||
case 0: // restore
|
||||
track_ = 0xff; // deliberate fallthrough
|
||||
case 1: // seek
|
||||
data_ = 0x00;
|
||||
break;
|
||||
case 2: case 3: // step
|
||||
break;
|
||||
case 4: case 5: // step in
|
||||
is_step_in_ = true;
|
||||
break;
|
||||
case 6: case 7: // step out
|
||||
is_step_in_ = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!(command_ >> 5))
|
||||
state_ = State::TestTrack;
|
||||
else
|
||||
state_ = (command_ & 0x10) ? State::TestDirection : State::TestHead;
|
||||
continue;
|
||||
|
||||
case State::TestTrack:
|
||||
data_shift_register_ = data_;
|
||||
if(track_ == data_shift_register_)
|
||||
state_ = State::TestVerify;
|
||||
else
|
||||
{
|
||||
is_step_in_ = (data_shift_register_ < track_);
|
||||
state_ = State::TestDirection;
|
||||
}
|
||||
continue;
|
||||
|
||||
case State::TestDirection:
|
||||
track_ += is_step_in_ ? -1 : +1;
|
||||
state_ = State::TestHead;
|
||||
continue;
|
||||
|
||||
case State::TestHead:
|
||||
if(get_is_track_zero() && !is_step_in_)
|
||||
{
|
||||
track_ = 0;
|
||||
state_ = State::TestVerify;
|
||||
}
|
||||
else
|
||||
{
|
||||
step(is_step_in_ ? 1 : -1);
|
||||
state_ = State::StepDelay;
|
||||
step_delay_.count = 0;
|
||||
}
|
||||
continue;
|
||||
|
||||
case State::StepDelay:
|
||||
if(step_delay_.count == (command_&3))
|
||||
{
|
||||
state_ = (command_ >> 5) ? State::TestVerify : State::TestTrack;
|
||||
}
|
||||
step_delay_.count++;
|
||||
continue;
|
||||
|
||||
case State::TestVerify:
|
||||
if(command_ & 0x04)
|
||||
{
|
||||
state_ = State::VerifyTrack;
|
||||
}
|
||||
else
|
||||
{
|
||||
set_interrupt_request(true);
|
||||
status_ &= ~Flag::Busy;
|
||||
state_ = State::Waiting;
|
||||
}
|
||||
continue;
|
||||
|
||||
#pragma mark - Type 2
|
||||
|
||||
case State::BeginType2:
|
||||
status_ |= Flag::Busy;
|
||||
status_ &= ~(Flag::DataRequest | Flag::LostData | Flag::RecordNotFound | 0x60);
|
||||
state_ = State::TestPause;
|
||||
if(!(command_&0x08))
|
||||
{
|
||||
wait_six_index_pulses_.next_state = state_;
|
||||
index_hole_count_ = 0;
|
||||
state_ = State::WaitForSixIndexPulses;
|
||||
}
|
||||
continue;
|
||||
|
||||
case State::TestPause:
|
||||
// TODO: pause for 30ms if E is set
|
||||
state_ = State::TestWriteProtect;
|
||||
continue;
|
||||
|
||||
case State::TestWriteProtect:
|
||||
if(command_ & 0x20) // TODO: && write protect
|
||||
{
|
||||
set_interrupt_request(true);
|
||||
status_ &= ~Flag::Busy;
|
||||
status_ |= Flag::WriteProtect;
|
||||
state_ = State::Waiting;
|
||||
}
|
||||
else
|
||||
{
|
||||
get_header_.found_id = false;
|
||||
state_ = State::GetHeader;
|
||||
}
|
||||
continue;
|
||||
|
||||
case State::GetHeader:
|
||||
if(index_hole_count_ == 5)
|
||||
{
|
||||
set_interrupt_request(true);
|
||||
status_ &= ~Flag::Busy;
|
||||
status_ |= Flag::RecordNotFound;
|
||||
state_ = State::Waiting;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(get_header_.found_id)
|
||||
{
|
||||
if(token_counter_ > 0 && latest_token_.type != Token::Byte)
|
||||
{
|
||||
get_header_.found_id = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(token_counter_ == 5)
|
||||
{
|
||||
}
|
||||
else if(token_counter_ > 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(latest_token_.type == Token::ID)
|
||||
{
|
||||
get_header_.found_id = true;
|
||||
token_counter_ = 0;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
static bool has_hit_error = false;
|
||||
if(!has_hit_error)
|
||||
printf("Unhandled state %d!\n", state_);
|
||||
has_hit_error = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void WD1770::process_input_bit(int value, unsigned int cycles_since_index_hole)
|
||||
|
@ -17,7 +17,6 @@ class WD1770: public Storage::Disk::Drive {
|
||||
public:
|
||||
WD1770();
|
||||
|
||||
// void set_disk(std::shared_ptr<Storage::Disk::Disk> disk);
|
||||
void set_is_double_density(bool is_double_density);
|
||||
void set_register(int address, uint8_t value);
|
||||
uint8_t get_register(int address);
|
||||
@ -47,50 +46,9 @@ class WD1770: public Storage::Disk::Drive {
|
||||
uint8_t command_;
|
||||
|
||||
int index_hole_count_;
|
||||
int bits_since_token_;
|
||||
int distance_into_section_;
|
||||
|
||||
/* enum class State {
|
||||
Waiting,
|
||||
BeginType1, BeginType2, BeginType3,
|
||||
BeginType1PostSpin,
|
||||
WaitForSixIndexPulses,
|
||||
TestTrack, TestDirection, TestHead,
|
||||
TestVerify, VerifyTrack,
|
||||
StepDelay, TestPause, TestWriteProtect,
|
||||
GetHeader,
|
||||
} state_;
|
||||
|
||||
union {
|
||||
struct {
|
||||
State next_state;
|
||||
} wait_six_index_pulses_;
|
||||
struct {
|
||||
int count;
|
||||
} step_delay_;
|
||||
struct {
|
||||
bool found_id;
|
||||
uint8_t value[4];
|
||||
} get_header_;
|
||||
};
|
||||
|
||||
enum class ReadingState {
|
||||
Idle,
|
||||
ReadingHeader,
|
||||
ReadingData
|
||||
} reading_state_;
|
||||
struct {
|
||||
uint8_t track;
|
||||
uint8_t sector;
|
||||
uint8_t length;
|
||||
} header;
|
||||
bool crc_error_;
|
||||
|
||||
int shift_register_;
|
||||
int shift_register_duration_;
|
||||
bool is_double_density_;
|
||||
|
||||
bool has_command_;
|
||||
|
||||
bool is_step_in_;*/
|
||||
int step_direction_;
|
||||
void set_interrupt_request(bool interrupt_request) {}
|
||||
|
||||
@ -103,7 +61,6 @@ class WD1770: public Storage::Disk::Drive {
|
||||
} type;
|
||||
uint8_t byte_value;
|
||||
} latest_token_;
|
||||
int bits_since_token_;
|
||||
|
||||
// Events
|
||||
enum Event: int {
|
||||
@ -118,7 +75,6 @@ class WD1770: public Storage::Disk::Drive {
|
||||
int delay_time_;
|
||||
|
||||
// ID buffer
|
||||
int distance_into_section_;
|
||||
uint8_t header[6];
|
||||
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user