Skip to content

Commit 2f53d07

Browse files
committed
sinclair/tsconf.cpp: Added FPGA 100K variant; implemented Copper for it.
1 parent bd7d398 commit 2f53d07

File tree

8 files changed

+356
-14
lines changed

8 files changed

+356
-14
lines changed

src/mame/mame.lst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42920,6 +42920,7 @@ uk2086
4292042920

4292142921
@source:sinclair/tsconf.cpp
4292242922
tsconf
42923+
tsconf2
4292342924

4292442925
@source:sinclair/zx.cpp
4292542926
lambda

src/mame/sinclair/tsconf.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ Features (TS-Configuration):
2121
2222
- DRAM-to-Device, Device-to-DRAM and DRAM-to-DRAM DMA Controller
2323
24+
Revisions:
25+
tsconf: Initial release for ZX Evolution baser on Altera's FPGA 50K
26+
tsconf2: Requires 100K FPGA and has extra feature set like 'Copper'
27+
2428
Refs:
2529
TsConf: https://github.com/tslabs/zx-evo/blob/master/pentevo/docs/TSconf/tsconf_en.md
2630
https://github.com/tslabs/zx-evo/raw/master/pentevo/docs/TSconf/TSconf.xls
@@ -332,6 +336,18 @@ void tsconf_state::tsconf(machine_config &config)
332336
SOFTWARE_LIST(config, "betadisc_list_tsconf").set_original("tsconf_betadisc_flop");
333337
}
334338

339+
340+
void tsconf_state::tsconf2(machine_config &config)
341+
{
342+
tsconf(config);
343+
TSCONF_COPPER(config, m_copper, 28_MHz_XTAL);
344+
m_copper->out_wreg_cb().set(FUNC(tsconf_state::tsconf_port_xxaf_w));
345+
m_copper->set_in_until_pos_cb(FUNC(tsconf_state::cooper_until_pos_r));
346+
347+
m_dma->on_ready_callback().append(m_copper, FUNC(tsconf_copper_device::dma_ready_w));
348+
}
349+
350+
335351
ROM_START(tsconf)
336352
ROM_REGION(0x080000, "maincpu", ROMREGION_ERASEFF) // ROM: 32 * 16KB
337353
ROM_DEFAULT_BIOS("v2407")
@@ -346,5 +362,18 @@ ROM_START(tsconf)
346362
ROM_LOAD( "cram-init.bin", 0, 0x200, CRC(8b96ffb7) SHA1(4dbd22f4312251e922911a01526cbfba77a122fc))
347363
ROM_END
348364

349-
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
350-
COMP( 2011, tsconf, spec128, 0, tsconf, tsconf, tsconf_state, empty_init, "NedoPC, TS-Labs", "ZX Evolution: TS-Configuration", MACHINE_SUPPORTS_SAVE)
365+
ROM_START(tsconf2)
366+
ROM_REGION(0x080000, "maincpu", ROMREGION_ERASEFF) // ROM: 32 * 16KB
367+
ROM_DEFAULT_BIOS("v2407")
368+
369+
ROM_SYSTEM_BIOS(0, "v2407", "Update 24.07.28")
370+
ROMX_LOAD("ts-bios.240728.rom", 0, 0x10000, CRC(19f8ad7b) SHA1(9cee82d4a6212686358a50b0fd5a2981b3323ab6), ROM_BIOS(0))
371+
372+
ROM_REGION(0x200, "cram_init", ROMREGION_ERASEFF)
373+
ROM_LOAD( "cram-init.bin", 0, 0x200, CRC(8b96ffb7) SHA1(4dbd22f4312251e922911a01526cbfba77a122fc))
374+
ROM_END
375+
376+
377+
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
378+
COMP( 2011, tsconf, spec128, 0, tsconf, tsconf, tsconf_state, empty_init, "NedoPC, TS-Labs", "ZX Evolution: TS-Configuration", MACHINE_SUPPORTS_SAVE)
379+
COMP( 2024, tsconf2, spec128, 0, tsconf2, tsconf, tsconf_state, empty_init, "TS-Labs", "EvoMAX3: TS-Configuration 2", MACHINE_SUPPORTS_SAVE)

src/mame/sinclair/tsconf.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
#include "spec128.h"
1414

1515
#include "glukrs.h"
16+
#include "tsconf_copper.h"
17+
#include "tsconf_dma.h"
1618
#include "tsconf_rs232.h"
17-
#include "tsconfdma.h"
1819

1920
#include "beta_m.h"
2021
#include "machine/pckeybrd.h"
@@ -43,10 +44,12 @@ class tsconf_state : public spectrum_128_state
4344
, m_cram(*this, "cram")
4445
, m_sfile(*this, "sfile")
4546
, m_dac(*this, "dac")
47+
, m_copper(*this, "copper")
4648
{
4749
}
4850

4951
void tsconf(machine_config &config);
52+
void tsconf2(machine_config &config);
5053

5154
static constexpr u16 with_hblank(u16 pixclocks) { return 88 + pixclocks; }
5255
static constexpr u16 with_vblank(u16 pixclocks) { return 32 + pixclocks; }
@@ -100,6 +103,7 @@ class tsconf_state : public spectrum_128_state
100103
PAGE2 = 0x12,
101104
PAGE3 = 0x13,
102105

106+
COPPER = 0x14,
103107
FMAPS = 0x15,
104108
T_MAP_PAGE = 0x16,
105109
T0_G_PAGE = 0x17,
@@ -173,6 +177,7 @@ class tsconf_state : public spectrum_128_state
173177
void draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
174178
void tsconf_update_video_mode();
175179
void copy_tiles_to_raw(const u8 *tiles_src, u8 *raw_target);
180+
attotime cooper_until_pos_r(u16 pos);
176181

177182
u8 tsconf_port_xx1f_r(offs_t offset);
178183
void tsconf_port_7ffd_w(u8 data);
@@ -239,6 +244,7 @@ class tsconf_state : public spectrum_128_state
239244
std::vector<sprite_data> m_sprites_cache;
240245

241246
required_device<dac_byte_interface> m_dac;
247+
optional_device<tsconf_copper_device> m_copper;
242248
};
243249

244250
/*----------- defined in drivers/tsconf.c -----------*/

src/mame/sinclair/tsconf_copper.cpp

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
// license:BSD-3-Clause
2+
// copyright-holders:Andrei I. Holub
3+
/**********************************************************************
4+
TS-Configuration Copper
5+
**********************************************************************/
6+
7+
#include "emu.h"
8+
#include "tsconf_copper.h"
9+
10+
11+
#define LOG_CTRL (1U << 1)
12+
#define LOG_DATA (1U << 2)
13+
14+
//#define VERBOSE ( LOG_GENERAL /*| LOG_CTRL | LOG_DATA*/ )
15+
#include "logmacro.h"
16+
17+
#define LOGCTRL(...) LOGMASKED(LOG_CTRL, __VA_ARGS__)
18+
#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__)
19+
20+
21+
// device type definition
22+
DEFINE_DEVICE_TYPE(TSCONF_COPPER, tsconf_copper_device, "tsconf_copper", "TS-Configuration Copper")
23+
24+
25+
tsconf_copper_device::tsconf_copper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
26+
: device_t(mconfig, TSCONF_COPPER, tag, owner, clock)
27+
, m_timer(nullptr)
28+
, m_cl_data(*this, "cl_data", 0x100, ENDIANNESS_LITTLE)
29+
, m_out_wreg_cb(*this)
30+
, m_in_dma_ready_cb(*this, 0)
31+
, m_in_until_pos_cb(*this)
32+
{
33+
}
34+
35+
void tsconf_copper_device::copper_en_w(u8 data)
36+
{
37+
m_en = data != 0xff;
38+
m_pc = data;
39+
40+
if (m_en)
41+
{
42+
LOGCTRL("START\n");
43+
m_timer->adjust(attotime::zero);
44+
}
45+
else
46+
{
47+
LOGCTRL("STOP\n");
48+
m_timer->reset();
49+
}
50+
}
51+
52+
void tsconf_copper_device::cl_data_w(u16 addr, u8 data)
53+
{
54+
addr &= 0x1ff;
55+
LOGDATA("data(W) %02x %04x\n", addr, data);
56+
m_cl_data[addr >> 1] = (addr & 1)
57+
? (m_cl_data[addr >> 1] & 0x00ff) | (data << 8)
58+
: (m_cl_data[addr >> 1] & 0xff00) | data;
59+
}
60+
61+
void tsconf_copper_device::dma_ready_w(int status)
62+
{
63+
if(m_en && (status & 1) && (m_cl_data[m_pc] & 0xff0f) == 0b1111'0100'0000'0001)
64+
{
65+
++m_pc;
66+
m_timer->adjust(attotime::from_hz(clock()), 0);
67+
}
68+
}
69+
70+
TIMER_CALLBACK_MEMBER(tsconf_copper_device::timer_callback)
71+
{
72+
const u16 data = m_cl_data[m_pc];
73+
if (BIT(data, 12, 4) == 0b1111) // all instructions except WREG
74+
{
75+
switch (BIT(data, 8, 4))
76+
{
77+
case 0b0110: //SETA
78+
m_a = data & 0xff;
79+
++m_pc;
80+
break;
81+
82+
case 0b1000: //SETB
83+
case 0b1001:
84+
m_b = data & 0x1ff;
85+
++m_pc;
86+
break;
87+
88+
case 0b0100: // WAIT
89+
{
90+
const u8 event = data & 0x0f;
91+
if (event == param)
92+
++m_pc;
93+
else
94+
{
95+
switch (event)
96+
{
97+
case 1: // DMA
98+
m_timer->reset();
99+
return;
100+
break;
101+
case 2: // frame
102+
m_timer->adjust(m_in_until_pos_cb(0b00 << 14), 2);
103+
return;
104+
break;
105+
case 3: // line start
106+
m_timer->adjust(m_in_until_pos_cb(0b11 << 14), 3);
107+
return;
108+
break;
109+
default:
110+
++m_pc;
111+
break;
112+
113+
}
114+
}
115+
}
116+
break;
117+
118+
case 0b0111: // WAITX
119+
if (param == 0b1111'0111)
120+
++m_pc;
121+
else
122+
{
123+
const u8 x = data & 0xff;
124+
if (x < 224)
125+
m_timer->adjust(m_in_until_pos_cb(0x8000 | x), 0b1111'0111);
126+
else
127+
m_timer->reset();
128+
return;
129+
}
130+
break;
131+
132+
case 0b1010: // WAITY
133+
case 0b1011:
134+
if (param == 0b1111'1010)
135+
++m_pc;
136+
else
137+
{
138+
const u16 y = data & 0x1ff;
139+
if (y < 320)
140+
m_timer->adjust(m_in_until_pos_cb(0x4000 | y), 0b1111'1010);
141+
else
142+
m_timer->reset();
143+
return;
144+
}
145+
break;
146+
147+
case 0b1100: // DJNZA
148+
--m_a;
149+
m_pc = m_a ? data & 0xff : (m_pc + 1);
150+
break;
151+
152+
case 0b1101: // DJNZB
153+
--m_b;
154+
m_pc = m_b ? data & 0xff : (m_pc + 1);
155+
break;
156+
157+
case 0b1110: // CALL
158+
m_ret_pc = m_pc + 1;
159+
m_pc = data & 0xff;
160+
break;
161+
162+
case 0b1111: // JUMP
163+
{
164+
const u8 to = data & 0xff;
165+
if (to == m_pc) // HALT
166+
{
167+
m_en = false;
168+
m_timer->reset();
169+
return;
170+
}
171+
172+
m_pc = (to == 0xff) ? m_ret_pc : to;
173+
}
174+
break;
175+
176+
case 0b0101: // SIGNAL
177+
++m_pc; // TODO signal logic
178+
break;
179+
180+
default: // reserved instructions
181+
++m_pc;
182+
break;
183+
}
184+
}
185+
else
186+
{
187+
m_out_wreg_cb((data & 0xff00) | 0xaf, data & 0x00ff);
188+
++m_pc;
189+
}
190+
191+
m_timer->adjust(attotime::from_hz(clock()), 0);
192+
}
193+
194+
195+
void tsconf_copper_device::device_start()
196+
{
197+
m_timer = timer_alloc(FUNC(tsconf_copper_device::timer_callback), this);
198+
199+
m_in_until_pos_cb.resolve_safe(attotime::zero);
200+
201+
save_item(NAME(m_en));
202+
save_item(NAME(m_pc));
203+
save_item(NAME(m_ret_pc));
204+
save_item(NAME(m_a));
205+
save_item(NAME(m_b));
206+
}
207+
208+
void tsconf_copper_device::device_reset()
209+
{
210+
m_timer->reset();
211+
212+
m_en = false;
213+
m_pc = 0;
214+
m_ret_pc = 0;
215+
m_a = 0;
216+
m_b = 0;
217+
}

src/mame/sinclair/tsconf_copper.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// license:BSD-3-Clause
2+
// copyright-holders:Andrei I. Holub
3+
#ifndef MAME_SINCLAIR_TSCONF_COPPER_H
4+
#define MAME_SINCLAIR_TSCONF_COPPER_H
5+
6+
#pragma once
7+
8+
class tsconf_copper_device : public device_t
9+
{
10+
11+
public:
12+
tsconf_copper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
13+
14+
auto out_wreg_cb() { return m_out_wreg_cb.bind(); }
15+
template <typename... T> void set_in_until_pos_cb(T &&... args) { return m_in_until_pos_cb.set(std::forward<T>(args)...); }
16+
17+
void copper_en_w(u8 data);
18+
void cl_data_w(u16 addr, u8 data);
19+
void dma_ready_w(int status);
20+
21+
protected:
22+
virtual void device_start() override ATTR_COLD;
23+
virtual void device_reset() override ATTR_COLD;
24+
25+
TIMER_CALLBACK_MEMBER(timer_callback);
26+
27+
emu_timer *m_timer;
28+
29+
private:
30+
memory_share_creator<u16> m_cl_data;
31+
32+
devcb_write8 m_out_wreg_cb;
33+
devcb_read_line m_in_dma_ready_cb;
34+
device_delegate<attotime (u16)> m_in_until_pos_cb;
35+
36+
bool m_en;
37+
u8 m_pc;
38+
u8 m_ret_pc;
39+
u8 m_a;
40+
u16 m_b; // u9
41+
};
42+
43+
44+
DECLARE_DEVICE_TYPE(TSCONF_COPPER, tsconf_copper_device)
45+
46+
#endif // MAME_SINCLAIR_TSCONF_COPPER_H

src/mame/sinclair/tsconfdma.cpp renamed to src/mame/sinclair/tsconf_dma.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
**********************************************************************/
1111

1212
#include "emu.h"
13-
#include "tsconfdma.h"
13+
#include "tsconf_dma.h"
1414

15-
#define VERBOSE ( LOG_GENERAL )
15+
//#define VERBOSE ( LOG_GENERAL )
1616
#include "logmacro.h"
1717

1818
tsconfdma_device::tsconfdma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@@ -125,6 +125,7 @@ void tsconfdma_device::start_tx(u8 task, bool s_align, bool d_align, bool align_
125125

126126
m_tx_block_num = 0;
127127
m_tx_block = 0;
128+
// Below is not precise. Clock must match but amount of cycles available depends how much left after screen line rendering based on presented tiles/sprites.
128129
m_dma_clock->adjust(attotime::from_ticks(1, clock() / 6), 0, attotime::from_ticks(1, clock() / 6));
129130
}
130131

0 commit comments

Comments
 (0)