Previous 199869 Revisions Next

r33460 Thursday 20th November, 2014 at 07:19:30 UTC by Thomas Klausner
Fix comment.

Some parsers report:
Entity: line 461: parser error : Double hyphen within comment: <!--
[hash]vsmile_cart.xml
[src/emu/bus]bus.mak
[src/emu/bus/centronics]ctronics.c epson_lx800.c epson_lx800.h epson_lx810l.c epson_lx810l.h
[src/emu/cpu/rsp]rspcp2d.c
[src/emu/machine]e05a30.c e05a30.h i6300esb.c i6300esb.h machine.mak steppers.c steppers.h
[src/mame]mame.mak
[src/mame/drivers]sauro.c
[src/mame/machine]steppers.c* steppers.h*
[src/mess]mess.mak
[src/mess/includes]amstrad.h
[src/targets]mess.lst

trunk/hash/vsmile_cart.xml
r241971r241972
45845880-092360(US)   | Zayzoo My Alien Classmate
45945980-092360-101(US)   | Zayzoo - An Earth Adventure
46046080-092362(NL)   | Zayzoo - Mijn Buitenaardse Vriendje
46180-092363(UK)   | Zayzoo My Alien Classmate   <-- yes, duped#
46180-092363(UK)   | Zayzoo My Alien Classmate   <- yes, duped#
46246280-092363(UK)   | Zayzoo - An Earth Adventure <- saw it, can't find pic again
46346380-092363-103(UK)   | Zayzoo - An Earth Adventure
46446480-092364(GE)   | Zayzoo Lernall
trunk/src/emu/bus/bus.mak
r241971r241972
956956BUSOBJS += $(BUSOBJ)/centronics/dsjoy.o
957957BUSOBJS += $(BUSOBJ)/centronics/epson_ex800.o
958958BUSOBJS += $(BUSOBJ)/centronics/epson_lx800.o
959BUSOBJS += $(BUSOBJ)/centronics/epson_lx810l.o
960959BUSOBJS += $(BUSOBJ)/centronics/printer.o
961960BUSOBJS += $(BUSOBJ)/centronics/digiblst.o
962961$(BUSOBJ)/centronics/epson_ex800.o:    $(EMUOBJ)/layout/ex800.lh
963962$(BUSOBJ)/centronics/epson_lx800.o:    $(EMUOBJ)/layout/lx800.lh
964$(BUSOBJ)/centronics/epson_lx810l.o:   $(EMUOBJ)/layout/lx800.lh
965963endif
966964
967965#-------------------------------------------------
trunk/src/emu/bus/centronics/ctronics.c
r241971r241972
119119#include "comxpl80.h"
120120#include "epson_ex800.h"
121121#include "epson_lx800.h"
122#include "epson_lx810l.h"
123122#include "printer.h"
124123#include "covox.h"
125124
trunk/src/emu/bus/centronics/epson_lx800.c
r241971r241972
1515      input buttons and switches.
1616    - CPU disassembly doesn't seem to indicate conditional JR or RET.
1717
18
19    2014-06-10 Added LX810L, gets caught in a loop almost immediately.
20               IC list:
21               * uPD7810HG (cpu)
22               * E05A30 (gate array)
23               * 2064C (8k RAM)
24               * ER59256 (EEP-ROM - serial nvram)
25               * SLA7020M (step motor driver)
26               * uPC494C (pulse width modulation control)
27               May need to be split off to another driver.
28
29    2014-06-10 Added AP2000, gets caught in the same place as LX810L.
30
1831**********************************************************************/
1932
2033#include "epson_lx800.h"
r241971r241972
2740//**************************************************************************
2841
2942const device_type EPSON_LX800 = &device_creator<epson_lx800_t>;
43const device_type EPSON_LX810L = &device_creator<epson_lx810l_t>;
44const device_type EPSON_AP2000 = &device_creator<epson_ap2000_t>;
3045
3146
3247//-------------------------------------------------
r241971r241972
4055
4156
4257//-------------------------------------------------
58//  ROM( lx810l )
59//-------------------------------------------------
60
61ROM_START( lx810l )
62   ROM_REGION(0x8000, "maincpu", 0)
63   ROM_LOAD("lx810l.ic3c", 0x0000, 0x8000, CRC(a66454e1) SHA1(8e6f2f98abcbd8af6e34b9ba746edf0d18aef843) )
64ROM_END
65
66
67//-------------------------------------------------
68//  ROM( ap2000 )
69//-------------------------------------------------
70
71ROM_START( ap2000 )
72   ROM_REGION(0x8000, "maincpu", 0)
73   ROM_LOAD("ap2k.ic3c", 0x0000, 0x8000, CRC(ee7294b7) SHA1(219ffa6ff661ce95d5772c9fc1967093718f04e9) )
74ROM_END
75
76
77//-------------------------------------------------
4378//  rom_region - device-specific ROM region
4479//-------------------------------------------------
4580
r241971r241972
5085
5186
5287//-------------------------------------------------
88//  rom_region - device-specific ROM region
89//-------------------------------------------------
90
91const rom_entry *epson_lx810l_t::device_rom_region() const
92{
93   return ROM_NAME( lx810l );
94}
95
96
97//-------------------------------------------------
98//  rom_region - device-specific ROM region
99//-------------------------------------------------
100
101const rom_entry *epson_ap2000_t::device_rom_region() const
102{
103   return ROM_NAME( ap2000 );
104}
105
106
107//-------------------------------------------------
53108//  ADDRESS_MAP( lx800_mem )
54109//-------------------------------------------------
55110
r241971r241972
218273{
219274}
220275
276epson_lx810l_t::epson_lx810l_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
277   : epson_lx800_t(mconfig, EPSON_LX810L, "Epson LX-810L", tag, owner, clock, "lx810l", __FILE__) { }
221278
279epson_ap2000_t::epson_ap2000_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
280   : epson_lx800_t(mconfig, EPSON_AP2000, "Epson ActionPrinter 2000", tag, owner, clock, "ap2000", __FILE__) { }
281
282
222283//-------------------------------------------------
223284//  device_start - device-specific startup
224285//-------------------------------------------------
trunk/src/emu/bus/centronics/epson_lx800.h
r241971r241972
6767};
6868
6969
70// ======================> epson_lx810l_t
7071
72class epson_lx810l_t :  public epson_lx800_t
73{
74public:
75   // construction/destruction
76   epson_lx810l_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
77
78   // optional information overrides
79   virtual const rom_entry *device_rom_region() const;
80};
81
82
83// ======================> epson_ap2000_t
84
85class epson_ap2000_t :  public epson_lx800_t
86{
87public:
88   // construction/destruction
89   epson_ap2000_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
90
91   // optional information overrides
92   virtual const rom_entry *device_rom_region() const;
93};
94
95
96
7197// device type definition
7298extern const device_type EPSON_LX800;
99extern const device_type EPSON_LX810L;
100extern const device_type EPSON_AP2000;
73101
74102
75103
trunk/src/emu/bus/centronics/epson_lx810l.c
r241971r241972
1/*
2 * Epson LX-810L dot matrix printer emulation
3 *
4 * Copyright: 2014 Ramiro Polla
5 *                 Felipe Sanches
6 * License: BSD-3-Clause
7 *
8 * IC list:
9 *   uPD7810HG (cpu)
10 *   E05A30 (gate array)
11 *   2064C (8k RAM)
12 *   ER59256 (EEP-ROM - serial nvram)
13 *   SLA7020M (step motor driver)
14 *   uPC494C (pulse width modulation control)
15 *
16 * Devices boot and enter main input loop, but input is not yet implemented.
17 *
18 * It is possible to run the printers' self test with this procedure:
19 * - Turn on device;
20 * - Toggle Line Feed button (press 'L');
21 * - Reset device;
22 * - Toggle Line Feed button again;
23 * - Press Online button (press 'O');
24 * - Press Online button again;
25 *
26 * The printer's carriage will seek home, it will pull in paper for a while,
27 * and it will start printing some test data. The Online LED will blink at
28 * each line. Look at the output from the fire signal to see what's actually
29 * being printed (epson_lx810l_t::co0_w()).
30 */
31
32#include "epson_lx810l.h"
33extern const char layout_lx800[]; /* use layout from lx800 */
34
35//#define LX810LDEBUG
36#ifdef LX810LDEBUG
37#define LX810LLOG(...) fprintf(stderr, __VA_ARGS__)
38#else
39#define LX810LLOG(...)
40#endif
41
42//**************************************************************************
43//  DEVICE DEFINITIONS
44//**************************************************************************
45
46const device_type EPSON_LX810L = &device_creator<epson_lx810l_t>;
47const device_type EPSON_AP2000 = &device_creator<epson_ap2000_t>;
48
49
50//-------------------------------------------------
51//  ROM( lx810l )
52//-------------------------------------------------
53
54ROM_START( lx810l )
55   ROM_REGION(0x8000, "maincpu", 0)
56   ROM_LOAD("lx810l.ic3c", 0x0000, 0x8000, CRC(a66454e1) SHA1(8e6f2f98abcbd8af6e34b9ba746edf0d18aef843) )
57   ROM_REGION(0x20, "eeprom", 0)
58   ROM_LOAD( "at93c06", 0x00, 0x20, NO_DUMP )
59ROM_END
60
61
62//-------------------------------------------------
63//  ROM( ap2000 )
64//-------------------------------------------------
65
66ROM_START( ap2000 )
67   ROM_REGION(0x8000, "maincpu", 0)
68   ROM_LOAD("ap2k.ic3c", 0x0000, 0x8000, CRC(ee7294b7) SHA1(219ffa6ff661ce95d5772c9fc1967093718f04e9) )
69   ROM_REGION(0x20, "eeprom", 0)
70   ROM_LOAD( "at93c06", 0x00, 0x20, NO_DUMP )
71ROM_END
72
73
74//-------------------------------------------------
75//  rom_region - device-specific ROM region
76//-------------------------------------------------
77
78const rom_entry *epson_lx810l_t::device_rom_region() const
79{
80   return ROM_NAME( lx810l );
81}
82
83
84//-------------------------------------------------
85//  rom_region - device-specific ROM region
86//-------------------------------------------------
87
88const rom_entry *epson_ap2000_t::device_rom_region() const
89{
90   return ROM_NAME( ap2000 );
91}
92
93
94//-------------------------------------------------
95//  ADDRESS_MAP( lx810l_mem )
96//-------------------------------------------------
97
98static ADDRESS_MAP_START( lx810l_mem, AS_PROGRAM, 8, epson_lx810l_t )
99   AM_RANGE(0x0000, 0x7fff) AM_ROM /* 32k firmware */
100   AM_RANGE(0x8000, 0x9fff) AM_RAM /* 8k external RAM */
101   AM_RANGE(0xa000, 0xbfff) AM_READWRITE(fakemem_r, fakemem_w) /* fake memory, write one, set all */
102   AM_RANGE(0xc000, 0xdfff) AM_MIRROR(0x1ff0) AM_DEVREADWRITE("ic3b", e05a30_device, read, write)
103   AM_RANGE(0xe000, 0xfeff) AM_NOP /* not used */
104   AM_RANGE(0xff00, 0xffff) AM_RAM /* internal CPU RAM */
105ADDRESS_MAP_END
106
107
108//-------------------------------------------------
109//  ADDRESS_MAP( lx810l_io )
110//-------------------------------------------------
111
112static ADDRESS_MAP_START( lx810l_io, AS_IO, 8, epson_lx810l_t )
113   AM_RANGE(UPD7810_PORTA, UPD7810_PORTA) AM_READWRITE(porta_r, porta_w)
114   AM_RANGE(UPD7810_PORTB, UPD7810_PORTB) AM_READWRITE(portb_r, portb_w)
115   AM_RANGE(UPD7810_PORTC, UPD7810_PORTC) AM_READWRITE(portc_r, portc_w)
116ADDRESS_MAP_END
117
118
119//-------------------------------------------------
120//  MACHINE_DRIVER( epson_lx810l )
121//-------------------------------------------------
122
123static MACHINE_CONFIG_FRAGMENT( epson_lx810l )
124   /* basic machine hardware */
125   MCFG_CPU_ADD("maincpu", UPD7810, XTAL_14_7456MHz)
126   MCFG_CPU_PROGRAM_MAP(lx810l_mem)
127   MCFG_CPU_IO_MAP(lx810l_io)
128   MCFG_UPD7810_AN0(READ8(epson_lx810l_t, an0_r))
129   MCFG_UPD7810_AN1(READ8(epson_lx810l_t, an1_r))
130   MCFG_UPD7810_AN2(READ8(epson_lx810l_t, an2_r))
131   MCFG_UPD7810_AN3(READ8(epson_lx810l_t, an3_r))
132   MCFG_UPD7810_AN4(READ8(epson_lx810l_t, an4_r))
133   MCFG_UPD7810_AN5(READ8(epson_lx810l_t, an5_r))
134   MCFG_UPD7810_AN6(READ8(epson_lx810l_t, an6_r))
135   MCFG_UPD7810_AN7(READ8(epson_lx810l_t, an7_r))
136   MCFG_UPD7810_CO0(WRITELINE(epson_lx810l_t, co0_w))
137   MCFG_UPD7810_CO1(WRITELINE(epson_lx810l_t, co1_w))
138
139   MCFG_DEFAULT_LAYOUT(layout_lx800)
140
141   /* audio hardware */
142   MCFG_SPEAKER_STANDARD_MONO("mono")
143   MCFG_SOUND_ADD("beeper", BEEP, 0)
144   MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
145   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
146
147   /* gate array */
148   MCFG_DEVICE_ADD("ic3b", E05A30, 0)
149   MCFG_E05A30_PRINTHEAD_CALLBACK(WRITE16(epson_lx810l_t, printhead))
150   MCFG_E05A30_PF_STEPPER_CALLBACK(WRITE8(epson_lx810l_t, pf_stepper))
151   MCFG_E05A30_CR_STEPPER_CALLBACK(WRITE8(epson_lx810l_t, cr_stepper))
152   MCFG_E05A30_READY_CALLBACK(WRITELINE(epson_lx810l_t, e05a30_ready))
153
154   /* 256-bit eeprom */
155   MCFG_EEPROM_SERIAL_93C06_ADD("eeprom")
156MACHINE_CONFIG_END
157
158//-------------------------------------------------
159//  machine_config_additions - device-specific
160//  machine configurations
161//-------------------------------------------------
162
163machine_config_constructor epson_lx810l_t::device_mconfig_additions() const
164{
165   return MACHINE_CONFIG_NAME( epson_lx810l );
166}
167
168
169/***************************************************************************
170    INPUT PORTS
171***************************************************************************/
172
173static INPUT_PORTS_START( epson_lx810l )
174
175   /* Buttons on printer */
176   PORT_START("ONLINE")
177   PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("On Line") PORT_CODE(KEYCODE_O) PORT_CHANGED_MEMBER(DEVICE_SELF, epson_lx810l_t, online_sw, NULL)
178   PORT_START("FORMFEED")
179   PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Form Feed") PORT_CODE(KEYCODE_F) PORT_TOGGLE
180   PORT_START("LINEFEED")
181   PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_L) PORT_TOGGLE
182   PORT_START("LOADEJECT")
183   PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Load/Eject") PORT_CODE(KEYCODE_E)
184
185   /* DIPSW1 */
186   PORT_START("DIPSW1")
187
188   PORT_DIPNAME(0x01, 0x01, "Character spacing")
189   PORT_DIPLOCATION("DIP:1")
190   PORT_DIPSETTING(0x01, "12 cpi") /* default */
191   PORT_DIPSETTING(0x00, "10 cpi")
192
193   PORT_DIPNAME(0x02, 0x00, "Shape of zero")
194   PORT_DIPLOCATION("DIP:2")
195   PORT_DIPSETTING(0x02, "Slashed")
196   PORT_DIPSETTING(0x00, "Not slashed") /* default */
197
198   PORT_DIPNAME(0x0c, 0x08, "Page length")
199   PORT_DIPLOCATION("DIP:3,4")
200   PORT_DIPSETTING(0x00, "11 inches")
201   PORT_DIPSETTING(0x04, "12 inches")
202   PORT_DIPSETTING(0x08, "8.5 inches") /* default */
203   PORT_DIPSETTING(0x0c, "11.7 inches")
204
205   PORT_DIPNAME(0x10, 0x10, "Character table")
206   PORT_DIPLOCATION("DIP:5")
207   PORT_DIPSETTING(0x10, "Graphics") /* default */
208   PORT_DIPSETTING(0x00, "Italics")
209
210   PORT_DIPNAME(0xe0, 0xe0, "International characters and PC selection")
211   PORT_DIPLOCATION("DIP:6,7,8")
212   PORT_DIPSETTING(0xe0, "United States") /* default */
213   PORT_DIPSETTING(0x60, "France")
214   PORT_DIPSETTING(0xa0, "Germany")
215   PORT_DIPSETTING(0x20, "United Kingdom")
216   PORT_DIPSETTING(0xc0, "Denmark")
217   PORT_DIPSETTING(0x40, "Sweden")
218   PORT_DIPSETTING(0x80, "Italy")
219   PORT_DIPSETTING(0x00, "Spain")
220
221   /* DIPSW2 */
222   PORT_START("DIPSW2")
223
224   PORT_DIPNAME(0x01, 0x01, "Short tear-off")
225   PORT_DIPLOCATION("DIP:1")
226   PORT_DIPSETTING(0x01, "Invalid") /* default */
227   PORT_DIPSETTING(0x00, "Valid")
228
229   PORT_DIPNAME(0x02, 0x00, "Cut-sheet feeder mode")
230   PORT_DIPLOCATION("DIP:2")
231   PORT_DIPSETTING(0x02, "ON")
232   PORT_DIPSETTING(0x00, "OFF") /* default */
233
234   PORT_DIPNAME(0x04, 0x00, "Skip-over-perforation")
235   PORT_DIPLOCATION("DIP:3")
236   PORT_DIPSETTING(0x04, "ON")
237   PORT_DIPSETTING(0x00, "OFF") /* default */
238
239   PORT_DIPNAME(0x08, 0x00, "Auto line feed")
240   PORT_DIPLOCATION("DIP:4")
241   PORT_DIPSETTING(0x08, "ON")
242   PORT_DIPSETTING(0x00, "OFF") /* default */
243
244INPUT_PORTS_END
245
246
247//-------------------------------------------------
248//  input_ports - device-specific input ports
249//-------------------------------------------------
250
251ioport_constructor epson_lx810l_t::device_input_ports() const
252{
253   return INPUT_PORTS_NAME( epson_lx810l );
254}
255
256INPUT_CHANGED_MEMBER(epson_lx810l_t::online_sw)
257{
258   m_maincpu->set_input_line(UPD7810_INTF2, newval ? CLEAR_LINE : ASSERT_LINE);
259}
260
261
262//**************************************************************************
263//  LIVE DEVICE
264//**************************************************************************
265
266//-------------------------------------------------
267//  epson_lx810l_t - constructor
268//-------------------------------------------------
269
270epson_lx810l_t::epson_lx810l_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
271   device_t(mconfig, EPSON_LX810L, "Epson LX-810L", tag, owner, clock, "lx810l", __FILE__),
272   device_centronics_peripheral_interface(mconfig, *this),
273   m_maincpu(*this, "maincpu"),
274   m_eeprom(*this, "eeprom"),
275   m_speaker(*this, "speaker"),
276   m_93c06_clk(0),
277   m_93c06_cs(0),
278   m_printhead(0),
279   m_pf_pos_abs(200),
280   m_cr_pos_abs(200),
281   m_last_fire(0)
282{
283}
284
285epson_lx810l_t::epson_lx810l_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
286   device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__),
287   device_centronics_peripheral_interface(mconfig, *this),
288   m_maincpu(*this, "maincpu"),
289   m_eeprom(*this, "eeprom"),
290   m_speaker(*this, "speaker"),
291   m_93c06_clk(0),
292   m_93c06_cs(0),
293   m_printhead(0),
294   m_pf_pos_abs(200),
295   m_cr_pos_abs(200),
296   m_last_fire(0)
297{
298}
299
300epson_ap2000_t::epson_ap2000_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
301   : epson_lx810l_t(mconfig, EPSON_AP2000, "Epson ActionPrinter 2000", tag, owner, clock, "ap2000", __FILE__)
302{ }
303
304
305//-------------------------------------------------
306//  device_start - device-specific startup
307//-------------------------------------------------
308
309static const stepper_interface lx810l_pf_stepper =
310{
311   STARPOINT_48STEP_REEL,
312   16,
313   24,
314   0x00,
315   0
316};
317
318static const stepper_interface lx810l_cr_stepper =
319{
320   STARPOINT_48STEP_REEL,
321   16,
322   24,
323   0x00,
324   2
325};
326
327void epson_lx810l_t::device_start()
328{
329   stepper_config(machine(), 0, &lx810l_pf_stepper);
330   stepper_config(machine(), 1, &lx810l_cr_stepper);
331}
332
333
334//-------------------------------------------------
335//  device_reset - device-specific reset
336//-------------------------------------------------
337
338void epson_lx810l_t::device_reset()
339{
340   m_speaker->level_w(0);
341}
342
343
344/***************************************************************************
345    FAKEMEM READ/WRITE
346***************************************************************************/
347
348READ8_MEMBER(epson_lx810l_t::fakemem_r)
349{
350   return m_fakemem;
351}
352
353WRITE8_MEMBER(epson_lx810l_t::fakemem_w)
354{
355   m_fakemem = data;
356}
357
358
359/***************************************************************************
360    I/O PORTS
361***************************************************************************/
362
363/*
364 * PA0  R   CN7 sensor (Home Position, HP, active low)
365 * PA1  R   CN6 sensor (Paper-End, PE, active low)
366 * PA2  R   CN4 sensor (Release, low = tractor)
367 * PA3   W  Stepper motor voltage reference (these 3 pins make up one voltage)
368 * PA4   W  Stepper motor voltage reference (these 3 pins make up one voltage)
369 * PA5   W  Stepper motor voltage reference (these 3 pins make up one voltage)
370 * PA6  R   Line Feed SWITCH
371 * PA7  R   Form Feed SWITCH
372 */
373READ8_MEMBER( epson_lx810l_t::porta_r )
374{
375   UINT8 result = 0;
376   UINT8 hp_sensor = m_cr_pos_abs <= 0 ? 0 : 1;
377   UINT8 pe_sensor = m_pf_pos_abs <= 0 ? 1 : 0;
378
379   result |= hp_sensor; /* home position */
380   result |= pe_sensor << 1; /* paper end */
381   result |= ioport("LINEFEED")->read() << 6;
382   result |= ioport("FORMFEED")->read() << 7;
383
384   LX810LLOG("%s: lx810l_PA_r(%02x): result %02x\n", machine().describe_context(), offset, result);
385
386   return result;
387}
388
389WRITE8_MEMBER( epson_lx810l_t::porta_w )
390{
391   LX810LLOG("%s: lx810l_PA_w(%02x): %02x: stepper vref %d\n", machine().describe_context(), offset, data, BIT(data, 3) | (BIT(data, 4)<<1) | (BIT(data, 5)<<2));
392}
393
394/*
395 * PB0  R   DIP1.0 & 93C06.DO
396 * PB1  RW  DIP1.1 & 93C06.DI
397 * PB2  R   DIP1.2
398 * PB3  R   DIP1.3
399 * PB4  R   DIP1.4
400 * PB5  R   DIP1.5
401 * PB6  R   DIP1.6
402 * PB7  R   DIP1.7
403 */
404READ8_MEMBER( epson_lx810l_t::portb_r )
405{
406   UINT8 result = ~ioport("DIPSW1")->read();
407
408   /* if 93C06 is selected */
409   if (m_93c06_cs) {
410      UINT8 do_r = m_eeprom->do_read();
411      result &= 0xfe;
412      result |= do_r;
413   }
414
415   LX810LLOG("%s: lx810l_PB_r(%02x): result %02x\n", machine().describe_context(), offset, result);
416
417   return result;
418}
419
420WRITE8_MEMBER( epson_lx810l_t::portb_w )
421{
422   UINT8 data_in = BIT(data, 1);
423
424   /* if 93C06 is selected */
425   if (m_93c06_cs)
426      m_eeprom->di_write(data_in);
427
428   LX810LLOG("%s: lx810l_PB_w(%02x): %02x: 93c06 data %d\n", machine().describe_context(), offset, data, data_in);
429}
430
431/*
432 * PC0   W  TXD        serial i/o txd, also TAMA.25
433 * PC1  R   RXD        serial i/o rxd, also E05A30.28
434 * PC2   W  ONLINE LP  online led
435 * PC3  R   ONLINE SW  online switch
436 * PC4   W  93C06.SK
437 * PC5   W  93C06.CS
438 * PC6   W  FIRE       drive pulse width signal, also E05A30.57
439 * PC7   W  BUZZER     buzzer signal
440 */
441READ8_MEMBER( epson_lx810l_t::portc_r )
442{
443   UINT8 result = 0;
444
445   /* result |= ioport("serial")->read() << 1; */
446   result |= !ioport("ONLINE")->read() << 3;
447   result |= m_93c06_clk << 4;
448   result |= m_93c06_cs  << 5;
449
450   LX810LLOG("%s: lx810l_PC_r(%02x): %02x\n", machine().describe_context(), offset, result);
451
452   return result;
453}
454
455WRITE8_MEMBER( epson_lx810l_t::portc_w )
456{
457   /* ioport("serial")->write(BIT(data, 0)); */
458
459   m_93c06_clk =  BIT(data, 4);
460   m_93c06_cs  = !BIT(data, 5);
461
462   LX810LLOG("%s: PC_w(%02x): %02x 93c06 clk: %d cs: %d\n", machine().describe_context(), offset, data, m_93c06_clk, m_93c06_cs);
463
464   m_eeprom->clk_write(m_93c06_clk ? ASSERT_LINE : CLEAR_LINE);
465   m_eeprom->cs_write (m_93c06_cs  ? ASSERT_LINE : CLEAR_LINE);
466
467   output_set_value("online_led", !BIT(data, 2));
468}
469
470
471/***************************************************************************
472    GATE ARRAY
473***************************************************************************/
474
475WRITE16_MEMBER( epson_lx810l_t::printhead )
476{
477   m_printhead = data;
478}
479
480WRITE8_MEMBER( epson_lx810l_t::pf_stepper )
481{
482   stepper_update(0, data);
483   m_pf_pos_abs = 200 - stepper_get_absolute_position(0);
484
485   LX810LLOG("%s: %s(%02x); abs %d\n", machine().describe_context(), __func__, data, m_pf_pos_abs);
486}
487
488WRITE8_MEMBER( epson_lx810l_t::cr_stepper )
489{
490   stepper_update(1, data);
491   m_cr_pos_abs = 200 - stepper_get_absolute_position(1);
492
493   LX810LLOG("%s: %s(%02x); abs %d\n", machine().describe_context(), __func__, data, m_cr_pos_abs);
494}
495
496WRITE_LINE_MEMBER( epson_lx810l_t::e05a30_ready )
497{
498   m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
499}
500
501
502/***************************************************************************
503    Extended Timer Output
504***************************************************************************/
505
506WRITE_LINE_MEMBER( epson_lx810l_t::co0_w )
507{
508   /* TODO Draw the dots on the paper using this information. */
509
510   /* Printhead is being fired on !state. */
511   if (!state) {
512      int pos = m_cr_pos_abs;
513
514      /* HACK to get fire positions for motor in movement. The firmware
515       * issues two half-steps one immediately after the other. A timer
516       * fires the printhead twice. Supposedly, the first time the
517       * printhead is fired, it is midway between one step and the other.
518       * Ideally, the stepper motor interface should model the physics
519       * of the motors. For the moment, we adjust pos to get the
520       * intermediate position.
521       */
522
523      if      (m_cr_pos_abs > m_last_fire + 1)
524         pos--;
525      else if (m_cr_pos_abs < m_last_fire - 1)
526         pos++;
527
528      LX810LLOG("FIRE0 %d %d %04x\n", m_pf_pos_abs, pos, m_printhead);
529
530      m_last_fire = pos;
531   }
532}
533
534WRITE_LINE_MEMBER( epson_lx810l_t::co1_w )
535{
536   m_speaker->level_w(state);
537}
538
539
540/***************************************************************************
541    ADC
542***************************************************************************/
543
544READ8_MEMBER(epson_lx810l_t::an0_r)
545{
546   UINT8 res = !!(ioport("DIPSW2")->read() & 0x01);
547   return res - 1; /* DIPSW2.1 */
548}
549
550READ8_MEMBER(epson_lx810l_t::an1_r)
551{
552   UINT8 res = !!(ioport("DIPSW2")->read() & 0x02);
553   return res - 1; /* DIPSW2.2 */
554}
555
556READ8_MEMBER(epson_lx810l_t::an2_r)
557{
558   UINT8 res = !!(ioport("DIPSW2")->read() & 0x04);
559   return res - 1; /* DIPSW2.3 */
560}
561
562READ8_MEMBER(epson_lx810l_t::an3_r)
563{
564   UINT8 res = !!(ioport("DIPSW2")->read() & 0x08);
565   return res - 1; /* DIPSW2.4 */
566}
567
568READ8_MEMBER(epson_lx810l_t::an4_r)
569{
570   return 0xff;
571}
572
573READ8_MEMBER(epson_lx810l_t::an5_r)
574{
575   return 0xCB; /* motor voltage, 0xcb = 24V */
576}
577
578READ8_MEMBER(epson_lx810l_t::an6_r)
579{
580   UINT8 res = !ioport("LOADEJECT")->read();
581   return res - 1;
582}
583
584READ8_MEMBER(epson_lx810l_t::an7_r)
585{
586   return 0xff;
587}
trunk/src/emu/bus/centronics/epson_lx810l.h
r241971r241972
1/*
2 * Epson LX-810L dot matrix printer emulation
3 *
4 * Copyright: 2014 Ramiro Polla
5 *                 Felipe Sanches
6 * License: BSD-3-Clause
7 */
8
9#pragma once
10
11#ifndef __EPSON_LX810L__
12#define __EPSON_LX810L__
13
14#include "emu.h"
15#include "ctronics.h"
16#include "cpu/upd7810/upd7810.h"
17#include "machine/e05a30.h"
18#include "machine/eepromser.h"
19#include "machine/steppers.h"
20#include "sound/beep.h"
21#include "sound/speaker.h"
22
23
24//**************************************************************************
25//  TYPE DEFINITIONS
26//**************************************************************************
27
28// ======================> epson_lx810l_t
29
30class epson_lx810l_t : public device_t,
31                       public device_centronics_peripheral_interface
32{
33public:
34   // construction/destruction
35   epson_lx810l_t(const machine_config &mconfig, const char *tag,
36                  device_t *owner, UINT32 clock);
37   epson_lx810l_t(const machine_config &mconfig, device_type type,
38                  const char *name, const char *tag, device_t *owner,
39                  UINT32 clock, const char *shortname, const char *source);
40
41   // optional information overrides
42   virtual const rom_entry *device_rom_region() const;
43   virtual machine_config_constructor device_mconfig_additions() const;
44   virtual ioport_constructor device_input_ports() const;
45
46   DECLARE_READ8_MEMBER(porta_r);
47   DECLARE_WRITE8_MEMBER(porta_w);
48   DECLARE_READ8_MEMBER(portb_r);
49   DECLARE_WRITE8_MEMBER(portb_w);
50   DECLARE_READ8_MEMBER(portc_r);
51   DECLARE_WRITE8_MEMBER(portc_w);
52
53   /* Extended Timer Output */
54   DECLARE_WRITE_LINE_MEMBER(co0_w);
55   DECLARE_WRITE_LINE_MEMBER(co1_w);
56
57   /* ADC */
58   DECLARE_READ8_MEMBER(an0_r);
59   DECLARE_READ8_MEMBER(an1_r);
60   DECLARE_READ8_MEMBER(an2_r);
61   DECLARE_READ8_MEMBER(an3_r);
62   DECLARE_READ8_MEMBER(an4_r);
63   DECLARE_READ8_MEMBER(an5_r);
64   DECLARE_READ8_MEMBER(an6_r);
65   DECLARE_READ8_MEMBER(an7_r);
66
67   /* fake memory I/O to get past memory reset check */
68   DECLARE_READ8_MEMBER(fakemem_r);
69   DECLARE_WRITE8_MEMBER(fakemem_w);
70
71   /* GATE ARRAY */
72   DECLARE_WRITE16_MEMBER(printhead);
73   DECLARE_WRITE8_MEMBER(pf_stepper);
74   DECLARE_WRITE8_MEMBER(cr_stepper);
75   DECLARE_WRITE_LINE_MEMBER(e05a30_ready);
76
77   /* Panel buttons */
78   DECLARE_INPUT_CHANGED_MEMBER(online_sw);
79
80protected:
81   // device-level overrides
82   virtual void device_start();
83   virtual void device_reset();
84
85private:
86   required_device<cpu_device> m_maincpu;
87   required_device<eeprom_serial_93cxx_device> m_eeprom;
88   required_device<speaker_sound_device> m_speaker;
89
90   int m_93c06_clk;
91   int m_93c06_cs;
92   UINT16 m_printhead;
93   int m_pf_pos_abs;
94   int m_cr_pos_abs;
95   int m_last_fire; /* HACK to get fire positions for motor in movement */
96   UINT8 m_fakemem;
97};
98
99// ======================> epson_ap2000_t
100
101class epson_ap2000_t : public epson_lx810l_t
102{
103public:
104   // construction/destruction
105   epson_ap2000_t(const machine_config &mconfig, const char *tag,
106                  device_t *owner, UINT32 clock);
107
108   // optional information overrides
109   virtual const rom_entry *device_rom_region() const;
110};
111
112
113// device type definition
114extern const device_type EPSON_LX810L;
115extern const device_type EPSON_AP2000;
116
117#endif
trunk/src/emu/cpu/rsp/rspcp2d.c
r241971r241972
258258//
259259// Load 1 byte to vector byte index
260260
261void rsp_cop2_drc::lbv()
261inline void rsp_cop2_drc::lbv()
262262{
263263   UINT32 op = m_op;
264264
r241971r241972
291291//
292292// Loads 2 bytes starting from vector byte index
293293
294void rsp_cop2_drc::lsv()
294inline void rsp_cop2_drc::lsv()
295295{
296296   UINT32 op = m_op;
297297   int dest = (op >> 16) & 0x1f;
r241971r241972
327327//
328328// Loads 4 bytes starting from vector byte index
329329
330void rsp_cop2_drc::llv()
330inline void rsp_cop2_drc::llv()
331331{
332332   UINT32 op = m_op;
333333   UINT32 ea = 0;
r241971r241972
366366//
367367// Loads 8 bytes starting from vector byte index
368368
369void rsp_cop2_drc::ldv()
369inline void rsp_cop2_drc::ldv()
370370{
371371   UINT32 op = m_op;
372372   UINT32 ea = 0;
r241971r241972
405405//
406406// Loads up to 16 bytes starting from vector byte index
407407
408void rsp_cop2_drc::lqv()
408inline void rsp_cop2_drc::lqv()
409409{
410410   UINT32 op = m_op;
411411   int dest = (op >> 16) & 0x1f;
r241971r241972
443443//
444444// Stores up to 16 bytes starting from right side until 16-byte boundary
445445
446void rsp_cop2_drc::lrv()
446inline void rsp_cop2_drc::lrv()
447447{
448448   UINT32 op = m_op;
449449   int dest = (op >> 16) & 0x1f;
r241971r241972
482482//
483483// Loads a byte as the upper 8 bits of each element
484484
485void rsp_cop2_drc::lpv()
485inline void rsp_cop2_drc::lpv()
486486{
487487   UINT32 op = m_op;
488488   int dest = (op >> 16) & 0x1f;
r241971r241972
517517//
518518// Loads a byte as the bits 14-7 of each element
519519
520void rsp_cop2_drc::luv()
520inline void rsp_cop2_drc::luv()
521521{
522522   UINT32 op = m_op;
523523   int dest = (op >> 16) & 0x1f;
r241971r241972
552552//
553553// Loads a byte as the bits 14-7 of each element, with 2-byte stride
554554
555void rsp_cop2_drc::lhv()
555inline void rsp_cop2_drc::lhv()
556556{
557557   UINT32 op = m_op;
558558   int dest = (op >> 16) & 0x1f;
r241971r241972
586586//
587587// Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride
588588
589void rsp_cop2_drc::lfv()
589inline void rsp_cop2_drc::lfv()
590590{
591591   UINT32 op = m_op;
592592   int dest = (op >> 16) & 0x1f;
r241971r241972
627627// Loads the full 128-bit vector starting from vector byte index and wrapping to index 0
628628// after byte index 15
629629
630void rsp_cop2_drc::lwv()
630inline void rsp_cop2_drc::lwv()
631631{
632632   UINT32 op = m_op;
633633   int dest = (op >> 16) & 0x1f;
r241971r241972
664664//
665665// Loads one element to maximum of 8 vectors, while incrementing element index
666666
667void rsp_cop2_drc::ltv()
667inline void rsp_cop2_drc::ltv()
668668{
669669   UINT32 op = m_op;
670670   int dest = (op >> 16) & 0x1f;
r241971r241972
791791//
792792// Stores 1 byte from vector byte index
793793
794void rsp_cop2_drc::sbv()
794inline void rsp_cop2_drc::sbv()
795795{
796796   UINT32 op = m_op;
797797   int dest = (op >> 16) & 0x1f;
r241971r241972
822822//
823823// Stores 2 bytes starting from vector byte index
824824
825void rsp_cop2_drc::ssv()
825inline void rsp_cop2_drc::ssv()
826826{
827827   UINT32 op = m_op;
828828   int dest = (op >> 16) & 0x1f;
r241971r241972
859859//
860860// Stores 4 bytes starting from vector byte index
861861
862void rsp_cop2_drc::slv()
862inline void rsp_cop2_drc::slv()
863863{
864864   UINT32 op = m_op;
865865   int dest = (op >> 16) & 0x1f;
r241971r241972
896896//
897897// Stores 8 bytes starting from vector byte index
898898
899void rsp_cop2_drc::sdv()
899inline void rsp_cop2_drc::sdv()
900900{
901901   UINT32 op = m_op;
902902   int dest = (op >> 16) & 0x1f;
r241971r241972
932932//
933933// Stores up to 16 bytes starting from vector byte index until 16-byte boundary
934934
935void rsp_cop2_drc::sqv()
935inline void rsp_cop2_drc::sqv()
936936{
937937   UINT32 op = m_op;
938938   int dest = (op >> 16) & 0x1f;
r241971r241972
968968//
969969// Stores up to 16 bytes starting from right side until 16-byte boundary
970970
971void rsp_cop2_drc::srv()
971inline void rsp_cop2_drc::srv()
972972{
973973   UINT32 op = m_op;
974974   int dest = (op >> 16) & 0x1f;
r241971r241972
10081008//
10091009// Stores upper 8 bits of each element
10101010
1011void rsp_cop2_drc::spv()
1011inline void rsp_cop2_drc::spv()
10121012{
10131013   UINT32 op = m_op;
10141014   int dest = (op >> 16) & 0x1f;
r241971r241972
10511051//
10521052// Stores bits 14-7 of each element
10531053
1054void rsp_cop2_drc::suv()
1054inline void rsp_cop2_drc::suv()
10551055{
10561056   UINT32 op = m_op;
10571057   int dest = (op >> 16) & 0x1f;
r241971r241972
10941094//
10951095// Stores bits 14-7 of each element, with 2-byte stride
10961096
1097void rsp_cop2_drc::shv()
1097inline void rsp_cop2_drc::shv()
10981098{
10991099   UINT32 op = m_op;
11001100   int dest = (op >> 16) & 0x1f;
r241971r241972
11321132//
11331133// Stores bits 14-7 of upper or lower quad, with 4-byte stride
11341134
1135void rsp_cop2_drc::sfv()
1135inline void rsp_cop2_drc::sfv()
11361136{
11371137   UINT32 op = m_op;
11381138   int dest = (op >> 16) & 0x1f;
r241971r241972
11731173// Stores the full 128-bit vector starting from vector byte index and wrapping to index 0
11741174// after byte index 15
11751175
1176void rsp_cop2_drc::swv()
1176inline void rsp_cop2_drc::swv()
11771177{
11781178   UINT32 op = m_op;
11791179   int dest = (op >> 16) & 0x1f;
r241971r241972
12121212//
12131213// Stores one element from maximum of 8 vectors, while incrementing element index
12141214
1215void rsp_cop2_drc::stv()
1215inline void rsp_cop2_drc::stv()
12161216{
12171217   UINT32 op = m_op;
12181218   int dest = (op >> 16) & 0x1f;
r241971r241972
13441344//
13451345// Multiplies signed integer by signed integer * 2
13461346
1347void rsp_cop2_drc::vmulf()
1347inline void rsp_cop2_drc::vmulf()
13481348{
13491349   int op = m_op;
13501350
r241971r241972
13911391// ------------------------------------------------------
13921392//
13931393
1394void rsp_cop2_drc::vmulu()
1394inline void rsp_cop2_drc::vmulu()
13951395{
13961396   int op = m_op;
13971397
r241971r241972
14431443// The result is added into accumulator
14441444// The middle slice of accumulator is stored into destination element
14451445
1446void rsp_cop2_drc::vmudl()
1446inline void rsp_cop2_drc::vmudl()
14471447{
14481448   int op = m_op;
14491449
r241971r241972
14831483// The result is stored into accumulator
14841484// The middle slice of accumulator is stored into destination element
14851485
1486void rsp_cop2_drc::vmudm()
1486inline void rsp_cop2_drc::vmudm()
14871487{
14881488   int op = m_op;
14891489
r241971r241972
15231523// The result is stored into accumulator
15241524// The low slice of accumulator is stored into destination element
15251525
1526void rsp_cop2_drc::vmudn()
1526inline void rsp_cop2_drc::vmudn()
15271527{
15281528   int op = m_op;
15291529
r241971r241972
15631563// The result is stored into highest 32 bits of accumulator, the low slice is zero
15641564// The highest 32 bits of accumulator is saturated into destination element
15651565
1566void rsp_cop2_drc::vmudh()
1566inline void rsp_cop2_drc::vmudh()
15671567{
15681568   int op = m_op;
15691569
r241971r241972
16021602// ------------------------------------------------------
16031603//
16041604
1605void rsp_cop2_drc::vmacf()
1605inline void rsp_cop2_drc::vmacf()
16061606{
16071607   int op = m_op;
16081608
r241971r241972
16461646// ------------------------------------------------------
16471647//
16481648
1649void rsp_cop2_drc::vmacu()
1649inline void rsp_cop2_drc::vmacu()
16501650{
16511651   int op = m_op;
16521652
r241971r241972
17091709// Adds the higher 16 bits of the 32-bit result to accumulator
17101710// The low slice of accumulator is stored into destination element
17111711
1712void rsp_cop2_drc::vmadl()
1712inline void rsp_cop2_drc::vmadl()
17131713{
17141714   int op = m_op;
17151715
r241971r241972
17431743// VMADM
17441744//
17451745
1746void rsp_cop2_drc::vmadm()
1746inline void rsp_cop2_drc::vmadm()
17471747{
17481748   int op = m_op;
17491749
r241971r241972
17811781// VMADN
17821782//
17831783
1784void rsp_cop2_drc::vmadn()
1784inline void rsp_cop2_drc::vmadn()
17851785{
17861786   int op = m_op;
17871787
r241971r241972
18261826// The result is added into highest 32 bits of accumulator, the low slice is zero
18271827// The highest 32 bits of accumulator is saturated into destination element
18281828
1829void rsp_cop2_drc::vmadh()
1829inline void rsp_cop2_drc::vmadh()
18301830{
18311831   int op = m_op;
18321832
r241971r241972
18641864//
18651865// Adds two vector registers and carry flag, the result is saturated to 32767
18661866
1867void rsp_cop2_drc::vadd()
1867inline void rsp_cop2_drc::vadd()
18681868{
18691869   int op = m_op;
18701870
r241971r241972
19041904// Subtracts two vector registers and carry flag, the result is saturated to -32768
19051905// TODO: check VS2REG == VDREG
19061906
1907void rsp_cop2_drc::vsub()
1907inline void rsp_cop2_drc::vsub()
19081908{
19091909   int op = m_op;
19101910
r241971r241972
19441944//
19451945// Changes the sign of source register 2 if source register 1 is negative and stores the result to destination register
19461946
1947void rsp_cop2_drc::vabs()
1947inline void rsp_cop2_drc::vabs()
19481948{
19491949   int op = m_op;
19501950
r241971r241972
19951995// Adds two vector registers, the carry out is stored into carry register
19961996// TODO: check VS2REG = VDREG
19971997
1998void rsp_cop2_drc::vaddc()
1998inline void rsp_cop2_drc::vaddc()
19991999{
20002000   int op = m_op;
20012001
r241971r241972
20382038// Subtracts two vector registers, the carry out is stored into carry register
20392039// TODO: check VS2REG = VDREG
20402040
2041void rsp_cop2_drc::vsubc()
2041inline void rsp_cop2_drc::vsubc()
20422042{
20432043   int op = m_op;
20442044
r241971r241972
20842084//
20852085// Adds two vector registers bytewise with rounding
20862086
2087void rsp_cop2_drc::vaddb()
2087inline void rsp_cop2_drc::vaddb()
20882088{
20892089   const int op = m_op;
20902090   const int round = (EL == 0) ? 0 : (1 << (EL - 1));
r241971r241972
21382138//
21392139// Stores high, middle or low slice of accumulator to destination vector
21402140
2141void rsp_cop2_drc::vsaw()
2141inline void rsp_cop2_drc::vsaw()
21422142{
21432143   int op = m_op;
21442144
r241971r241972
21882188// Sets compare flags if elements in VS1 are less than VS2
21892189// Moves the element in VS2 to destination vector
21902190
2191void rsp_cop2_drc::vlt()
2191inline void rsp_cop2_drc::vlt()
21922192{
21932193   int op = m_op;
21942194
r241971r241972
22462246// Sets compare flags if elements in VS1 are equal with VS2
22472247// Moves the element in VS2 to destination vector
22482248
2249void rsp_cop2_drc::veq()
2249inline void rsp_cop2_drc::veq()
22502250{
22512251   int op = m_op;
22522252
r241971r241972
22932293// Sets compare flags if elements in VS1 are not equal with VS2
22942294// Moves the element in VS2 to destination vector
22952295
2296void rsp_cop2_drc::vne()
2296inline void rsp_cop2_drc::vne()
22972297{
22982298   int op = m_op;
22992299
r241971r241972
23402340// Sets compare flags if elements in VS1 are greater or equal with VS2
23412341// Moves the element in VS2 to destination vector
23422342
2343void rsp_cop2_drc::vge()
2343inline void rsp_cop2_drc::vge()
23442344{
23452345   int op = m_op;
23462346
r241971r241972
23852385//
23862386// Vector clip low
23872387
2388void rsp_cop2_drc::vcl()
2388inline void rsp_cop2_drc::vcl()
23892389{
23902390   int op = m_op;
23912391
r241971r241972
24882488//
24892489// Vector clip high
24902490
2491void rsp_cop2_drc::vch()
2491inline void rsp_cop2_drc::vch()
24922492{
24932493   int op = m_op;
24942494
r241971r241972
25752575//
25762576// Vector clip reverse
25772577
2578void rsp_cop2_drc::vcr()
2578inline void rsp_cop2_drc::vcr()
25792579{
25802580   int op = m_op;
25812581
r241971r241972
26442644//
26452645// Merges two vectors according to compare flags
26462646
2647void rsp_cop2_drc::vmrg()
2647inline void rsp_cop2_drc::vmrg()
26482648{
26492649   int op = m_op;
26502650
r241971r241972
26822682//
26832683// Bitwise AND of two vector registers
26842684
2685void rsp_cop2_drc::vand()
2685inline void rsp_cop2_drc::vand()
26862686{
26872687   int op = m_op;
26882688
r241971r241972
27122712//
27132713// Bitwise NOT AND of two vector registers
27142714
2715void rsp_cop2_drc::vnand()
2715inline void rsp_cop2_drc::vnand()
27162716{
27172717   int op = m_op;
27182718
r241971r241972
27422742//
27432743// Bitwise OR of two vector registers
27442744
2745void rsp_cop2_drc::vor()
2745inline void rsp_cop2_drc::vor()
27462746{
27472747   int op = m_op;
27482748
r241971r241972
27722772//
27732773// Bitwise NOT OR of two vector registers
27742774
2775void rsp_cop2_drc::vnor()
2775inline void rsp_cop2_drc::vnor()
27762776{
27772777   int op = m_op;
27782778
r241971r241972
28022802//
28032803// Bitwise XOR of two vector registers
28042804
2805void rsp_cop2_drc::vxor()
2805inline void rsp_cop2_drc::vxor()
28062806{
28072807   int op = m_op;
28082808
r241971r241972
28322832//
28332833// Bitwise NOT XOR of two vector registers
28342834
2835void rsp_cop2_drc::vnxor()
2835inline void rsp_cop2_drc::vnxor()
28362836{
28372837   int op = m_op;
28382838
r241971r241972
28622862//
28632863// Calculates reciprocal
28642864
2865void rsp_cop2_drc::vrcp()
2865inline void rsp_cop2_drc::vrcp()
28662866{
28672867   int op = m_op;
28682868
r241971r241972
29272927//
29282928// Calculates reciprocal low part
29292929
2930void rsp_cop2_drc::vrcpl()
2930inline void rsp_cop2_drc::vrcpl()
29312931{
29322932   int op = m_op;
29332933
r241971r241972
30123012//
30133013// Calculates reciprocal high part
30143014
3015void rsp_cop2_drc::vrcph()
3015inline void rsp_cop2_drc::vrcph()
30163016{
30173017   int op = m_op;
30183018
r241971r241972
30423042//
30433043// Moves element from vector to destination vector
30443044
3045void rsp_cop2_drc::vmov()
3045inline void rsp_cop2_drc::vmov()
30463046{
30473047   int op = m_op;
30483048
r241971r241972
30683068//
30693069// Calculates reciprocal square-root
30703070
3071void rsp_cop2_drc::vrsq()
3071inline void rsp_cop2_drc::vrsq()
30723072{
30733073   int op = m_op;
30743074
r241971r241972
31993199//
32003200// Calculates reciprocal square-root low part
32013201
3202void rsp_cop2_drc::vrsql()
3202inline void rsp_cop2_drc::vrsql()
32033203{
32043204   int op = m_op;
32053205
r241971r241972
32853285//
32863286// Calculates reciprocal square-root high part
32873287
3288void rsp_cop2_drc::vrsqh()
3288inline void rsp_cop2_drc::vrsqh()
32893289{
32903290   int op = m_op;
32913291
r241971r241972
35533553    Vector Flag Reading/Writing
35543554***************************************************************************/
35553555
3556void rsp_cop2_drc::mfc2()
3556inline void rsp_cop2_drc::mfc2()
35573557{
35583558   UINT32 op = m_op;
35593559   int el = (op >> 7) & 0xf;
r241971r241972
35683568   ((rsp_cop2 *)param)->mfc2();
35693569}
35703570
3571void rsp_cop2_drc::cfc2()
3571inline void rsp_cop2_drc::cfc2()
35723572{
35733573   UINT32 op = m_op;
35743574   if (RTREG)
r241971r241972
36333633}
36343634
36353635
3636void rsp_cop2_drc::mtc2()
3636inline void rsp_cop2_drc::mtc2()
36373637{
36383638   UINT32 op = m_op;
36393639   int el = (op >> 7) & 0xf;
r241971r241972
36473647}
36483648
36493649
3650void rsp_cop2_drc::ctc2()
3650inline void rsp_cop2_drc::ctc2()
36513651{
36523652   UINT32 op = m_op;
36533653   switch(RDREG)
trunk/src/emu/machine/e05a30.c
r241971r241972
1/*
2 * E05A30 Gate Array (used in the Epson ActionPrinter 2000)
3 *
4 * Copyright: 2014 Ramiro Polla
5 * License: BSD-3-Clause
6 */
7
8#include "emu.h"
9#include "e05a30.h"
10
11//#define E05A30DEBUG
12#ifdef E05A30DEBUG
13#define LOG(...) fprintf(stderr, __VA_ARGS__)
14#else
15#define LOG(...)
16#endif
17
18
19/*****************************************************************************
20    DEVICE INTERFACE
21*****************************************************************************/
22
23const device_type E05A30 = &device_creator<e05a30_device>;
24
25e05a30_device::e05a30_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
26   : device_t(mconfig, E05A30, "E05A30", tag, owner, clock, "e05a30", __FILE__),
27   m_write_printhead(*this),
28   m_write_pf_stepper(*this),
29   m_write_cr_stepper(*this),
30   m_write_ready(*this),
31   m_printhead(0),
32   m_pf_stepper(0),
33   m_cr_stepper(0)
34{
35}
36
37//-------------------------------------------------
38//  device_start - device-specific startup
39//-------------------------------------------------
40
41void e05a30_device::device_start()
42{
43   /* resolve callbacks */
44   m_write_printhead.resolve_safe();
45   m_write_pf_stepper.resolve_safe();
46   m_write_cr_stepper.resolve_safe();
47   m_write_ready.resolve_safe();
48
49   /* register for state saving */
50   save_item(NAME(m_printhead));
51   save_item(NAME(m_pf_stepper));
52   save_item(NAME(m_cr_stepper));
53}
54
55//-------------------------------------------------
56//  device_reset - device-specific reset
57//-------------------------------------------------
58
59void e05a30_device::device_reset()
60{
61   m_printhead  = 0x00;
62   m_pf_stepper = 0x00;
63   m_cr_stepper = 0x00;
64
65   m_write_ready(1);
66}
67
68
69/***************************************************************************
70    PRINT HEAD
71***************************************************************************/
72
73/* The e05a30 controls the printhead through MMIOs 0xC005 and 0xC006.
74 * MMIO 0xC006 keeps the first 8 pins.
75 * MMIO 0xC005 keeps the 9th pin in the MSB.
76 */
77
78void e05a30_device::update_printhead(int pos, UINT8 data)
79{
80   if (pos == 0) {
81      m_printhead &= 0x00ff;
82      m_printhead |= (UINT16) !!data << 8;
83   } else {
84      m_printhead &= 0xff00;
85      m_printhead |= data;
86   }
87   m_write_printhead(m_printhead);
88}
89
90/***************************************************************************
91    STEPPER MOTORS
92***************************************************************************/
93
94/* The e05a30 controls two stepper motors:
95 * - The Paper Feed stepper motor is controlled through MMIO 0xC007
96 * - The Carriage Return stepper motor is controlled through MMIO 0xC008
97 * The Carriage Return stepper motor is used throug the SLA7020M driver. It
98 * is therefore necessary to translate the input data from the SLA7020M
99 * format to a format describing the 4 phases of a stepper motor.
100 * For the PF motor, the output data is fed directly to the stepper motor.
101 */
102
103void e05a30_device::update_pf_stepper(UINT8 data)
104{
105   m_pf_stepper = data & 0x0f;
106   m_write_pf_stepper(m_pf_stepper);
107}
108
109static UINT8 cr_sla7020m(UINT8 data)
110{
111   bool ina = BIT(data, 0);
112   bool inb = BIT(data, 1);
113   bool tda = BIT(data, 2);
114   bool tdb = BIT(data, 3);
115   bool outa0 =  ina && tda;
116   bool outa1 = !ina && tda;
117   bool outb0 =  inb && tdb;
118   bool outb1 = !inb && tdb;
119   return (outb1<<3)|(outb0<<2)|(outa1<<1)|(outa0<<0);
120}
121void e05a30_device::update_cr_stepper(UINT8 data)
122{
123   m_cr_stepper = data & 0x0f;
124   m_write_cr_stepper(cr_sla7020m(m_cr_stepper));
125}
126
127
128/***************************************************************************
129    IMPLEMENTATION
130***************************************************************************/
131
132WRITE8_MEMBER( e05a30_device::write )
133{
134   LOG("%s: e05a30_w([0xC0%02x]): %02x\n", space.machine().describe_context(), offset, data);
135
136   switch (offset) {
137   /* printhead */
138   case 0x05: update_printhead(0, data); break;
139   case 0x06: update_printhead(1, data); break;
140   /* paper feed stepper motor */
141   case 0x07: update_pf_stepper(data); break;
142   /* carriage return stepper motor */
143   case 0x08: update_cr_stepper(data); break;
144   }
145}
146
147READ8_MEMBER( e05a30_device::read )
148{
149   UINT8 result = 0;
150
151   LOG("%s: e05a30_r([0xC0%02x]): ", space.machine().describe_context(), offset);
152
153   switch (offset) {
154   /* paper feed stepper motor */
155   case 0x07: result = m_pf_stepper; break;
156   /* carriage return stepper motor */
157   case 0x08: result = m_cr_stepper; break;
158   }
159
160   LOG("0x%02x\n", result);
161
162   return result;
163}
trunk/src/emu/machine/e05a30.h
r241971r241972
1/*
2 * E05A30 Gate Array (used in the Epson ActionPrinter 2000)
3 *
4 * Copyright: 2014 Ramiro Polla
5 * License: BSD-3-Clause
6 */
7
8#ifndef __E05A30_H__
9#define __E05A30_H__
10
11/***************************************************************************
12    DEVICE CONFIGURATION MACROS
13***************************************************************************/
14
15#define MCFG_E05A30_PRINTHEAD_CALLBACK(_write) \
16   devcb = &e05a30_device::set_printhead_wr_callback(*device, DEVCB_##_write);
17
18#define MCFG_E05A30_PF_STEPPER_CALLBACK(_write) \
19   devcb = &e05a30_device::set_pf_stepper_wr_callback(*device, DEVCB_##_write);
20
21#define MCFG_E05A30_CR_STEPPER_CALLBACK(_write) \
22   devcb = &e05a30_device::set_cr_stepper_wr_callback(*device, DEVCB_##_write);
23
24#define MCFG_E05A30_READY_CALLBACK(_write) \
25   devcb = &e05a30_device::set_ready_wr_callback(*device, DEVCB_##_write);
26
27/***************************************************************************
28    TYPE DEFINITIONS
29***************************************************************************/
30
31class e05a30_device : public device_t
32{
33public:
34   e05a30_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
35   ~e05a30_device() {}
36
37   template<class _Object> static devcb_base &set_printhead_wr_callback(device_t &device, _Object object) { return downcast<e05a30_device &>(device).m_write_printhead.set_callback(object); }
38   template<class _Object> static devcb_base &set_pf_stepper_wr_callback(device_t &device, _Object object) { return downcast<e05a30_device &>(device).m_write_pf_stepper.set_callback(object); }
39   template<class _Object> static devcb_base &set_cr_stepper_wr_callback(device_t &device, _Object object) { return downcast<e05a30_device &>(device).m_write_cr_stepper.set_callback(object); }
40   template<class _Object> static devcb_base &set_ready_wr_callback(device_t &device, _Object object) { return downcast<e05a30_device &>(device).m_write_ready.set_callback(object); }
41
42   DECLARE_WRITE8_MEMBER( write );
43   DECLARE_READ8_MEMBER( read );
44
45protected:
46   // device-level overrides
47   virtual void device_start();
48   virtual void device_reset();
49
50private:
51   /* callbacks */
52   devcb_write16 m_write_printhead;
53   devcb_write8 m_write_pf_stepper;
54   devcb_write8 m_write_cr_stepper;
55   devcb_write_line m_write_ready;
56
57   void update_printhead(int pos, UINT8 data);
58   void update_pf_stepper(UINT8 data);
59   void update_cr_stepper(UINT8 data);
60
61   /* port 0x05 and 0x06 (9-bit) */
62   UINT16 m_printhead;
63   /* port 0x07 (4-bit) */
64   UINT8 m_pf_stepper;
65   /* port 0x08 (4-bit) */
66   UINT8 m_cr_stepper;
67};
68
69extern const device_type E05A30;
70
71#endif /* __E05A30_H__ */
trunk/src/emu/machine/i6300esb.c
r241971r241972
3939   AM_RANGE(0x88, 0x8b) AM_READWRITE8 (d31_err_cfg_r,          d31_err_cfg_w,          0x000000ff)
4040   AM_RANGE(0x88, 0x8b) AM_READWRITE8 (d31_err_sts_r,          d31_err_sts_w,          0x00ff0000)
4141   AM_RANGE(0x90, 0x93) AM_READWRITE16(pci_dma_cfg_r,          pci_dma_cfg_w,          0x0000ffff)
42   AM_RANGE(0xa0, 0xa3) AM_READWRITE16(gen_pmcon_1_r,          gen_pmcon_1_w,          0x0000ffff)
43   AM_RANGE(0xa0, 0xa3) AM_READWRITE16(gen_pmcon_2_r,          gen_pmcon_2_w,          0xffff0000)
44   AM_RANGE(0xa4, 0xa7) AM_READWRITE8 (gen_pmcon_3_r,          gen_pmcon_3_w,          0x000000ff)
45   AM_RANGE(0xac, 0xaf) AM_READWRITE  (rst_cnt2_r,             rst_cnt2_w)
46   AM_RANGE(0xb0, 0xb3) AM_READWRITE8 (apm_cnt_r,              apm_cnt_w,              0x00ff0000)
47   AM_RANGE(0xb0, 0xb3) AM_READWRITE8 (apm_sts_r,              apm_sts_w,              0xff000000)
48   AM_RANGE(0xb8, 0xbb) AM_READWRITE  (gpi_rout_r,             gpi_rout_w)
49   AM_RANGE(0xc0, 0xc3) AM_READWRITE8 (mon_fwd_en_r,           mon_fwd_en_w,           0x000000ff)
50   AM_RANGE(0xc4, 0xcb) AM_READWRITE16(mon_trp_rng_r,          mon_trp_rng_w,          0xffffffff)
51   AM_RANGE(0xcc, 0xcf) AM_READWRITE16(mon_trp_msk_r,          mon_trp_msk_w,          0x0000ffff)
5242   AM_RANGE(0xd0, 0xd3) AM_READWRITE  (gen_cntl_r,             gen_cntl_w)
5343   AM_RANGE(0xd4, 0xd7) AM_READWRITE8 (gen_sta_r,              gen_sta_w,              0x000000ff)
5444   AM_RANGE(0xd4, 0xd7) AM_READWRITE8 (back_cntl_r,            back_cntl_w,            0x0000ff00)
r241971r241972
10696   etr1 = 0x00000000;
10797   siu_config_port = 0;
10898   siu_config_state = 0;
109   gen_pmcon_1 = 0;
110   gen_pmcon_2 = 0;
111   gen_pmcon_3 = 0;
112   rst_cnt2 = 0;
113   apm_cnt = 0;
114   apm_sts = 0;
115   gpi_rout = 0;
116   mon_fwd_en = 0;
117   memset(mon_trp_rng, 0, sizeof(mon_trp_rng));
118   mon_trp_msk = 0;
11999}
120100
121101void i6300esb_lpc_device::reset_all_mappings()
r241971r241972
276256   logerror("%s: pci_dma_cfg = %04x\n", tag(), pci_dma_cfg);
277257}
278258
279READ16_MEMBER (i6300esb_lpc_device::gen_pmcon_1_r)
280{
281   return gen_pmcon_1;
282}
283
284WRITE16_MEMBER(i6300esb_lpc_device::gen_pmcon_1_w)
285{
286   COMBINE_DATA(&gen_pmcon_1);
287   logerror("%s: gen_pmcon_1 = %04x\n", tag(), gen_pmcon_1);
288}
289
290READ16_MEMBER (i6300esb_lpc_device::gen_pmcon_2_r)
291{
292   return gen_pmcon_2;
293}
294
295WRITE16_MEMBER(i6300esb_lpc_device::gen_pmcon_2_w)
296{
297   COMBINE_DATA(&gen_pmcon_2);
298   logerror("%s: gen_pmcon_2 = %04x\n", tag(), gen_pmcon_2);
299}
300
301READ8_MEMBER  (i6300esb_lpc_device::gen_pmcon_3_r)
302{
303   return gen_pmcon_3;
304}
305
306WRITE8_MEMBER (i6300esb_lpc_device::gen_pmcon_3_w)
307{
308   gen_pmcon_3 = data;
309   logerror("%s: gen_pmcon_3 = %02x\n", tag(), gen_pmcon_3);
310}
311
312READ32_MEMBER (i6300esb_lpc_device::rst_cnt2_r)
313{
314   return rst_cnt2;
315}
316
317WRITE32_MEMBER(i6300esb_lpc_device::rst_cnt2_w)
318{
319   COMBINE_DATA(&rst_cnt2);
320   logerror("%s: rst_cnt2 = %08x\n", tag(), rst_cnt2);
321}
322
323READ8_MEMBER  (i6300esb_lpc_device::apm_cnt_r)
324{
325   return apm_cnt;
326}
327
328WRITE8_MEMBER (i6300esb_lpc_device::apm_cnt_w)
329{
330   apm_cnt = data;
331   logerror("%s: apm_cnt = %02x\n", tag(), apm_cnt);
332}
333
334READ8_MEMBER  (i6300esb_lpc_device::apm_sts_r)
335{
336   return apm_sts;
337}
338
339WRITE8_MEMBER (i6300esb_lpc_device::apm_sts_w)
340{
341   apm_sts = data;
342   logerror("%s: apm_sts = %02x\n", tag(), apm_sts);
343}
344
345READ32_MEMBER (i6300esb_lpc_device::gpi_rout_r)
346{
347   return gpi_rout;
348}
349
350WRITE32_MEMBER(i6300esb_lpc_device::gpi_rout_w)
351{
352   COMBINE_DATA(&gpi_rout);
353   logerror("%s: gpi_rout = %08x\n", tag(), gpi_rout);
354}
355
356READ8_MEMBER  (i6300esb_lpc_device::mon_fwd_en_r)
357{
358   return mon_fwd_en;
359}
360
361WRITE8_MEMBER (i6300esb_lpc_device::mon_fwd_en_w)
362{
363   mon_fwd_en = data;
364   logerror("%s: mon_fwd_en = %02x\n", tag(), mon_fwd_en);
365}
366
367READ16_MEMBER (i6300esb_lpc_device::mon_trp_rng_r)
368{
369   return mon_trp_rng[offset];
370}
371
372WRITE16_MEMBER(i6300esb_lpc_device::mon_trp_rng_w)
373{
374   COMBINE_DATA(&mon_trp_rng[offset]);
375   logerror("%s: mon_trp_rng[%d] = %04x\n", tag(), 4+offset, mon_trp_rng[offset]);
376}
377
378READ16_MEMBER (i6300esb_lpc_device::mon_trp_msk_r)
379{
380   return mon_trp_msk;
381}
382
383WRITE16_MEMBER(i6300esb_lpc_device::mon_trp_msk_w)
384{
385   COMBINE_DATA(&mon_trp_msk);
386   logerror("%s: mon_trp_msk = %04x\n", tag(), mon_trp_msk);
387}
388
389259READ32_MEMBER (i6300esb_lpc_device::gen_cntl_r)
390260{
391261   return gen_cntl;
trunk/src/emu/machine/i6300esb.h
r241971r241972
2929private:
3030   DECLARE_ADDRESS_MAP(internal_io_map, 32);
3131
32   UINT32 pmbase, gpio_base, fwh_sel1, gen_cntl, etr1, rst_cnt2, gpi_rout;
33   UINT16 bios_cntl, pci_dma_cfg, gen1_dec, lpc_en, gen2_dec, fwh_sel2, func_dis, gen_pmcon_1, gen_pmcon_2;
34   UINT16 mon_trp_rng[4], mon_trp_msk;
32   UINT32 pmbase, gpio_base, fwh_sel1, gen_cntl, etr1;
33   UINT16 bios_cntl, pci_dma_cfg, gen1_dec, lpc_en, gen2_dec, fwh_sel2, func_dis;
3534   UINT8 pirq_rout[8];
3635   UINT8 acpi_cntl, tco_cntl, gpio_cntl, serirq_cntl, d31_err_cfg, d31_err_sts, gen_sta, back_cntl, rtc_conf;
3736   UINT8 lpc_if_com_range, lpc_if_fdd_lpt_range, lpc_if_sound_range, fwh_dec_en1, fwh_dec_en2, siu_config_port;
38   UINT8 gen_pmcon_3, apm_cnt, apm_sts, mon_fwd_en;
3937   int siu_config_state;
4038
4139   DECLARE_WRITE8_MEMBER (nop_w);
r241971r241972
6563   DECLARE_WRITE8_MEMBER (d31_err_sts_w);
6664   DECLARE_READ16_MEMBER (pci_dma_cfg_r);          // 90
6765   DECLARE_WRITE16_MEMBER(pci_dma_cfg_w);
68   DECLARE_READ16_MEMBER (gen_pmcon_1_r);          // a0
69   DECLARE_WRITE16_MEMBER(gen_pmcon_1_w);
70   DECLARE_READ16_MEMBER (gen_pmcon_2_r);          // a2
71   DECLARE_WRITE16_MEMBER(gen_pmcon_2_w);
72   DECLARE_READ8_MEMBER  (gen_pmcon_3_r);          // a4
73   DECLARE_WRITE8_MEMBER (gen_pmcon_3_w);
74   DECLARE_READ32_MEMBER (rst_cnt2_r);             // ac
75   DECLARE_WRITE32_MEMBER(rst_cnt2_w);
76   DECLARE_READ8_MEMBER  (apm_cnt_r);              // b2
77   DECLARE_WRITE8_MEMBER (apm_cnt_w);
78   DECLARE_READ8_MEMBER  (apm_sts_r);              // b3
79   DECLARE_WRITE8_MEMBER (apm_sts_w);
80   DECLARE_READ32_MEMBER (gpi_rout_r);             // b8
81   DECLARE_WRITE32_MEMBER(gpi_rout_w);
82   DECLARE_READ8_MEMBER  (mon_fwd_en_r);           // c0
83   DECLARE_WRITE8_MEMBER (mon_fwd_en_w);
84   DECLARE_READ16_MEMBER (mon_trp_rng_r);          // c4-ca
85   DECLARE_WRITE16_MEMBER(mon_trp_rng_w);
86   DECLARE_READ16_MEMBER (mon_trp_msk_r);          // cc
87   DECLARE_WRITE16_MEMBER(mon_trp_msk_w);
8866   DECLARE_READ32_MEMBER (gen_cntl_r);             // d0
8967   DECLARE_WRITE32_MEMBER(gen_cntl_w);
9068   DECLARE_READ8_MEMBER  (gen_sta_r);              // d4
trunk/src/emu/machine/machine.mak
r241971r241972
521521
522522#-------------------------------------------------
523523#
524#@src/emu/machine/e05a30.h,MACHINES += E05A30
525#-------------------------------------------------
526
527ifneq ($(filter E05A30,$(MACHINES)),)
528MACHINEOBJS += $(MACHINEOBJ)/e05a30.o
529endif
530
531#-------------------------------------------------
532#
533524#@src/emu/machine/eeprom.h,MACHINES += EEPROMDEV
534525#@src/emu/machine/eepromser.h,MACHINES += EEPROMDEV
535526#@src/emu/machine/eeprompar.h,MACHINES += EEPROMDEV
r241971r241972
19011892
19021893#-------------------------------------------------
19031894#
1904#@src/emu/machine/steppers.h,MACHINES += STEPPERS
1905#-------------------------------------------------
1906
1907ifneq ($(filter STEPPERS,$(MACHINES)),)
1908MACHINEOBJS += $(MACHINEOBJ)/steppers.o
1909endif
1910
1911#-------------------------------------------------
1912#
19131895#@src/emu/machine/corvushd.h,MACHINES += CORVUSHD
19141896#-------------------------------------------------
19151897ifneq ($(filter CORVUSHD,$(MACHINES)),)
trunk/src/emu/machine/steppers.c
r241971r241972
1///////////////////////////////////////////////////////////////////////////
2//                                                                       //
3// steppers.c steppermotor emulation                                     //
4//                                                                       //
5// Emulates : Stepper motors driven with full step or half step          //
6//            also emulates the index optic                              //
7//                                                                       //
8// 26-05-2012: J. Wallace - Implemented proper phase alignment, we no    //
9//                          longer need reverse interfaces here, the     //
10//                          layout will suffice. Added belt reel handler.//
11// 09-04-2012: J. Wallace - Studied some old reel motors and added a     //
12//                          number of new stepper types. I am yet to     //
13//                          add them to drivers, but barring some init   //
14//                          stuff, they should work.                     //
15// 15-01-2012: J. Wallace - Total internal rewrite to remove the table   //
16//                          hoodoo that stops anyone but me actually     //
17//                          updating this. In theory, we should be able  //
18//                          to adapt the phase code to any reel type by  //
19//                          studying a game's startup                    //
20//                          Documentation is much better now.            //
21// 04-04-2011: J. Wallace - Added reverse spin (this is necessary for    //
22//                          accuracy), and improved wraparound logic     //
23//    03-2011:              New 2D array to remove reel bounce and       //
24//                          make more realistic                          //
25// 26-01-2007: J. Wallace - Rewritten to make it more flexible           //
26//                          and to allow indices to be set in drivers    //
27// 29-12-2006: J. Wallace - Added state save support                     //
28// 05-03-2004: Re-Animator                                               //
29//                                                                       //
30// TODO:  add further types of stepper motors if needed (Konami/IGT?)    //
31//        Someone who understands the device system may want to convert  //
32//        this                                                           //
33//        200 Step reels can alter their relative opto tab position,     //
34//        may be worth adding the phase setting to the interface         //
35//        There are reports that some games use a pulse that is too short//
36//        to give a 'judder' effect for holds, etc. We'll need to time   //
37//        the pulses to keep tack of this without going out of sync.     //
38//        Check 20RM and Starpoint 200 step                              //
39///////////////////////////////////////////////////////////////////////////
40
41#include "emu.h"
42#include "steppers.h"
43
44/* local prototypes */
45
46static void update_optic(int which);
47
48/* local vars */
49
50struct stepper
51{
52   const stepper_interface *intf;
53   UINT8    pattern,   /* coil pattern */
54         old_pattern,    /* old coil pattern */
55         initphase,
56            phase,  /* motor phase */
57         old_phase,  /* old phase */
58            type;   /* reel type */
59   INT16   step_pos,   /* step position 0 - max_steps */
60         max_steps;  /* maximum step position */
61   INT32   abs_step_pos; /* absolute step position */
62
63   INT16 index_start,  /* start position of index (in half steps) */
64         index_end,  /* end position of index (in half steps) */
65         index_patt; /* pattern needed on coils (0=don't care) */
66
67   UINT8 optic;
68};
69
70static stepper step[MAX_STEPPERS];
71
72/* useful interfaces (Starpoint is a very common setup)*/
73const stepper_interface starpoint_interface_48step =
74{
75   STARPOINT_48STEP_REEL,
76   1,
77   3,
78   0x09,
79   4
80};
81
82const stepper_interface starpointrm20_interface_48step =
83{
84   STARPOINT_48STEP_REEL,
85   16,
86   24,
87   0x09,
88   7
89};
90const stepper_interface starpoint_interface_200step_reel =
91{
92   STARPOINT_200STEP_REEL,
93   12,
94   24,
95   0x09,
96   7
97};
98// guess
99const stepper_interface ecoin_interface_200step_reel =
100{
101   ECOIN_200STEP_REEL,
102   12,
103   24,
104   0x09,
105   7
106};
107
108
109
110///////////////////////////////////////////////////////////////////////////
111void stepper_config(running_machine &machine, int which, const stepper_interface *intf)
112{
113   assert_always(machine.phase() == MACHINE_PHASE_INIT, "Can only call stepper_config at init time!");
114   assert_always((which >= 0) && (which < MAX_STEPPERS), "stepper_config called on an invalid stepper motor!");
115   assert_always(intf, "stepper_config called with an invalid interface!");
116
117   step[which].intf = intf;
118
119   step[which].type = intf->type;
120   step[which].index_start = intf->index_start;/* location of first index value in half steps */
121   step[which].index_end   = intf->index_end;  /* location of last index value in half steps */
122   step[which].index_patt  = intf->index_patt; /* hex value of coil pattern (0 if not needed)*/
123   step[which].initphase   = intf->initphase; /* Phase at 0 steps, for alignment) */
124
125
126   step[which].pattern     = 0;
127   step[which].old_pattern = 0;
128   step[which].step_pos    = 0;
129   step[which].abs_step_pos= 0;
130   step[which].phase = step[which].initphase;
131   step[which].old_phase = step[which].initphase;
132
133
134   switch ( step[which].type )
135   {   default:
136      case STARPOINT_48STEP_REEL:  /* STARPOINT RMxxx */
137      case BARCREST_48STEP_REEL :  /* Barcrest Reel unit */
138      case MPU3_48STEP_REEL :
139      case GAMESMAN_48STEP_REEL :  /* Gamesman GMxxxx */
140      case PROJECT_48STEP_REEL :
141      step[which].max_steps = (48*2);
142      break;
143      case GAMESMAN_100STEP_REEL :
144      step[which].max_steps = (100*2);
145      break;
146      case STARPOINT_144STEP_DICE :/* STARPOINT 1DCU DICE mechanism */
147      //Dice reels are 48 step motors, but complete three full cycles between opto updates
148      step[which].max_steps = ((48*3)*2);
149      break;
150      case STARPOINT_200STEP_REEL :
151      case GAMESMAN_200STEP_REEL :
152      case ECOIN_200STEP_REEL :
153      step[which].max_steps = (200*2);
154      break;
155   }
156
157   state_save_register_item(machine, "stepper", NULL, which, step[which].index_start);
158   state_save_register_item(machine, "stepper", NULL, which, step[which].index_end);
159   state_save_register_item(machine, "stepper", NULL, which, step[which].index_patt);
160   state_save_register_item(machine, "stepper", NULL, which, step[which].initphase);
161   state_save_register_item(machine, "stepper", NULL, which, step[which].phase);
162   state_save_register_item(machine, "stepper", NULL, which, step[which].old_phase);
163   state_save_register_item(machine, "stepper", NULL, which, step[which].pattern);
164   state_save_register_item(machine, "stepper", NULL, which, step[which].old_pattern);
165   state_save_register_item(machine, "stepper", NULL, which, step[which].step_pos);
166   state_save_register_item(machine, "stepper", NULL, which, step[which].abs_step_pos);
167   state_save_register_item(machine, "stepper", NULL, which, step[which].max_steps);
168   state_save_register_item(machine, "stepper", NULL, which, step[which].type);
169}
170
171///////////////////////////////////////////////////////////////////////////
172int stepper_get_position(int which)
173{
174   return step[which].step_pos;
175}
176
177///////////////////////////////////////////////////////////////////////////
178int stepper_get_absolute_position(int which)
179{
180   return step[which].abs_step_pos;
181}
182
183///////////////////////////////////////////////////////////////////////////
184
185int stepper_get_max(int which)
186{
187   return step[which].max_steps;
188}
189
190///////////////////////////////////////////////////////////////////////////
191
192static void update_optic(int which)
193{
194   int pos   = step[which].step_pos,
195      start = step[which].index_start,
196      end = step[which].index_end;
197
198   if (start > end) // cope with index patterns that wrap around
199   {
200      if ( (( pos > start ) || ( pos < end )) &&
201      ( ( step[which].pattern == step[which].index_patt || step[which].index_patt==0) ||
202      ( step[which].pattern == 0 &&
203      (step[which].old_pattern == step[which].index_patt || step[which].index_patt==0)
204      ) ) )
205      {
206         step[which].optic = 1;
207      }
208      else step[which].optic = 0;
209      }
210   else
211   {
212      if ( (( pos > start ) && ( pos < end )) &&
213      ( ( step[which].pattern == step[which].index_patt || step[which].index_patt==0) ||
214      ( step[which].pattern == 0 &&
215      (step[which].old_pattern == step[which].index_patt || step[which].index_patt==0)
216      ) ) )
217      {
218      step[which].optic = 1;
219      }
220      else step[which].optic = 0;
221   }
222}
223///////////////////////////////////////////////////////////////////////////
224
225void stepper_reset_position(int which)
226{
227   step[which].step_pos    = 0x00;
228   step[which].abs_step_pos= 0x00;
229   step[which].pattern     = 0x00;
230   step[which].old_pattern = 0x00;
231   step[which].phase = step[which].initphase;
232   step[which].old_phase = step[which].initphase;
233   update_optic(which);
234}
235
236///////////////////////////////////////////////////////////////////////////
237
238int stepper_optic_state(int which)
239{
240   int result = 0;
241
242   if ( which < MAX_STEPPERS )
243   {
244      result = step[which].optic;
245   }
246
247   return result;
248}
249
250///////////////////////////////////////////////////////////////////////////
251
252int stepper_update(int which, UINT8 pattern)
253{
254   int changed = 0;
255
256   /* This code probably makes more sense if you visualise what is being emulated, namely
257   a spinning drum with two electromagnets inside. Essentially, the CPU
258   activates a pair of windings on these magnets leads as necessary to attract and repel the drum to pull it round and
259   display as appropriate. To attempt to visualise the rotation effect, take a look at the compass rose below, representing a side on view of the reel,
260   the numbers indicate the phase information as used
261
262       7
263       N
264   1 W   E 5
265       S
266       3
267
268   For sake of accuracy, we're representing all possible phases of the motor, effectively moving the motor one half step at a time, so a 48 step motor becomes
269   96 half steps. This is necessary because of some programs running the wiring in series with a distinct delay between the pair being completed. This causes
270   a small movement that may trigger the optic tab.
271   */
272
273   int pos,steps=0;
274   step[which].pattern = pattern;
275   switch ( step[which].type )
276   {
277      default:
278      logerror("No reel type specified for %x!\n",which);
279      break;
280      case STARPOINT_48STEP_REEL : /* STARPOINT RMxxx */
281      case GAMESMAN_200STEP_REEL : /* Gamesman GMxxxx */
282      case STARPOINT_144STEP_DICE :/* STARPOINT 1DCU DICE mechanism */
283      case STARPOINT_200STEP_REEL :/* STARPOINT 1DCU DICE mechanism */
284      //Standard drive table is 2,6,4,5,1,9,8,a
285      //NOTE: This runs through the stator patterns in such a way as to drive the reel forward (downwards from the player's view, clockwise on our rose)
286      //The Heber 'Pluto' controller runs this in reverse
287      switch (pattern)
288      {             //Black  Blue  Red  Yellow
289         case 0x02://  0     0     1     0
290         step[which].phase = 7;
291         break;
292         case 0x06://  0     1     1     0
293         step[which].phase = 6;
294         break;
295         case 0x04://  0     1     0     0
296         step[which].phase = 5;
297         break;
298         case 0x05://  0     1     0     1
299         step[which].phase = 4;
300         break;
301         case 0x01://  0     0     0     1
302         step[which].phase = 3;
303         break;
304         case 0x09://  1     0     0     1
305         step[which].phase = 2;
306         break;
307         case 0x08://  1     0     0     0
308         step[which].phase = 1;
309         break;
310         case 0x0A://  1     0     1     0
311         step[which].phase = 0;
312         break;
313         //          Black  Blue  Red  Yellow
314         case 0x03://  0     0     1     1
315         {
316            if ((step[which].old_phase ==6)||(step[which].old_phase == 0)) // if the previous pattern had the drum in the northern quadrant, it will point north now
317            {
318               step[which].phase = 7;
319            }
320            else //otherwise it will line up due south
321            {
322               step[which].phase = 3;
323            }
324         }
325         break;
326         case 0x0C://  1     1     0     0
327         {
328            if ((step[which].old_phase ==6)||(step[which].old_phase == 4)) // if the previous pattern had the drum in the eastern quadrant, it will point east now
329            {
330               step[which].phase = 5;
331            }
332            else //otherwise it will line up due west
333            {
334               step[which].phase = 1;
335            }
336         }
337         break;
338      }
339      break;
340
341      case BARCREST_48STEP_REEL :
342      case GAMESMAN_48STEP_REEL :
343      case GAMESMAN_100STEP_REEL :
344      //Standard drive table is 1,3,2,6,4,C,8,9
345      //Gamesman 48 step uses this pattern shifted one place forward, though this shouldn't matter
346      switch (pattern)
347      {
348         //             Yellow   Brown  Orange Black
349         case 0x01://  0        0      0      1
350         step[which].phase = 7;
351         break;
352         case 0x03://  0        0      1      1
353         step[which].phase = 6;
354         break;
355         case 0x02://  0        0      1      0
356         step[which].phase = 5;
357         break;
358         case 0x06://  0        1      1      0
359         step[which].phase = 4;
360         break;
361         case 0x04://  0        1      0      0
362         step[which].phase = 3;
363         break;
364         case 0x0C://  1        1      0      0
365         step[which].phase = 2;
366         break;
367         case 0x08://  1        0      0      0
368         step[which].phase = 1;
369         break;//YOLB
370         case 0x09://  1        0      0      1
371         step[which].phase = 0;
372         break;
373
374         // The below values should not be used by anything sane, as they effectively ignore one stator side entirely
375         //          Yellow   Brown  Orange Black
376         case 0x05://   0       1       0     1
377         {
378            if ((step[which].old_phase ==6)||(step[which].old_phase == 0)) // if the previous pattern had the drum in the northern quadrant, it will point north now
379            {
380               step[which].phase = 7;
381            }
382            else //otherwise it will line up due south
383            {
384               step[which].phase = 3;
385            }
386         }
387         break;
388
389         case 0x0A://   1       0       1     0
390         {
391            if ((step[which].old_phase ==6)||(step[which].old_phase == 4)) // if the previous pattern had the drum in the eastern quadrant, it will point east now
392            {
393               step[which].phase = 5;
394            }
395            else //otherwise it will line up due west
396            {
397               step[which].phase = 1;
398            }
399         }
400         break;
401      }
402      break;
403
404      case MPU3_48STEP_REEL :
405      /* The MPU3 interface is actually the same as the MPU4 setup, but with two active lines instead of four
406         Inverters are used so if a pin is low, the higher bit of the pair is activated, and if high the lower bit is activated.
407         TODO:Check this, 2 and 1 could be switched over.
408       */
409      switch (pattern)
410      {
411      //             Yellow(2)   Brown(1)  Orange(!2) Black(!1)
412         case 0x00 :// 0          0          1         1
413         step[which].phase = 6;
414         break;
415         case 0x01 :// 0          1          1         0
416         step[which].phase = 4;
417         break;
418         case 0x03 :// 1          1          0         0
419         step[which].phase = 2;
420         break;
421         case 0x02 :// 1          0          0         1
422         step[which].phase = 0;
423         break;
424      }
425      break;
426
427      case ECOIN_200STEP_REEL :
428      //While the 48 and 100 step models appear to be reverse driven Starpoint reels, the 200 step model seems bespoke, certainly in terms of wiring.
429      //On a Proconn machine this same pattern is seen but running in reverse
430      //Standard drive table is 8,c,4,6,2,3,1,9
431      switch (pattern)
432      {
433         case 0x08://  0     0     1     0
434         step[which].phase = 7;
435         break;
436         case 0x0c://  0     1     1     0
437         step[which].phase = 6;
438         break;
439         case 0x04://  0     1     0     0
440         step[which].phase = 5;
441         break;
442         case 0x06://  0     1     0     1
443         step[which].phase = 4;
444         break;
445         case 0x02://  0     0     0     1
446         step[which].phase = 3;
447         break;
448         case 0x03://  1     0     0     1
449         step[which].phase = 2;
450         break;
451         case 0x01://  1     0     0     0
452         step[which].phase = 1;
453         break;
454         case 0x09://  1     0     1     0
455         step[which].phase = 0;
456         break;
457         case 0x0a://  0     0     1     1
458         {
459            if ((step[which].old_phase ==6)||(step[which].old_phase == 0)) // if the previous pattern had the drum in the northern quadrant, it will point north now
460            {
461               step[which].phase = 7;
462            }
463            else //otherwise it will line up due south
464            {
465               step[which].phase = 3;
466            }
467         }
468         break;
469         case 0x07://  1     1     0     0
470         {
471            if ((step[which].old_phase ==6)||(step[which].old_phase == 4)) // if the previous pattern had the drum in the eastern quadrant, it will point east now
472            {
473               step[which].phase = 5;
474            }
475            else //otherwise it will line up due west
476            {
477               step[which].phase = 1;
478            }
479         }
480         break;
481      }
482      break;
483
484      case PROJECT_48STEP_REEL :
485      //Standard drive table is 8,c,4,5,1,3,2,a
486      //This appears to be basically a rewired Gamesman (the reel PCB looks like it does some shuffling)
487      //TODO: Not sure if this should be represented as a type here, or by defining it as a Gamesman in the driver and bitswapping.
488      switch (pattern)
489      {
490         case 0x08://  0     0     1     0
491         step[which].phase = 7;
492         break;
493         case 0x0c://  0     1     1     0
494         step[which].phase = 6;
495         break;
496         case 0x04://  0     1     0     0
497         step[which].phase = 5;
498         break;
499         case 0x05://  0     1     0     1
500         step[which].phase = 4;
501         break;
502         case 0x01://  0     0     0     1
503         step[which].phase = 3;
504         break;
505         case 0x03://  1     0     0     1
506         step[which].phase = 2;
507         break;
508         case 0x02://  1     0     0     0
509         step[which].phase = 1;
510         break;
511         case 0x0a://  1     0     1     0
512         step[which].phase = 0;
513         break;
514         case 0x09://  0     0     1     1
515         {
516            if ((step[which].old_phase ==6)||(step[which].old_phase == 0)) // if the previous pattern had the drum in the northern quadrant, it will point north now
517            {
518               step[which].phase = 7;
519            }
520            else //otherwise it will line up due south
521            {
522               step[which].phase = 3;
523            }
524         }
525         break;
526         case 0x06://  1     1     0     0
527         {
528            if ((step[which].old_phase ==6)||(step[which].old_phase == 4)) // if the previous pattern had the drum in the eastern quadrant, it will point east now
529            {
530               step[which].phase = 5;
531            }
532            else //otherwise it will line up due west
533            {
534               step[which].phase = 1;
535            }
536         }
537         break;
538      }
539      break;
540
541
542
543   }
544
545   steps = step[which].old_phase - step[which].phase;
546
547   if (steps < -4)
548   {
549      steps = steps +8;
550   }
551   if (steps > 4)
552   {
553      steps = steps -8;
554   }
555
556   step[which].old_phase = step[which].phase;
557   step[which].old_pattern = step[which].pattern;
558
559   int max = step[which].max_steps;
560   pos = 0;
561
562   if (max!=0)
563   {
564      step[which].abs_step_pos += steps;
565      pos = (step[which].step_pos + steps + max) % max;
566   }
567   else
568   {
569      logerror("step[%x].max_steps == 0\n",which);
570   }
571
572   if (pos != step[which].step_pos)
573   {
574      changed++;
575   }
576
577   step[which].step_pos = pos;
578   update_optic(which);
579
580   return changed;
581}
trunk/src/emu/machine/steppers.h
r241971r241972
1///////////////////////////////////////////////////////////////////////////
2//                                                                       //
3// steppers.c steppermotor emulation                                     //
4//                                                                       //
5// Emulates : stepper motors driven with full step or half step          //
6//            also emulates the index optic                              //
7//                                                                       //
8//                                                                       //
9// TODO:  add further types of stepper motors if needed (Konami/IGT?)    //
10//        Someone who understands the device system may want to convert  //
11//        this                                                           //
12///////////////////////////////////////////////////////////////////////////
13
14
15#ifndef INC_STEPPERS
16#define INC_STEPPERS
17
18#define MAX_STEPPERS            8           /* maximum number of steppers */
19
20#define STARPOINT_48STEP_REEL   0           /* STARPOINT RMXXX reel unit */
21#define STARPOINT_144STEP_DICE  1           /* STARPOINT 1DCU DICE mechanism */
22#define STARPOINT_200STEP_REEL  2
23
24#define BARCREST_48STEP_REEL    3           /* Barcrest bespoke reel unit */
25#define MPU3_48STEP_REEL        4
26
27#define ECOIN_200STEP_REEL      5           /* Probably not bespoke, but can't find a part number */
28
29#define GAMESMAN_48STEP_REEL    6
30#define GAMESMAN_100STEP_REEL   7
31#define GAMESMAN_200STEP_REEL   8
32
33#define PROJECT_48STEP_REEL     9
34
35/*------------- Stepper motor interface structure -----------------*/
36
37struct stepper_interface
38{
39   UINT8 type; /* Reel unit type */
40   INT16 index_start;/* start position of index (in half steps) */
41   INT16 index_end;  /* end position of index (in half steps) */
42   INT16 index_patt; /* pattern needed on coils (0=don't care) */
43   UINT8 initphase; /* Phase at 0, for opto linkage */
44};
45
46extern const stepper_interface starpoint_interface_48step;
47extern const stepper_interface starpointrm20_interface_48step;
48
49extern const stepper_interface starpoint_interface_200step_reel;
50extern const stepper_interface ecoin_interface_200step_reel;
51
52void stepper_config(running_machine &machine, int which, const stepper_interface *intf);
53
54void stepper_reset_position(int id);        /* reset a motor to position 0 */
55
56int  stepper_optic_state(   int id);        /* read a motor's optics */
57
58int  stepper_update(int id, UINT8 pattern); /* update a motor */
59
60int  stepper_get_position(int id);          /* get current position in half steps */
61
62int  stepper_get_absolute_position(int id); /* get current absolute position in half steps */
63
64int  stepper_get_max(int id);               /* get maximum position in half steps */
65#endif
trunk/src/mame/drivers/sauro.c
r241971r241972
585585
586586GAME( 1987, sauro,    0,        sauro,    tecfri, sauro_state,    tecfri, ROT0, "Tecfri",                                "Sauro", 0 )
587587GAME( 1987, saurop,   sauro,    sauro,    tecfri, sauro_state,    tecfri, ROT0, "Tecfri (Philko license)",               "Sauro (Philko license)", 0 )
588GAME( 1987, saurorr,  sauro,    sauro,    tecfri, sauro_state,    tecfri, ROT0, "Tecfri (Recreativos Real S.A. license)","Sauro (Recreativos Real S.A. license)", 0 )
588GAME( 1987, saurorr,  sauro,    sauro,    tecfri, sauro_state,    tecfri, ROT0, "Tecfri (Recreativo Real S.A. license)", "Sauro (Recreativo Real S.A. license)", 0 )
589589
590590GAME( 1987, trckydoc, 0,        trckydoc, tecfri, sauro_state,    tecfri, ROT0, "Tecfri", "Tricky Doc (set 1)", 0 )
591591GAME( 1987, trckydoca,trckydoc, trckydoc, trckydoca, sauro_state, tecfri, ROT0, "Tecfri", "Tricky Doc (set 2)", 0 )
trunk/src/mame/machine/steppers.c
r0r241972
1///////////////////////////////////////////////////////////////////////////
2//                                                                       //
3// steppers.c steppermotor emulation                                     //
4//                                                                       //
5// Emulates : Stepper motors driven with full step or half step          //
6//            also emulates the index optic                              //
7//                                                                       //
8// 26-05-2012: J. Wallace - Implemented proper phase alignment, we no    //
9//                          longer need reverse interfaces here, the     //
10//                          layout will suffice. Added belt reel handler.//
11// 09-04-2012: J. Wallace - Studied some old reel motors and added a     //
12//                          number of new stepper types. I am yet to     //
13//                          add them to drivers, but barring some init   //
14//                          stuff, they should work.                     //
15// 15-01-2012: J. Wallace - Total internal rewrite to remove the table   //
16//                          hoodoo that stops anyone but me actually     //
17//                          updating this. In theory, we should be able  //
18//                          to adapt the phase code to any reel type by  //
19//                          studying a game's startup                    //
20//                          Documentation is much better now.            //
21// 04-04-2011: J. Wallace - Added reverse spin (this is necessary for    //
22//                          accuracy), and improved wraparound logic     //
23//    03-2011:              New 2D array to remove reel bounce and       //
24//                          make more realistic                          //
25// 26-01-2007: J. Wallace - Rewritten to make it more flexible           //
26//                          and to allow indices to be set in drivers    //
27// 29-12-2006: J. Wallace - Added state save support                     //
28// 05-03-2004: Re-Animator                                               //
29//                                                                       //
30// TODO:  add further types of stepper motors if needed (Konami/IGT?)    //
31//        Someone who understands the device system may want to convert  //
32//        this                                                           //
33//        200 Step reels can alter their relative opto tab position,     //
34//        may be worth adding the phase setting to the interface         //
35//        There are reports that some games use a pulse that is too short//
36//        to give a 'judder' effect for holds, etc. We'll need to time   //
37//        the pulses to keep tack of this without going out of sync.     //
38//        Check 20RM and Starpoint 200 step                              //
39///////////////////////////////////////////////////////////////////////////
40
41#include "emu.h"
42#include "steppers.h"
43
44/* local prototypes */
45
46static void update_optic(int which);
47
48/* local vars */
49
50struct stepper
51{
52   const stepper_interface *intf;
53   UINT8    pattern,   /* coil pattern */
54         old_pattern,    /* old coil pattern */
55         initphase,
56            phase,  /* motor phase */
57         old_phase,  /* old phase */
58            type;   /* reel type */
59   INT16   step_pos,   /* step position 0 - max_steps */
60         max_steps;  /* maximum step position */
61   INT32   abs_step_pos; /* absolute step position */
62
63   INT16 index_start,  /* start position of index (in half steps) */
64         index_end,  /* end position of index (in half steps) */
65         index_patt; /* pattern needed on coils (0=don't care) */
66
67   UINT8 optic;
68};
69
70static stepper step[MAX_STEPPERS];
71
72/* useful interfaces (Starpoint is a very common setup)*/
73const stepper_interface starpoint_interface_48step =
74{
75   STARPOINT_48STEP_REEL,
76   1,
77   3,
78   0x09,
79   4
80};
81
82const stepper_interface starpointrm20_interface_48step =
83{
84   STARPOINT_48STEP_REEL,
85   16,
86   24,
87   0x09,
88   7
89};
90const stepper_interface starpoint_interface_200step_reel =
91{
92   STARPOINT_200STEP_REEL,
93   12,
94   24,
95   0x09,
96   7
97};
98// guess
99const stepper_interface ecoin_interface_200step_reel =
100{
101   ECOIN_200STEP_REEL,
102   12,
103   24,
104   0x09,
105   7
106};
107
108
109
110///////////////////////////////////////////////////////////////////////////
111void stepper_config(running_machine &machine, int which, const stepper_interface *intf)
112{
113   assert_always(machine.phase() == MACHINE_PHASE_INIT, "Can only call stepper_config at init time!");
114   assert_always((which >= 0) && (which < MAX_STEPPERS), "stepper_config called on an invalid stepper motor!");
115   assert_always(intf, "stepper_config called with an invalid interface!");
116
117   step[which].intf = intf;
118
119   step[which].type = intf->type;
120   step[which].index_start = intf->index_start;/* location of first index value in half steps */
121   step[which].index_end   = intf->index_end;  /* location of last index value in half steps */
122   step[which].index_patt  = intf->index_patt; /* hex value of coil pattern (0 if not needed)*/
123   step[which].initphase   = intf->initphase; /* Phase at 0 steps, for alignment) */
124
125
126   step[which].pattern     = 0;
127   step[which].old_pattern = 0;
128   step[which].step_pos    = 0;
129   step[which].abs_step_pos= 0;
130   step[which].phase = step[which].initphase;
131   step[which].old_phase = step[which].initphase;
132
133
134   switch ( step[which].type )
135   {   default:
136      case STARPOINT_48STEP_REEL:  /* STARPOINT RMxxx */
137      case BARCREST_48STEP_REEL :  /* Barcrest Reel unit */
138      case MPU3_48STEP_REEL :
139      case GAMESMAN_48STEP_REEL :  /* Gamesman GMxxxx */
140      case PROJECT_48STEP_REEL :
141      step[which].max_steps = (48*2);
142      break;
143      case GAMESMAN_100STEP_REEL :
144      step[which].max_steps = (100*2);
145      break;
146      case STARPOINT_144STEP_DICE :/* STARPOINT 1DCU DICE mechanism */
147      //Dice reels are 48 step motors, but complete three full cycles between opto updates
148      step[which].max_steps = ((48*3)*2);
149      break;
150      case STARPOINT_200STEP_REEL :
151      case GAMESMAN_200STEP_REEL :
152      case ECOIN_200STEP_REEL :
153      step[which].max_steps = (200*2);
154      break;
155   }
156
157   state_save_register_item(machine, "stepper", NULL, which, step[which].index_start);
158   state_save_register_item(machine, "stepper", NULL, which, step[which].index_end);
159   state_save_register_item(machine, "stepper", NULL, which, step[which].index_patt);
160   state_save_register_item(machine, "stepper", NULL, which, step[which].initphase);
161   state_save_register_item(machine, "stepper", NULL, which, step[which].phase);
162   state_save_register_item(machine, "stepper", NULL, which, step[which].old_phase);
163   state_save_register_item(machine, "stepper", NULL, which, step[which].pattern);
164   state_save_register_item(machine, "stepper", NULL, which, step[which].old_pattern);
165   state_save_register_item(machine, "stepper", NULL, which, step[which].step_pos);
166   state_save_register_item(machine, "stepper", NULL, which, step[which].abs_step_pos);
167   state_save_register_item(machine, "stepper", NULL, which, step[which].max_steps);
168   state_save_register_item(machine, "stepper", NULL, which, step[which].type);
169}
170
171///////////////////////////////////////////////////////////////////////////
172int stepper_get_position(int which)
173{
174   return step[which].step_pos;
175}
176
177///////////////////////////////////////////////////////////////////////////
178int stepper_get_absolute_position(int which)
179{
180   return step[which].abs_step_pos;
181}
182
183///////////////////////////////////////////////////////////////////////////
184
185int stepper_get_max(int which)
186{
187   return step[which].max_steps;
188}
189
190///////////////////////////////////////////////////////////////////////////
191
192static void update_optic(int which)
193{
194   int pos   = step[which].step_pos,
195      start = step[which].index_start,
196      end = step[which].index_end;
197
198   if (start > end) // cope with index patterns that wrap around
199   {
200      if ( (( pos > start ) || ( pos < end )) &&
201      ( ( step[which].pattern == step[which].index_patt || step[which].index_patt==0) ||
202      ( step[which].pattern == 0 &&
203      (step[which].old_pattern == step[which].index_patt || step[which].index_patt==0)
204      ) ) )
205      {
206         step[which].optic = 1;
207      }
208      else step[which].optic = 0;
209      }
210   else
211   {
212      if ( (( pos > start ) && ( pos < end )) &&
213      ( ( step[which].pattern == step[which].index_patt || step[which].index_patt==0) ||
214      ( step[which].pattern == 0 &&
215      (step[which].old_pattern == step[which].index_patt || step[which].index_patt==0)
216      ) ) )
217      {
218      step[which].optic = 1;
219      }
220      else step[which].optic = 0;
221   }
222}
223///////////////////////////////////////////////////////////////////////////
224
225void stepper_reset_position(int which)
226{
227   step[which].step_pos    = 0x00;
228   step[which].abs_step_pos= 0x00;
229   step[which].pattern     = 0x00;
230   step[which].old_pattern = 0x00;
231   step[which].phase = step[which].initphase;
232   step[which].old_phase = step[which].initphase;
233   update_optic(which);
234}
235
236///////////////////////////////////////////////////////////////////////////
237
238int stepper_optic_state(int which)
239{
240   int result = 0;
241
242   if ( which < MAX_STEPPERS )
243   {
244      result = step[which].optic;
245   }
246
247   return result;
248}
249
250///////////////////////////////////////////////////////////////////////////
251
252int stepper_update(int which, UINT8 pattern)
253{
254   int changed = 0;
255
256   /* This code probably makes more sense if you visualise what is being emulated, namely
257   a spinning drum with two electromagnets inside. Essentially, the CPU
258   activates a pair of windings on these magnets leads as necessary to attract and repel the drum to pull it round and
259   display as appropriate. To attempt to visualise the rotation effect, take a look at the compass rose below, representing a side on view of the reel,
260   the numbers indicate the phase information as used
261
262       7
263       N
264   1 W   E 5
265       S
266       3
267
268   For sake of accuracy, we're representing all possible phases of the motor, effectively moving the motor one half step at a time, so a 48 step motor becomes
269   96 half steps. This is necessary because of some programs running the wiring in series with a distinct delay between the pair being completed. This causes
270   a small movement that may trigger the optic tab.
271   */
272
273   int pos,steps=0;
274   step[which].pattern = pattern;
275   switch ( step[which].type )
276   {
277      default:
278      logerror("No reel type specified for %x!\n",which);
279      break;
280      case STARPOINT_48STEP_REEL : /* STARPOINT RMxxx */
281      case GAMESMAN_200STEP_REEL : /* Gamesman GMxxxx */
282      case STARPOINT_144STEP_DICE :/* STARPOINT 1DCU DICE mechanism */
283      case STARPOINT_200STEP_REEL :/* STARPOINT 1DCU DICE mechanism */
284      //Standard drive table is 2,6,4,5,1,9,8,a
285      //NOTE: This runs through the stator patterns in such a way as to drive the reel forward (downwards from the player's view, clockwise on our rose)
286      //The Heber 'Pluto' controller runs this in reverse
287      switch (pattern)
288      {             //Black  Blue  Red  Yellow
289         case 0x02://  0     0     1     0
290         step[which].phase = 7;
291         break;
292         case 0x06://  0     1     1     0
293         step[which].phase = 6;
294         break;
295         case 0x04://  0     1     0     0
296         step[which].phase = 5;
297         break;
298         case 0x05://  0     1     0     1
299         step[which].phase = 4;
300         break;
301         case 0x01://  0     0     0     1
302         step[which].phase = 3;
303         break;
304         case 0x09://  1     0     0     1
305         step[which].phase = 2;
306         break;
307         case 0x08://  1     0     0     0
308         step[which].phase = 1;
309         break;
310         case 0x0A://  1     0     1     0
311         step[which].phase = 0;
312         break;
313         //          Black  Blue  Red  Yellow
314         case 0x03://  0     0     1     1
315         {
316            if ((step[which].old_phase ==6)||(step[which].old_phase == 0)) // if the previous pattern had the drum in the northern quadrant, it will point north now
317            {
318               step[which].phase = 7;
319            }
320            else //otherwise it will line up due south
321            {
322               step[which].phase = 3;
323            }
324         }
325         break;
326         case 0x0C://  1     1     0     0
327         {
328            if ((step[which].old_phase ==6)||(step[which].old_phase == 4)) // if the previous pattern had the drum in the eastern quadrant, it will point east now
329            {
330               step[which].phase = 5;
331            }
332            else //otherwise it will line up due west
333            {
334               step[which].phase = 1;
335            }
336         }
337         break;
338      }
339      break;
340
341      case BARCREST_48STEP_REEL :
342      case GAMESMAN_48STEP_REEL :
343      case GAMESMAN_100STEP_REEL :
344      //Standard drive table is 1,3,2,6,4,C,8,9
345      //Gamesman 48 step uses this pattern shifted one place forward, though this shouldn't matter
346      switch (pattern)
347      {
348         //             Yellow   Brown  Orange Black
349         case 0x01://  0        0      0      1
350         step[which].phase = 7;
351         break;
352         case 0x03://  0        0      1      1
353         step[which].phase = 6;
354         break;
355         case 0x02://  0        0      1      0
356         step[which].phase = 5;
357         break;
358         case 0x06://  0        1      1      0
359         step[which].phase = 4;
360         break;
361         case 0x04://  0        1      0      0
362         step[which].phase = 3;
363         break;
364         case 0x0C://  1        1      0      0
365         step[which].phase = 2;
366         break;
367         case 0x08://  1        0      0      0
368         step[which].phase = 1;
369         break;//YOLB
370         case 0x09://  1        0      0      1
371         step[which].phase = 0;
372         break;
373
374         // The below values should not be used by anything sane, as they effectively ignore one stator side entirely
375         //          Yellow   Brown  Orange Black
376         case 0x05://   0       1       0     1
377         {
378            if ((step[which].old_phase ==6)||(step[which].old_phase == 0)) // if the previous pattern had the drum in the northern quadrant, it will point north now
379            {
380               step[which].phase = 7;
381            }
382            else //otherwise it will line up due south
383            {
384               step[which].phase = 3;
385            }
386         }
387         break;
388
389         case 0x0A://   1       0       1     0
390         {
391            if ((step[which].old_phase ==6)||(step[which].old_phase == 4)) // if the previous pattern had the drum in the eastern quadrant, it will point east now
392            {
393               step[which].phase = 5;
394            }
395            else //otherwise it will line up due west
396            {
397               step[which].phase = 1;
398            }
399         }
400         break;
401      }
402      break;
403
404      case MPU3_48STEP_REEL :
405      /* The MPU3 interface is actually the same as the MPU4 setup, but with two active lines instead of four
406         Inverters are used so if a pin is low, the higher bit of the pair is activated, and if high the lower bit is activated.
407         TODO:Check this, 2 and 1 could be switched over.
408       */
409      switch (pattern)
410      {
411      //             Yellow(2)   Brown(1)  Orange(!2) Black(!1)
412         case 0x00 :// 0          0          1         1
413         step[which].phase = 6;
414         break;
415         case 0x01 :// 0          1          1         0
416         step[which].phase = 4;
417         break;
418         case 0x03 :// 1          1          0         0
419         step[which].phase = 2;
420         break;
421         case 0x02 :// 1          0          0         1
422         step[which].phase = 0;
423         break;
424      }
425      break;
426
427      case ECOIN_200STEP_REEL :
428      //While the 48 and 100 step models appear to be reverse driven Starpoint reels, the 200 step model seems bespoke, certainly in terms of wiring.
429      //On a Proconn machine this same pattern is seen but running in reverse
430      //Standard drive table is 8,c,4,6,2,3,1,9
431      switch (pattern)
432      {
433         case 0x08://  0     0     1     0
434         step[which].phase = 7;
435         break;
436         case 0x0c://  0     1     1     0
437         step[which].phase = 6;
438         break;
439         case 0x04://  0     1     0     0
440         step[which].phase = 5;
441         break;
442         case 0x06://  0     1     0     1
443         step[which].phase = 4;
444         break;
445         case 0x02://  0     0     0     1
446         step[which].phase = 3;
447         break;
448         case 0x03://  1     0     0     1
449         step[which].phase = 2;
450         break;
451         case 0x01://  1     0     0     0
452         step[which].phase = 1;
453         break;
454         case 0x09://  1     0     1     0
455         step[which].phase = 0;
456         break;
457         case 0x0a://  0     0     1     1
458         {
459            if ((step[which].old_phase ==6)||(step[which].old_phase == 0)) // if the previous pattern had the drum in the northern quadrant, it will point north now
460            {
461               step[which].phase = 7;
462            }
463            else //otherwise it will line up due south
464            {
465               step[which].phase = 3;
466            }
467         }
468         break;
469         case 0x07://  1     1     0     0
470         {
471            if ((step[which].old_phase ==6)||(step[which].old_phase == 4)) // if the previous pattern had the drum in the eastern quadrant, it will point east now
472            {
473               step[which].phase = 5;
474            }
475            else //otherwise it will line up due west
476            {
477               step[which].phase = 1;
478            }
479         }
480         break;
481      }
482      break;
483
484      case PROJECT_48STEP_REEL :
485      //Standard drive table is 8,c,4,5,1,3,2,a
486      //This appears to be basically a rewired Gamesman (the reel PCB looks like it does some shuffling)
487      //TODO: Not sure if this should be represented as a type here, or by defining it as a Gamesman in the driver and bitswapping.
488      switch (pattern)
489      {
490         case 0x08://  0     0     1     0
491         step[which].phase = 7;
492         break;
493         case 0x0c://  0     1     1     0
494         step[which].phase = 6;
495         break;
496         case 0x04://  0     1     0     0
497         step[which].phase = 5;
498         break;
499         case 0x05://  0     1     0     1
500         step[which].phase = 4;
501         break;
502         case 0x01://  0     0     0     1
503         step[which].phase = 3;
504         break;
505         case 0x03://  1     0     0     1
506         step[which].phase = 2;
507         break;
508         case 0x02://  1     0     0     0
509         step[which].phase = 1;
510         break;
511         case 0x0a://  1     0     1     0
512         step[which].phase = 0;
513         break;
514         case 0x09://  0     0     1     1
515         {
516            if ((step[which].old_phase ==6)||(step[which].old_phase == 0)) // if the previous pattern had the drum in the northern quadrant, it will point north now
517            {
518               step[which].phase = 7;
519            }
520            else //otherwise it will line up due south
521            {
522               step[which].phase = 3;
523            }
524         }
525         break;
526         case 0x06://  1     1     0     0
527         {
528            if ((step[which].old_phase ==6)||(step[which].old_phase == 4)) // if the previous pattern had the drum in the eastern quadrant, it will point east now
529            {
530               step[which].phase = 5;
531            }
532            else //otherwise it will line up due west
533            {
534               step[which].phase = 1;
535            }
536         }
537         break;
538      }
539      break;
540
541
542
543   }
544
545   steps = step[which].old_phase - step[which].phase;
546
547   if (steps < -4)
548   {
549      steps = steps +8;
550   }
551   if (steps > 4)
552   {
553      steps = steps -8;
554   }
555
556   step[which].old_phase = step[which].phase;
557   step[which].old_pattern = step[which].pattern;
558
559   int max = step[which].max_steps;
560   pos = 0;
561
562   if (max!=0)
563   {
564      step[which].abs_step_pos += steps;
565      pos = (step[which].step_pos + steps + max) % max;
566   }
567   else
568   {
569      logerror("step[%x].max_steps == 0\n",which);
570   }
571
572   if (pos != step[which].step_pos)
573   {
574      changed++;
575   }
576
577   step[which].step_pos = pos;
578   update_optic(which);
579
580   return changed;
581}
trunk/src/mame/machine/steppers.h
r0r241972
1///////////////////////////////////////////////////////////////////////////
2//                                                                       //
3// steppers.c steppermotor emulation                                     //
4//                                                                       //
5// Emulates : stepper motors driven with full step or half step          //
6//            also emulates the index optic                              //
7//                                                                       //
8//                                                                       //
9// TODO:  add further types of stepper motors if needed (Konami/IGT?)    //
10//        Someone who understands the device system may want to convert  //
11//        this                                                           //
12///////////////////////////////////////////////////////////////////////////
13
14
15#ifndef INC_STEPPERS
16#define INC_STEPPERS
17
18#define MAX_STEPPERS            8           /* maximum number of steppers */
19
20#define STARPOINT_48STEP_REEL   0           /* STARPOINT RMXXX reel unit */
21#define STARPOINT_144STEP_DICE  1           /* STARPOINT 1DCU DICE mechanism */
22#define STARPOINT_200STEP_REEL  2
23
24#define BARCREST_48STEP_REEL    3           /* Barcrest bespoke reel unit */
25#define MPU3_48STEP_REEL        4
26
27#define ECOIN_200STEP_REEL      5           /* Probably not bespoke, but can't find a part number */
28
29#define GAMESMAN_48STEP_REEL    6
30#define GAMESMAN_100STEP_REEL   7
31#define GAMESMAN_200STEP_REEL   8
32
33#define PROJECT_48STEP_REEL     9
34
35/*------------- Stepper motor interface structure -----------------*/
36
37struct stepper_interface
38{
39   UINT8 type; /* Reel unit type */
40   INT16 index_start;/* start position of index (in half steps) */
41   INT16 index_end;  /* end position of index (in half steps) */
42   INT16 index_patt; /* pattern needed on coils (0=don't care) */
43   UINT8 initphase; /* Phase at 0, for opto linkage */
44};
45
46extern const stepper_interface starpoint_interface_48step;
47extern const stepper_interface starpointrm20_interface_48step;
48
49extern const stepper_interface starpoint_interface_200step_reel;
50extern const stepper_interface ecoin_interface_200step_reel;
51
52void stepper_config(running_machine &machine, int which, const stepper_interface *intf);
53
54void stepper_reset_position(int id);        /* reset a motor to position 0 */
55
56int  stepper_optic_state(   int id);        /* read a motor's optics */
57
58int  stepper_update(int id, UINT8 pattern); /* update a motor */
59
60int  stepper_get_position(int id);          /* get current position in half steps */
61
62int  stepper_get_absolute_position(int id); /* get current absolute position in half steps */
63
64int  stepper_get_max(int id);               /* get maximum position in half steps */
65#endif
trunk/src/mame/mame.mak
r241971r241972
401401MACHINES += DS75161A
402402MACHINES += E0516
403403MACHINES += E05A03
404MACHINES += E05A30
405404MACHINES += EEPROMDEV
406405MACHINES += ER2055
407406MACHINES += F3853
r241971r241972
565564#MACHINES += SMC92X4
566565#MACHINES += TI99_HD
567566#MACHINES += STRATA
568MACHINES += STEPPERS
569567#MACHINES += CORVUSHD
570568#MACHINES += WOZFDC
571569#MACHINES += DIABLO_HD
r241971r241972
956954   $(DRIVERS)/mpu5hw.o $(DRIVERS)/mpu5.o \
957955   $(VIDEO)/awpvid.o \
958956   $(MACHINE)/meters.o \
957   $(MACHINE)/steppers.o \
959958
960959$(MAMEOBJ)/bfm.a: \
961960   $(DRIVERS)/bfcobra.o \
r241971r241972
12901289   $(DRIVERS)/jpmsys7.o \
12911290   $(VIDEO)/awpvid.o \
12921291   $(MACHINE)/meters.o \
1292   $(MACHINE)/steppers.o \
12931293
12941294$(MAMEOBJ)/kaneko.a: \
12951295   $(DRIVERS)/airbustr.o $(VIDEO)/airbustr.o \
trunk/src/mess/includes/amstrad.h
r241971r241972
2929#include "bus/centronics/comxpl80.h"
3030#include "bus/centronics/epson_ex800.h"
3131#include "bus/centronics/epson_lx800.h"
32#include "bus/centronics/epson_lx810l.h"
3332#include "bus/centronics/printer.h"
3433#include "bus/centronics/digiblst.h"
3534#include "bus/generic/slot.h"
trunk/src/mess/mess.mak
r241971r241972
387387MACHINES += DS75161A
388388MACHINES += E0516
389389MACHINES += E05A03
390MACHINES += E05A30
391390MACHINES += EEPROMDEV
392391MACHINES += ER2055
393392MACHINES += F3853
r241971r241972
553552MACHINES += HDC9234
554553MACHINES += TI99_HD
555554MACHINES += STRATA
556MACHINES += STEPPERS
557555MACHINES += CORVUSHD
558556MACHINES += WOZFDC
559557MACHINES += DIABLO_HD
trunk/src/targets/mess.lst
r241971r241972
285285/mess/drivers/ex800
286286/mess/drivers/hx20
287287/mess/drivers/lx800
288/mess/drivers/lx810l
289288/mess/drivers/px4
290289/mess/drivers/px8
291290/mess/drivers/qx10


Previous 199869 Revisions Next


© 1997-2024 The MAME Team