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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
// license:BSD-3-Clause
// copyright-holders:R. Belmont
/***************************************************************************
icd2053b.cpp - Cypress ICD2053A Programmable Clock Generator
This is a serially programmed PLL clock generator rated for a range
from 391 kHz to 100 MHz at TTL levels or 90 MHz at CMOS levels.
Bits are shifted in LSB first. If 4 1 bits in a row are shifted in,
that's considered to be a command word of the form 0x1exx, where the
low 8 bits set the control register. Setting bit 0 of the command
register to 1 enables a write of the next 22 bits to the program register.
In the event that the program register contains 4 or more 1 bits in a row,
you can escape them by inserting a 0 bit after every group of 3 1 bits.
IC Designs/Cypress calls this "bit-stuffing". The stuffed bit is NOT
inserted into the shift register and the detection of 3 1 bits is reset
so that you can have another 3 1 bits after an escape bit before you
need another escape bit.
To program: 1111 0111 1110 111111
Send: 10111 00111 01110 01110111
The control register is as follows:
Bits 7, 6, and 4 are reserved and unused.
Bit 5 reduces the duty cycle by 0.7 nanoseconds if 1.
Bit 3 controls if pin 7 is OE (output enable) (0) or MUXREF (1).
Bit 2 determines if CLKOUT is the VCO frequency (0) or a passthrough of
the input clock (1).
Bit 1 controls OE (output enable), which tri-states the output clock
if 1 or operates normally if 0.
Bit 0 is the write enable for the program word. Set to "1" to enable
writing a 22-bit program word.
The program word is as follows:
Bits 21-15 are the 7-bit P parameter.
Bit 14 increases the duty cycle by 0.7 nanoseconds if 1. Cypress
recommends always setting it to 1.
Bits 13-11 are the 3-bit MUX parameter. This sets a post-VCO divider
of the form (1 << MUX), so 0 divides by 1 (no divide), 1 divides by
2, 2 divides by 4, and so on.
Bits 10-4 are the 7-bit Q parameter.
Bits 0-3 pre-set the VCO to an appropriate range. 0 is 50 to 80 MHz,
and a value of 8 is 80-150 MHz. Note that these frequencies
are prior to the MUX divider, so a divide by 2 to output
30 MHz would have a VCO frequency of 60 MHz.
The VCO rate fVCO is (Input clock * 2) * ((P+3) / (Q+2)), and the
output clock is (fVCO / (1 << MUX)).
For an input clock of 31.3344 MHz with P = 80, Q = 41, and MUX = 1,
the output is therefore ((31.3344 * 2) * (83 / 43)) / (2) = 30.241339 MHz.
Apple used a Motorola clone/second source labeled XCR2115805 (possibly
also XCR2115808, some photos are inconclusive), which they called
"Clifton", in the Quadra 660AV and Duo Dock.
***************************************************************************/
#include "emu.h"
#include "icd2053b.h"
#define VERBOSE (0)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(ICD2053B, icd2053b_device, "icd2053b", "Cypress Semiconductor ICD2053B Programmable Clock Generator")
icd2053b_device::icd2053b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ICD2053B, tag, owner, clock),
m_clkout_changed_cb(*this),
m_shifter(0),
m_shifter_last3(0),
m_shift_pos(0),
m_pll_control(0),
m_prev_shift_clock(CLEAR_LINE),
m_shifter_expected(22),
m_datalatch(0)
{
}
void icd2053b_device::device_start()
{
save_item(NAME(m_shifter));
save_item(NAME(m_shifter_last3));
save_item(NAME(m_shift_pos));
save_item(NAME(m_pll_control));
save_item(NAME(m_prev_shift_clock));
save_item(NAME(m_shifter_expected));
save_item(NAME(m_datalatch));
}
void icd2053b_device::data_w(int state)
{
m_datalatch = state;
}
void icd2053b_device::clk_w(int state)
{
// rising clock edge?
if (state && !m_prev_shift_clock)
{
LOG("%s: Got bit %d, shifter %08x, bits left %d\n", tag(), m_datalatch, m_shifter, m_shifter_expected);
// were the previous 3 bits 1s? If so this is a command word
if (m_shift_pos >= 3)
{
if (m_shifter_last3 == 7)
{
// each time we see an escape, forget the last 3 bits (example on page 2 of the ICD2053B datasheet)
m_shifter_last3 = 0;
if (m_datalatch)
{
m_shifter_expected = 2;
}
else // escaped bit, skip
{
LOG("%s: 0111 escape sequence!\n", tag());
return;
}
}
}
m_shifter_last3 >>= 1;
m_shifter_last3 |= (m_datalatch << 2);
m_shifter &= ~(1 << m_shift_pos);
m_shifter |= (m_datalatch << m_shift_pos);
m_shift_pos++;
if (m_shifter_expected > 0)
{
m_shifter_expected--;
}
if (m_shifter_expected == 0)
{
if ((m_shifter & 0xff00) == 0x1e00)
{
LOG("%s: Command word is %04x\n", tag(), m_shifter & 0x7fff);
m_pll_control = m_shifter & 0xff;
if (BIT(m_pll_control, 0))
{
m_shifter_expected = 22;
}
else
{
m_shifter_expected = -1;
}
}
else
{
LOG("%s: Program word is %08x\n", tag(), m_shifter);
int P = ((m_shifter >> 15) & 0x7f) + 3;
int Q = ((m_shifter >> 4) & 0x7f) + 2;
double ratio = (double)((double)P / (double)Q);
double pclock = ratio * (double)clock() * 2.0f;
int divider = 1 << ((m_shifter >> 11) & 7);
pclock /= (double)divider;
LOG("%s: Pixel clock is %f Hz from P %d Q %d ratio %f, divider %d (div factor %d)\n", tag(), pclock, P, Q, ratio, divider, (m_shifter >> 11) & 7);
m_clkout_changed_cb((u32)pclock);
m_shifter_expected = -1;
}
m_shift_pos = 0;
m_shifter = 0;
}
}
m_prev_shift_clock = state;
}
|