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
|
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/******************************************************************************
Psion ASIC4
ASIC4 is a serial protocol slave IC for addressing memory and general
memory-mapped peripherals. It is used in SSDs to convert SIBO serial protocol
signals into addresses within the memory range of the memory pack. ASIC4 was
designed to be a cut-down version of ASIC5 which was the original SIBO serial
protocol slave chip.
A27 A26 A25 A24 D7 D6 D5 D4 D3 D2 D1 D0
M Peripheral Id Memory Type No. devices Memory Size
1 0 0 0 No peripheral 0 0 0 RAM 0 0 1 device 0 0 0 No memory
0 0 1 Turbo RS232 (16550) 0 0 1 Type 1 Flash 0 1 2 devices 0 0 1 32K
0 1 0 3Fax 0 1 0 Type 2 Flash 1 0 3 devices 0 1 0 64K
1 1 1 Extended info in ROM 1 1 0 ROM 1 1 4 devices 0 1 1 128K
1 0 0 256K
1 0 1 512K
1 1 0 1M
******************************************************************************/
#include "emu.h"
#include "psion_asic4.h"
#define VERBOSE 0
//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
DEFINE_DEVICE_TYPE(PSION_ASIC4, psion_asic4_device, "psion_asic4", "Psion ASIC4")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
psion_asic4_device::psion_asic4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PSION_ASIC4, tag, owner, clock)
, device_memory_interface(mconfig, *this)
, m_space_config("program", ENDIANNESS_LITTLE, 8, 28)
{
}
device_memory_interface::space_config_vector psion_asic4_device::memory_space_config() const
{
return space_config_vector{ std::make_pair(0, &m_space_config) };
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void psion_asic4_device::device_start()
{
m_space = &space(0);
save_item(NAME(m_addr_latch));
save_item(NAME(m_addr_writes));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void psion_asic4_device::device_reset()
{
m_addr_latch = 0x00;
m_addr_writes = 0;
}
//**************************************************************************
// READ/WRITE HANDLERS
//**************************************************************************
void psion_asic4_device::data_w(uint16_t data)
{
switch (data & 0x300)
{
case NULL_FRAME:
device_reset();
break;
case CONTROL_FRAME:
m_sibo_control = data & 0xff;
// reset address register to LSB
m_addr_writes = 0;
break;
case DATA_FRAME:
data &= 0xff;
switch (m_sibo_control & 0x0f)
{
case 0x00: // Data register
LOG("%s data_w: Data register %02x\n", machine().describe_context(), data);
m_space->write_byte(m_addr_latch, data);
break;
case 0x01: // Device Size register
LOG("%s data_w: Device Size register %02x\n", machine().describe_context(), data);
break;
case 0x02: // Address Increment register
LOG("%s data_w: Address Increment register %02x\n", machine().describe_context(), data);
m_addr_latch = (m_addr_latch & 0xffffff0) | ((m_addr_latch + 1) & 0x0f);
break;
case 0x03: // Address register
LOG("%s data_w: Address register %02x\n", machine().describe_context(), data);
if (m_addr_writes == 0)
m_addr_latch = 0x00;
m_addr_latch |= data << (m_addr_writes << 3);
m_addr_writes = (m_addr_writes + 1) & 3;
break;
case 0x07: // Control register
LOG("%s data_w: Control register %02x\n", machine().describe_context(), data);
break;
default:
LOG("%s data_w: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data);
break;
}
break;
}
}
uint8_t psion_asic4_device::data_r()
{
uint8_t data = 0x00;
switch (m_sibo_control & 0xc0)
{
case 0x40: // SerialSelect
switch (m_sibo_control & 0x0f)
{
case 0x06: // Asic4Id
data = m_info_byte & 0xff; // A4InfoByte
break;
}
break;
case 0xc0: // SerialRead
switch (m_sibo_control & 0x0f)
{
case 0x00: // Data register
data = m_space->read_byte(m_addr_latch);
LOG("%s data_r: Data register %02x\n", machine().describe_context(), data);
m_addr_latch++;
break;
case 0x01: // Input register
data = (m_info_byte >> 4) & 0xf0;
LOG("%s data_r: Input register %02x\n", machine().describe_context(), data);
break;
default:
LOG("%s data_r: unknown control %02x data %02x\n", machine().describe_context(), m_sibo_control, data);
break;
}
break;
}
return data;
}
|