mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-25 09:30:14 +00:00
Start normalising Commodore serial bus interface.
This commit is contained in:
parent
b4b216de84
commit
c92b0dc886
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
using namespace Commodore::Serial;
|
using namespace Commodore::Serial;
|
||||||
|
|
||||||
const char *::Commodore::Serial::StringForLine(Line line) {
|
const char *::Commodore::Serial::to_string(Line line) {
|
||||||
switch(line) {
|
switch(line) {
|
||||||
case ServiceRequest: return "Service request";
|
case ServiceRequest: return "Service request";
|
||||||
case Attention: return "Attention";
|
case Attention: return "Attention";
|
||||||
|
@ -14,115 +14,123 @@
|
|||||||
|
|
||||||
namespace Commodore::Serial {
|
namespace Commodore::Serial {
|
||||||
|
|
||||||
enum Line {
|
enum class Line {
|
||||||
ServiceRequest = 0,
|
ServiceRequest = 0,
|
||||||
Attention,
|
Attention,
|
||||||
Clock,
|
Clock,
|
||||||
Data,
|
Data,
|
||||||
Reset
|
Reset
|
||||||
};
|
};
|
||||||
|
const char *to_string(Line line);
|
||||||
|
|
||||||
enum LineLevel: bool {
|
enum class LineLevel: bool {
|
||||||
High = true,
|
High = true,
|
||||||
Low = false
|
Low = false
|
||||||
};
|
};
|
||||||
|
const char *to_string(LineLevel line);
|
||||||
|
|
||||||
class Port;
|
class Port;
|
||||||
class Bus;
|
class Bus;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns a C string giving a human-readable name for the supplied line.
|
Calls both of the necessary methods to (i) set @c bus as the target for @c port outputs; and
|
||||||
*/
|
(ii) add @c port as one of the targets to which @c bus propagates line changes.
|
||||||
const char *StringForLine(Line line);
|
*/
|
||||||
|
void attach(Port &port, Bus &bus);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Calls both of the necessary methods to (i) set @c bus as the target for @c port outputs; and
|
A serial bus is responsible for retaining a weakly-held collection of attached ports and for deciding the
|
||||||
(ii) add @c port as one of the targets to which @c bus propagates line changes.
|
current bus levels based upon the net result of each port's output, and for communicating changes in bus
|
||||||
*/
|
levels to every port.
|
||||||
void AttachPortAndBus(std::shared_ptr<Port> port, std::shared_ptr<Bus> bus);
|
*/
|
||||||
|
class Bus {
|
||||||
|
public:
|
||||||
|
Bus() : line_levels_{
|
||||||
|
LineLevel::High,
|
||||||
|
LineLevel::High,
|
||||||
|
LineLevel::High,
|
||||||
|
LineLevel::High,
|
||||||
|
LineLevel::High
|
||||||
|
} {}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
A serial bus is responsible for retaining a weakly-held collection of attached ports and for deciding the
|
Adds the supplied port to the bus.
|
||||||
current bus levels based upon the net result of each port's output, and for communicating changes in bus
|
*/
|
||||||
levels to every port.
|
void add_port(Port &port);
|
||||||
*/
|
|
||||||
class Bus {
|
|
||||||
public:
|
|
||||||
Bus() : line_levels_{High, High, High, High, High} {}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Adds the supplied port to the bus.
|
Communicates to the bus that one of its attached port has changed its output level for the given line.
|
||||||
*/
|
The bus will therefore recalculate bus state and propagate as necessary.
|
||||||
void add_port(std::shared_ptr<Port> port);
|
*/
|
||||||
|
void set_line_output_did_change(Line line);
|
||||||
|
|
||||||
/*!
|
private:
|
||||||
Communicates to the bus that one of its attached port has changed its output level for the given line.
|
LineLevel line_levels_[5];
|
||||||
The bus will therefore recalculate bus state and propagate as necessary.
|
std::vector<Port &> ports_;
|
||||||
*/
|
};
|
||||||
void set_line_output_did_change(Line line);
|
|
||||||
|
|
||||||
private:
|
/*!
|
||||||
LineLevel line_levels_[5];
|
A serial port is an endpoint on a serial bus; this class provides a direct setter for current line outputs and
|
||||||
std::vector<std::weak_ptr<Port>> ports_;
|
expects to be subclassed in order for specific port-housing devices to deal with input.
|
||||||
};
|
*/
|
||||||
|
class Port {
|
||||||
|
public:
|
||||||
|
Port() : line_levels_{
|
||||||
|
LineLevel::High,
|
||||||
|
LineLevel::High,
|
||||||
|
LineLevel::High,
|
||||||
|
LineLevel::High,
|
||||||
|
LineLevel::High
|
||||||
|
} {}
|
||||||
|
virtual ~Port() = default;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
A serial port is an endpoint on a serial bus; this class provides a direct setter for current line outputs and
|
Sets the current level of an output line on this serial port.
|
||||||
expects to be subclassed in order for specific port-housing devices to deal with input.
|
*/
|
||||||
*/
|
void set_output(Line line, LineLevel level) {
|
||||||
class Port {
|
if(line_levels_[size_t(line)] != level) {
|
||||||
public:
|
line_levels_[size_t(line)] = level;
|
||||||
Port() : line_levels_{High, High, High, High, High} {}
|
if(serial_bus_) serial_bus_->set_line_output_did_change(line);
|
||||||
virtual ~Port() = default;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sets the current level of an output line on this serial port.
|
|
||||||
*/
|
|
||||||
void set_output(Line line, LineLevel level) {
|
|
||||||
if(line_levels_[line] != level) {
|
|
||||||
line_levels_[line] = level;
|
|
||||||
std::shared_ptr<Bus> bus = serial_bus_.lock();
|
|
||||||
if(bus) bus->set_line_output_did_change(line);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Gets the previously set level of an output line.
|
Gets the previously set level of an output line.
|
||||||
*/
|
*/
|
||||||
LineLevel get_output(Line line) {
|
LineLevel get_output(Line line) {
|
||||||
return line_levels_[line];
|
return line_levels_[size_t(line)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Called by the bus to signal a change in any input line level. Subclasses should implement this.
|
Called by the bus to signal a change in any input line level. Subclasses should implement this.
|
||||||
*/
|
*/
|
||||||
virtual void set_input(Line line, LineLevel value) = 0;
|
virtual void set_input(Line line, LineLevel value) = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Sets the supplied serial bus as that to which line levels will be communicated.
|
Sets the supplied serial bus as that to which line levels will be communicated.
|
||||||
*/
|
*/
|
||||||
inline void set_serial_bus(std::shared_ptr<Bus> serial_bus) {
|
inline void set_bus(Bus &serial_bus) {
|
||||||
serial_bus_ = serial_bus;
|
serial_bus_ = &serial_bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::weak_ptr<Bus> serial_bus_;
|
Bus *serial_bus_ = nullptr;
|
||||||
LineLevel line_levels_[5];
|
LineLevel line_levels_[5];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
A debugging port, which makes some attempt to log bus activity. Incomplete. TODO: complete.
|
A debugging port, which makes some attempt to log bus activity. Incomplete. TODO: complete.
|
||||||
*/
|
*/
|
||||||
class DebugPort: public Port {
|
class DebugPort: public Port {
|
||||||
public:
|
public:
|
||||||
void set_input(Line line, LineLevel value);
|
void set_input(Line line, LineLevel value);
|
||||||
|
|
||||||
DebugPort() : incoming_count_(0) {}
|
DebugPort() : incoming_count_(0) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t incoming_byte_;
|
uint8_t incoming_byte_;
|
||||||
int incoming_count_;
|
int incoming_count_;
|
||||||
LineLevel input_levels_[5];
|
LineLevel input_levels_[5];
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user