1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-13 00:29:14 +00:00
CLK/Components/8272/Status.hpp

132 lines
2.7 KiB
C++
Raw Normal View History

//
// 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,
2023-11-29 03:34:34 +00:00
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,
2024-12-01 14:04:32 +00:00
DataError = 0x20,
OverRun = 0x10,
NoData = 0x04,
NotWriteable = 0x02,
MissingAddressMark = 0x01,
};
enum class Status2: uint8_t {
DeletedControlMark = 0x40,
2024-12-01 14:04:32 +00:00
DataCRCError = 0x20,
WrongCyinder = 0x10,
ScanEqualHit = 0x08,
ScanNotSatisfied = 0x04,
BadCylinder = 0x02,
MissingDataAddressMark = 0x01,
};
enum class Status3: uint8_t {
Fault = 0x80,
2024-12-01 14:04:32 +00:00
WriteProtected = 0x40,
Ready = 0x20,
2023-11-28 04:05:37 +00:00
Track0 = 0x10,
TwoSided = 0x08,
HeadAddress = 0x04,
UnitSelect = 0x03,
};
class Status {
2024-11-30 03:43:54 +00:00
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 [](const int index) const {
return status_[index];
}
//
// Flag setters.
//
void set(const MainStatus flag, const bool value) {
set(uint8_t(flag), value, main_status_);
}
2024-12-01 14:04:32 +00:00
void start_seek(const int drive) { main_status_ |= 1 << drive; }
2024-11-30 03:43:54 +00:00
void set(const Status0 flag) { set(uint8_t(flag), true, status_[0]); }
2024-12-01 14:04:32 +00:00
void set(const Status1 flag) { set(uint8_t(flag), true, status_[1]); }
2024-11-30 03:43:54 +00:00
void set(const Status2 flag) { set(uint8_t(flag), true, status_[2]); }
void set_status0(uint8_t value) { status_[0] = value; }
//
// Flag getters.
//
bool get(const MainStatus flag) { return main_status_ & uint8_t(flag); }
bool get(const 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();
}
2024-11-30 03:43:54 +00:00
}
private:
void set(const uint8_t flag, const bool value, uint8_t &target) {
if(value) {
target |= flag;
} else {
target &= ~flag;
}
2024-11-30 03:43:54 +00:00
}
2024-11-30 03:43:54 +00:00
uint8_t main_status_;
uint8_t status_[3];
};
}