mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-29 12:50:28 +00:00
132 lines
2.7 KiB
C++
132 lines
2.7 KiB
C++
//
|
|
// Status.hpp
|
|
// Clock Signal
|
|
//
|
|
// Created by Thomas Harte on 25/11/2023.
|
|
// Copyright © 2023 Thomas Harte. All rights reserved.
|
|
//
|
|
|
|
#pragma once
|
|
|
|
namespace Intel::i8272 {
|
|
|
|
enum class MainStatus: uint8_t {
|
|
FDD0Seeking = 0x01,
|
|
FDD1Seeking = 0x02,
|
|
FDD2Seeking = 0x04,
|
|
FDD3Seeking = 0x08,
|
|
|
|
CommandInProgress = 0x10,
|
|
InNonDMAExecution = 0x20,
|
|
DataIsToProcessor = 0x40,
|
|
DataReady = 0x80,
|
|
};
|
|
|
|
enum class Status0: uint8_t {
|
|
NormalTermination = 0x00,
|
|
AbnormalTermination = 0x80,
|
|
InvalidCommand = 0x40,
|
|
BecameNotReady = 0xc0,
|
|
|
|
SeekEnded = 0x20,
|
|
EquipmentFault = 0x10,
|
|
NotReady = 0x08,
|
|
|
|
HeadAddress = 0x04,
|
|
UnitSelect = 0x03,
|
|
};
|
|
|
|
enum class Status1: uint8_t {
|
|
EndOfCylinder = 0x80,
|
|
DataError = 0x20,
|
|
OverRun = 0x10,
|
|
NoData = 0x04,
|
|
NotWriteable = 0x02,
|
|
MissingAddressMark = 0x01,
|
|
};
|
|
|
|
enum class Status2: uint8_t {
|
|
DeletedControlMark = 0x40,
|
|
DataCRCError = 0x20,
|
|
WrongCyinder = 0x10,
|
|
ScanEqualHit = 0x08,
|
|
ScanNotSatisfied = 0x04,
|
|
BadCylinder = 0x02,
|
|
MissingDataAddressMark = 0x01,
|
|
};
|
|
|
|
enum class Status3: uint8_t {
|
|
Fault = 0x80,
|
|
WriteProtected = 0x40,
|
|
Ready = 0x20,
|
|
Track0 = 0x10,
|
|
TwoSided = 0x08,
|
|
HeadAddress = 0x04,
|
|
UnitSelect = 0x03,
|
|
};
|
|
|
|
class Status {
|
|
public:
|
|
Status() {
|
|
reset();
|
|
}
|
|
|
|
void reset() {
|
|
main_status_ = 0;
|
|
set(MainStatus::DataReady, true);
|
|
status_[0] = status_[1] = status_[2] = 0;
|
|
}
|
|
|
|
/// @returns The main status register value.
|
|
uint8_t main() const {
|
|
return main_status_;
|
|
}
|
|
uint8_t operator [](int index) const {
|
|
return status_[index];
|
|
}
|
|
|
|
//
|
|
// Flag setters.
|
|
//
|
|
void set(MainStatus flag, bool value) {
|
|
set(uint8_t(flag), value, main_status_);
|
|
}
|
|
void start_seek(int drive) { main_status_ |= 1 << drive; }
|
|
void set(Status0 flag) { set(uint8_t(flag), true, status_[0]); }
|
|
void set(Status1 flag) { set(uint8_t(flag), true, status_[1]); }
|
|
void set(Status2 flag) { set(uint8_t(flag), true, status_[2]); }
|
|
|
|
void set_status0(uint8_t value) { status_[0] = value; }
|
|
|
|
//
|
|
// Flag getters.
|
|
//
|
|
bool get(MainStatus flag) { return main_status_ & uint8_t(flag); }
|
|
bool get(Status2 flag) { return status_[2] & uint8_t(flag); }
|
|
|
|
/// Begin execution of whatever @c CommandDecoder currently describes, setting internal
|
|
/// state appropriately.
|
|
void begin(const CommandDecoder &command) {
|
|
set(MainStatus::DataReady, false);
|
|
set(MainStatus::CommandInProgress, true);
|
|
|
|
if(command.is_access()) {
|
|
status_[0] = command.drive_head();
|
|
}
|
|
}
|
|
|
|
private:
|
|
void set(uint8_t flag, bool value, uint8_t &target) {
|
|
if(value) {
|
|
target |= flag;
|
|
} else {
|
|
target &= ~flag;
|
|
}
|
|
}
|
|
|
|
uint8_t main_status_;
|
|
uint8_t status_[3];
|
|
};
|
|
|
|
}
|