mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-11 05:29:43 +00:00
Improve ESCC stub to bypass LocalTalk.
This commit is contained in:
parent
205b5a4956
commit
4de10898ea
@ -46,22 +46,37 @@ void EsccController::reset()
|
||||
|
||||
uint8_t EsccController::read(uint8_t reg_offset)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
switch(reg_offset) {
|
||||
case EsccReg::Port_B_Cmd:
|
||||
LOG_F(9, "ESCC: reading Port B register RR%d", this->reg_ptr);
|
||||
if (this->reg_ptr == 2) {
|
||||
// TODO: implement interrupt vector modifications
|
||||
result = this->int_vec;
|
||||
} else {
|
||||
result = this->ch_b->read_reg(this->reg_ptr);
|
||||
}
|
||||
this->reg_ptr = 0;
|
||||
return this->ch_b->read_reg(reg_offset);
|
||||
break;
|
||||
case EsccReg::Port_A_Cmd:
|
||||
LOG_F(9, "ESCC: reading Port A register RR%d", this->reg_ptr);
|
||||
if (this->reg_ptr == 2) {
|
||||
return this->int_vec;
|
||||
} else {
|
||||
return this->ch_a->read_reg(this->reg_ptr);
|
||||
}
|
||||
this->reg_ptr = 0;
|
||||
return this->ch_a->read_reg(reg_offset);
|
||||
break;
|
||||
case EsccReg::Port_B_Data:
|
||||
return this->ch_b->receive_byte();
|
||||
case EsccReg::Port_A_Data:
|
||||
return this->ch_a->receive_byte();
|
||||
default:
|
||||
LOG_F(INFO, "ESCC: reading register %d", reg_offset);
|
||||
LOG_F(9, "ESCC: reading from unimplemented register %d", reg_offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
void EsccController::write(uint8_t reg_offset, uint8_t value)
|
||||
@ -73,8 +88,14 @@ void EsccController::write(uint8_t reg_offset, uint8_t value)
|
||||
case EsccReg::Port_A_Cmd:
|
||||
this->write_internal(this->ch_a.get(), value);
|
||||
break;
|
||||
case EsccReg::Port_B_Data:
|
||||
this->ch_b->send_byte(value);
|
||||
break;
|
||||
case EsccReg::Port_A_Data:
|
||||
this->ch_a->send_byte(value);
|
||||
break;
|
||||
default:
|
||||
LOG_F(INFO, "ESCC: writing 0x%X to register %d", value, reg_offset);
|
||||
LOG_F(9, "ESCC: writing 0x%X to unimplemented register %d", value, reg_offset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,6 +152,15 @@ void EsccChannel::reset(bool hw_reset)
|
||||
this->read_regs[3] = 0x00;
|
||||
this->read_regs[10] = 0x00;
|
||||
|
||||
// initialize DPLL
|
||||
this->dpll_active = 0;
|
||||
this->dpll_mode = DpllMode::NRZI;
|
||||
this->dpll_clock_src = 0;
|
||||
|
||||
// initialize Baud Rate Generator (BRG)
|
||||
this->brg_active = 0;
|
||||
this->brg_clock_src = 0;
|
||||
|
||||
if (hw_reset) {
|
||||
this->write_regs[10] = 0;
|
||||
this->write_regs[11] = 8;
|
||||
@ -145,14 +175,79 @@ void EsccChannel::reset(bool hw_reset)
|
||||
|
||||
void EsccChannel::write_reg(int reg_num, uint8_t value)
|
||||
{
|
||||
switch (reg_num) {
|
||||
case 3:
|
||||
if (value & 0x11) {
|
||||
if ((this->write_regs[3] ^ value) & 0x10) {
|
||||
this->write_regs[3] |= 0x10;
|
||||
this->read_regs[0] |= 0x10; // set SYNC_HUNT flag
|
||||
LOG_F(9, "ESCC: Hunt mode entered.");
|
||||
}
|
||||
if (value & 1) {
|
||||
this->write_regs[3] |= 0x1;
|
||||
LOG_F(9, "ESCC: receiver enabled.");
|
||||
}
|
||||
}
|
||||
this->write_regs[3] = (this->write_regs[3] & 0x11) | (value & 0xEE);
|
||||
return;
|
||||
case 7:
|
||||
if (this->write_regs[15] & 1) {
|
||||
this->wr7_enh = value;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
switch (value >> 5) {
|
||||
case DPLL_ENTER_SRC_MODE:
|
||||
this->dpll_active = 1;
|
||||
this->read_regs[10] &= 0x3F;
|
||||
break;
|
||||
case DPLL_DISABLE:
|
||||
this->dpll_active = 0;
|
||||
// fallthrough
|
||||
case DPLL_RST_MISSING_CLK:
|
||||
this->read_regs[10] &= 0x3F;
|
||||
break;
|
||||
case DPLL_SET_SRC_BGR:
|
||||
this->dpll_clock_src = 0;
|
||||
break;
|
||||
case DPLL_SET_SRC_RTXC:
|
||||
this->dpll_clock_src = 1;
|
||||
break;
|
||||
case DPLL_SET_FM_MODE:
|
||||
this->dpll_mode = DpllMode::FM;
|
||||
break;
|
||||
case DPLL_SET_NRZI_MODE:
|
||||
this->dpll_mode = DpllMode::NRZI;
|
||||
break;
|
||||
default:
|
||||
LOG_F(WARNING, "ESCC: unimplemented DPLL command %d", value >> 5);
|
||||
}
|
||||
if (value & 0x1C) { // Local Loopback, Auto Echo DTR/REQ bits set
|
||||
LOG_F(WARNING, "ESCC: unexpected value in WR14 = 0x%X", value);
|
||||
}
|
||||
if (this->brg_active ^ (value & 1)) {
|
||||
this->brg_active = value & 1;
|
||||
LOG_F(9, "ESCC: BRG %s", this->brg_active ? "enabled" : "disabled");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this->write_regs[reg_num] = value;
|
||||
LOG_F(9, "ESCC: writing 0x%X to Channel %s WR%d", value, this->name.c_str(),
|
||||
reg_num);
|
||||
|
||||
|
||||
}
|
||||
|
||||
uint8_t EsccChannel::read_reg(int reg_num)
|
||||
{
|
||||
return 0;
|
||||
return this->read_regs[reg_num];
|
||||
}
|
||||
|
||||
void EsccChannel::send_byte(uint8_t value)
|
||||
{
|
||||
// Put one byte into the Data FIFO
|
||||
}
|
||||
|
||||
uint8_t EsccChannel::receive_byte()
|
||||
{
|
||||
// Remove one byte from the Receive FIFO
|
||||
return 0xFF;
|
||||
}
|
||||
|
@ -28,17 +28,21 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
/** ESCC register addresses */
|
||||
/** ESCC register positions */
|
||||
/* Please note that the registers below are provided
|
||||
by Apple I/O controllers for accessing ESCC in a
|
||||
more convenient way. Actual physical addresses
|
||||
are controller dependent. */
|
||||
enum EsccReg : uint8_t {
|
||||
Port_B_Cmd = 0,
|
||||
Port_B_Data = 1,
|
||||
Port_A_Cmd = 2,
|
||||
Port_A_Data = 3,
|
||||
Enh_Reg_B = 4,
|
||||
Enh_Reg_A = 5,
|
||||
Port_A_Cmd = 1,
|
||||
Port_B_Data = 2, // direct access to WR8/RR8
|
||||
Port_A_Data = 3, // direct access to WR8/RR8
|
||||
Enh_Reg_B = 4, // undocumented Apple extension
|
||||
Enh_Reg_A = 5, // undocumented Apple extension
|
||||
};
|
||||
|
||||
/** LocalTalk LTPC registers */
|
||||
/** LocalTalk LTPC registers provided by a MacIO controller. */
|
||||
enum LocalTalkReg : uint8_t {
|
||||
Rec_Count = 8,
|
||||
Start_A = 9,
|
||||
@ -57,6 +61,22 @@ enum {
|
||||
RESET_CH_B = 0x40
|
||||
};
|
||||
|
||||
/** DPLL commands in WR14. */
|
||||
enum {
|
||||
DPLL_ENTER_SRC_MODE = 1,
|
||||
DPLL_RST_MISSING_CLK = 2,
|
||||
DPLL_DISABLE = 3,
|
||||
DPLL_SET_SRC_BGR = 4,
|
||||
DPLL_SET_SRC_RTXC = 5,
|
||||
DPLL_SET_FM_MODE = 6,
|
||||
DPLL_SET_NRZI_MODE = 7
|
||||
};
|
||||
|
||||
enum DpllMode : uint8_t {
|
||||
NRZI = 0,
|
||||
FM = 1
|
||||
};
|
||||
|
||||
/** ESCC Channel class. */
|
||||
class EsccChannel {
|
||||
public:
|
||||
@ -66,11 +86,19 @@ public:
|
||||
void reset(bool hw_reset);
|
||||
uint8_t read_reg(int reg_num);
|
||||
void write_reg(int reg_num, uint8_t value);
|
||||
void send_byte(uint8_t value);
|
||||
uint8_t receive_byte();
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
uint8_t read_regs[16];
|
||||
uint8_t write_regs[16];
|
||||
uint8_t wr7_enh;
|
||||
uint8_t dpll_active;
|
||||
uint8_t dpll_mode;
|
||||
uint8_t dpll_clock_src;
|
||||
uint8_t brg_active;
|
||||
uint8_t brg_clock_src;
|
||||
};
|
||||
|
||||
/** ESCC Controller class. */
|
||||
@ -91,6 +119,7 @@ private:
|
||||
std::unique_ptr<EsccChannel> ch_b;
|
||||
|
||||
int reg_ptr; // register pointer for reading/writing (same for both channels)
|
||||
|
||||
uint8_t master_int_cntrl;
|
||||
uint8_t int_vec;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user