2017-08-01 20:15:19 +00:00
|
|
|
//
|
|
|
|
// i8255.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 01/08/2017.
|
|
|
|
// Copyright © 2017 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef i8255_hpp
|
|
|
|
#define i8255_hpp
|
|
|
|
|
|
|
|
namespace Intel {
|
|
|
|
namespace i8255 {
|
|
|
|
|
|
|
|
class PortHandler {
|
2017-08-01 20:34:13 +00:00
|
|
|
public:
|
|
|
|
void set_value(int port, uint8_t value) {}
|
|
|
|
uint8_t get_value(int port) { return 0xff; }
|
2017-08-01 20:15:19 +00:00
|
|
|
};
|
|
|
|
|
2017-08-01 20:34:13 +00:00
|
|
|
// TODO: most of the implementation below. Right now it just blindly passes data in all directions,
|
|
|
|
// ignoring operation mode. But at least it establishes proper ownership and hand-off of decision making.
|
2017-08-01 20:15:19 +00:00
|
|
|
template <class T> class i8255 {
|
|
|
|
public:
|
2017-08-01 21:01:20 +00:00
|
|
|
i8255(T &port_handler) : control_(0), outputs_{0, 0, 0}, port_handler_(port_handler) {}
|
2017-08-01 20:34:13 +00:00
|
|
|
|
2017-08-01 20:15:19 +00:00
|
|
|
void set_register(int address, uint8_t value) {
|
2017-08-01 20:34:13 +00:00
|
|
|
switch(address & 3) {
|
|
|
|
case 0: outputs_[0] = value; port_handler_.set_value(0, value); break;
|
|
|
|
case 1: outputs_[1] = value; port_handler_.set_value(1, value); break;
|
|
|
|
case 2: outputs_[2] = value; port_handler_.set_value(2, value); break;
|
|
|
|
case 3:
|
|
|
|
if(value & 0x80) {
|
|
|
|
control_ = value;
|
|
|
|
} else {
|
|
|
|
if(value & 1) {
|
|
|
|
outputs_[2] |= 1 << ((value >> 1)&7);
|
|
|
|
} else {
|
|
|
|
outputs_[2] &= ~(1 << ((value >> 1)&7));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
update_outputs();
|
|
|
|
break;
|
2017-08-01 20:15:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t get_register(int address) {
|
2017-08-01 20:34:13 +00:00
|
|
|
switch(address & 3) {
|
2017-08-07 23:36:55 +00:00
|
|
|
case 0: return (control_ & 0x10) ? port_handler_.get_value(0) : outputs_[0];
|
|
|
|
case 1: return (control_ & 0x02) ? port_handler_.get_value(1) : outputs_[1];
|
|
|
|
case 2: {
|
|
|
|
if(!(control_ & 0x09)) return outputs_[2];
|
|
|
|
uint8_t input = port_handler_.get_value(2);
|
|
|
|
return ((control_ & 0x01) ? (input & 0x0f) : (outputs_[2] & 0x0f)) | ((control_ & 0x08) ? (input & 0xf0) : (outputs_[2] & 0xf0));
|
|
|
|
}
|
2017-08-01 20:34:13 +00:00
|
|
|
case 3: return control_;
|
2017-08-01 20:15:19 +00:00
|
|
|
}
|
|
|
|
return 0xff;
|
|
|
|
}
|
2017-08-01 20:34:13 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
void update_outputs() {
|
|
|
|
port_handler_.set_value(0, outputs_[0]);
|
|
|
|
port_handler_.set_value(1, outputs_[1]);
|
|
|
|
port_handler_.set_value(2, outputs_[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t control_;
|
|
|
|
uint8_t outputs_[3];
|
2017-08-01 21:01:20 +00:00
|
|
|
T &port_handler_;
|
2017-08-01 20:15:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* i8255_hpp */
|