summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/thomson/cc90_232.cpp
blob: 7b5a80e47b3812f652cb1a5bf21071a44dc63be0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// license:BSD-3-Clause
// copyright-holders:Antoine Mine

#include "emu.h"
#include "cc90_232.h"

#include "bus/centronics/ctronics.h"
#include "machine/input_merger.h"
#include "machine/output_latch.h"

#define VERBOSE 0
#include "logmacro.h"

/* ------------ CC 90-232 I/O extension ------------ */

/* Features:
   - 6821 PIA
   - serial RS232: bit-banging?
   - parallel CENTRONICS: a printer (-prin) is emulated
   - usable on TO7(/70), MO5(E), MO5NR
     (TO8, TO9, MO6 normally use their built-in parallel printer interfaces instead)

   Note: it seems impossible to connect both a serial & a parallel device
   because the Data Transmit Ready bit is shared in an incompatible way!
*/

// device type definition
DEFINE_DEVICE_TYPE(CC90_232, cc90_232_device, "cc90_232", "Thomson CC 90-232 Communication Interface")

//-------------------------------------------------
//  cc90_232_device - constructor
//-------------------------------------------------

cc90_232_device::cc90_232_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, CC90_232, tag, owner, clock),
	thomson_extension_interface(mconfig, *this),
	m_pia_io(*this, "pia"),
	m_rs232(*this, "rs232"),
	m_last_low(0)
{
}

void cc90_232_device::rom_map(address_map &map)
{
}

void cc90_232_device::io_map(address_map &map)
{
	map(0x20, 0x23).rw(m_pia_io, FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
}

void cc90_232_device::device_add_mconfig(machine_config &config)
{
	PIA6821(config, m_pia_io);
	m_pia_io->readpa_handler().set(FUNC(cc90_232_device::porta_in));
	m_pia_io->writepa_handler().set(FUNC(cc90_232_device::porta_out));
	m_pia_io->writepb_handler().set("cent_data_out", FUNC(output_latch_device::write));
	m_pia_io->cb2_handler().set("centronics", FUNC(centronics_device::write_strobe));
	m_pia_io->irqa_handler().set("piairq", FUNC(input_merger_device::in_w<0>));
	m_pia_io->irqb_handler().set("piairq", FUNC(input_merger_device::in_w<1>));

	INPUT_MERGER_ANY_HIGH(config, "piairq").output_handler().set(FUNC(cc90_232_device::firq_w));

	RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
	m_rs232->rxd_handler().set(FUNC(cc90_232_device::write_rxd));
	m_rs232->cts_handler().set(FUNC(cc90_232_device::write_cts));
	m_rs232->dsr_handler().set(FUNC(cc90_232_device::write_dsr));

	centronics_device &centronics(CENTRONICS(config, "centronics", centronics_devices, "printer"));
	centronics.ack_handler().set(m_pia_io, FUNC(pia6821_device::cb1_w));
	centronics.busy_handler().set(FUNC(cc90_232_device::write_centronics_busy));

	output_latch_device &cent_data_out(OUTPUT_LATCH(config, "cent_data_out"));
	centronics.set_output_latch(cent_data_out);
}


void cc90_232_device::device_start()
{
	m_rs232->write_dtr(0);
}

void cc90_232_device::porta_out(uint8_t data)
{
	int txd = (data >> 0) & 1;
	int rts = (data >> 1) & 1;

	LOG( "%s %f porta_out: txd=%i, rts=%i\n",  machine().describe_context(), machine().time().as_double(), txd, rts );

	m_rs232->write_txd(txd);
	m_rs232->write_rts(rts);
}



void cc90_232_device::write_rxd(int state)
{
	m_rxd = state;
}

void cc90_232_device::write_dsr(int state)
{
	if (!state) m_last_low = 0;

	m_dsr = state;
}

void cc90_232_device::write_cts(int state)
{
	m_pia_io->ca1_w(state);
	m_cts = state;
}

void cc90_232_device::write_centronics_busy(int state)
{
	if (!state) m_last_low = 1;

	m_centronics_busy = state;
}


uint8_t cc90_232_device::porta_in()
{
	LOG( "%s %f porta_in: select=%i cts=%i, dsr=%i, rd=%i\n", machine().describe_context(), machine().time().as_double(), m_centronics_busy, m_cts, m_dsr, m_rxd );

	/// HACK: without high impedance we can't tell whether a device is driving a line high or if it's being pulled up.
	/// so assume the last device to drive it low is active.
	int dsr;
	if (m_last_low == 0)
		dsr = m_dsr;
	else
		dsr = !m_centronics_busy;

	return (0x1f /* not required when converted to write_pa */) | (m_cts << 5) | (dsr << 6) | (m_rxd << 7);
}