summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/psion_asic4.cpp
blob: 0ed603eaa74d8e8dbad9b148d72f5c34f93bc9d7 (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
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;
}