Previous 15994 Revisions Next

r7587 Tuesday 16th March, 2010 at 13:39:20 UTC by Curt Coder
Refactored MOS6530 to use devcb.
[src/mess]mess.mak
[src/mess/drivers]kim1.c mk2.c
[src/mess/machine]6530miot.c 6530miot.h c2040.c mos6530.c mos6530.h

src/mess/machine/6530miot.c
r7586r7587
1/***************************************************************************
2
3  MIOT 6530 emulation
4
5The timer seems to follow these rules:
6- When the timer flag changes from 0 to 1 the timer continues to count
7  down at a 1 cycle rate.
8- When the timer is being read or written the timer flag is reset.
9- When the timer flag is set and the timer contents are 0, the counting
10  stops.
11
12From the operation of the KIM1 it expects the irqflag to be set whenever
13the unit is reset. This is something that is not clear from the datasheet
14and should be verified against real hardware.
15
16***************************************************************************/
17
18#include "emu.h"
19#include "6530miot.h"
20
21
22/***************************************************************************
23    CONSTANTS
24***************************************************************************/
25
26enum
27{
28   TIMER_IDLE,
29   TIMER_COUNTING,
30   TIMER_FINISHING
31};
32
33#define TIMER_FLAG      0x80
34
35
36
37/***************************************************************************
38    TYPE DEFINITIONS
39***************************************************************************/
40
41typedef struct _miot6530_port miot6530_port;
42struct _miot6530_port
43{
44   UINT8            in;
45   UINT8            out;
46   UINT8            ddr;
47   miot_read_func      in_func;
48   miot_write_func      out_func;
49};
50
51
52typedef struct _miot6530_state miot6530_state;
53struct _miot6530_state
54{
55   const miot6530_interface *intf;
56
57   miot6530_port   port[2];
58
59   UINT8         irqstate;
60   UINT8         irqenable;
61
62   UINT8         timershift;
63   UINT8         timerstate;
64   emu_timer *      timer;
65
66   UINT32         clock;
67};
68
69
70
71/***************************************************************************
72    INLINE FUNCTIONS
73***************************************************************************/
74
75/*-------------------------------------------------
76    get_safe_token - convert a device's token
77    into a miot6530_state
78-------------------------------------------------*/
79
80INLINE miot6530_state *get_safe_token(running_device *device)
81{
82   assert(device != NULL);
83   assert(device->token != NULL);
84   assert(device->type == MIOT6530);
85   return (miot6530_state *)device->token;
86}
87
88
89/*-------------------------------------------------
90    update_irqstate - update the IRQ state
91    based on interrupt enables
92-------------------------------------------------*/
93
94INLINE void update_irqstate(running_device *device)
95{
96   miot6530_state *miot = get_safe_token(device);
97   UINT8 out = miot->port[1].out;
98
99   if ( miot->irqenable )
100      out = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( out & 0x7F );
101
102   if (miot->port[1].out_func != NULL)
103      (*miot->port[1].out_func)(device, out, out);
104   else
105      logerror("6530MIOT chip %s: Port B is being written to but has no handler.\n", device->tag());
106}
107
108
109/*-------------------------------------------------
110    get_timer - return the current timer value
111-------------------------------------------------*/
112
113INLINE UINT8 get_timer(miot6530_state *miot)
114{
115   /* if idle, return 0 */
116   if (miot->timerstate == TIMER_IDLE)
117      return 0;
118
119   /* if counting, return the number of ticks remaining */
120   else if (miot->timerstate == TIMER_COUNTING)
121      return attotime_to_ticks(timer_timeleft(miot->timer), miot->clock) >> miot->timershift;
122
123   /* if finishing, return the number of ticks without the shift */
124   else
125      return attotime_to_ticks(timer_timeleft(miot->timer), miot->clock);
126}
127
128
129/***************************************************************************
130    INTERNAL FUNCTIONS
131***************************************************************************/
132
133/*-------------------------------------------------
134    timer_end_callback - callback to process the
135    timer
136-------------------------------------------------*/
137
138static TIMER_CALLBACK( timer_end_callback )
139{
140   running_device *device = (running_device *)ptr;
141   miot6530_state *miot = get_safe_token(device);
142
143   assert(miot->timerstate != TIMER_IDLE);
144
145   /* if we finished counting, switch to the finishing state */
146   if (miot->timerstate == TIMER_COUNTING)
147   {
148      miot->timerstate = TIMER_FINISHING;
149      timer_adjust_oneshot(miot->timer, ticks_to_attotime(256, miot->clock), 0);
150
151      /* signal timer IRQ as well */
152      miot->irqstate |= TIMER_FLAG;
153      update_irqstate(device);
154   }
155
156   /* if we finished finishing, switch to the idle state */
157   else if (miot->timerstate == TIMER_FINISHING)
158   {
159      miot->timerstate = TIMER_IDLE;
160      timer_adjust_oneshot(miot->timer, attotime_never, 0);
161   }
162}
163
164
165
166/***************************************************************************
167    I/O ACCESS
168***************************************************************************/
169
170/*-------------------------------------------------
171    miot6530_w - master I/O write access
172-------------------------------------------------*/
173
174WRITE8_DEVICE_HANDLER( miot6530_w )
175{
176   miot6530_state *miot = get_safe_token(device);
177
178   /* if A2 == 1, we are writing to the timer */
179   if (offset & 0x04)
180   {
181      static const UINT8 timershift[4] = { 0, 3, 6, 10 };
182      attotime curtime = timer_get_time(device->machine);
183      INT64 target;
184
185      /* A0-A1 contain the timer divisor */
186      miot->timershift = timershift[offset & 3];
187
188      /* A3 contains the timer IRQ enable */
189      if (offset & 8)
190         miot->irqenable |= TIMER_FLAG;
191      else
192         miot->irqenable &= ~TIMER_FLAG;
193
194      /* writes here clear the timer flag */
195      if (miot->timerstate != TIMER_FINISHING || get_timer(miot) != 0xff)
196         miot->irqstate &= ~TIMER_FLAG;
197      update_irqstate(device);
198
199      /* update the timer */
200      miot->timerstate = TIMER_COUNTING;
201      target = attotime_to_ticks(curtime, miot->clock) + 1 + (data << miot->timershift);
202      timer_adjust_oneshot(miot->timer, attotime_sub(ticks_to_attotime(target, miot->clock), curtime), 0);
203   }
204
205   /* if A2 == 0, we are writing to the I/O section */
206   else
207   {
208      /* A1 selects the port */
209      miot6530_port *port = &miot->port[(offset >> 1) & 1];
210
211      /* if A0 == 1, we are writing to the port's DDR */
212      if (offset & 1)
213         port->ddr = data;
214
215      /* if A0 == 0, we are writing to the port's output */
216      else
217      {
218         UINT8 olddata = port->out;
219         port->out = data;
220
221         if ( ( offset & 2 ) && miot->irqenable )
222         {
223            olddata = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( olddata & 0x7F );
224            data = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( data & 0x7F );
225         }
226
227         if (port->out_func != NULL)
228            (*port->out_func)(device, data, olddata);
229         else
230            logerror("6530MIOT chip %s: Port %c is being written to but has no handler.  PC: %08X - %02X\n", device->tag(), 'A' + (offset & 1), cpu_get_pc(device->machine->firstcpu), data);
231      }
232   }
233}
234
235
236/*-------------------------------------------------
237    miot6530_r - master I/O read access
238-------------------------------------------------*/
239
240READ8_DEVICE_HANDLER( miot6530_r )
241{
242   miot6530_state *miot = get_safe_token(device);
243   UINT8 val = 0;
244
245   /* if A2 == 1 and A0 == 1, we are reading interrupt flags */
246   if ((offset & 0x05) == 0x05)
247   {
248      val = miot->irqstate;
249   }
250
251   /* if A2 == 1 and A0 == 0, we are reading the timer */
252   else if ((offset & 0x05) == 0x04)
253   {
254      val = get_timer(miot);
255
256      /* A3 contains the timer IRQ enable */
257      if (offset & 8)
258         miot->irqenable |= TIMER_FLAG;
259      else
260         miot->irqenable &= ~TIMER_FLAG;
261
262      /* implicitly clears the timer flag */
263      if (miot->timerstate != TIMER_FINISHING || val != 0xff)
264         miot->irqstate &= ~TIMER_FLAG;
265      update_irqstate(device);
266   }
267
268   /* if A2 == 0 and A0 == anything, we are reading from ports */
269   else
270   {
271      /* A1 selects the port */
272      miot6530_port *port = &miot->port[(offset >> 1) & 1];
273
274      /* if A0 == 1, we are reading the port's DDR */
275      if (offset & 1)
276         val = port->ddr;
277
278      /* if A0 == 0, we are reading the port as an input */
279      else
280      {
281         UINT8   out = port->out;
282
283         if ( ( offset & 2 ) && miot->irqenable )
284            out = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( out & 0x7F );
285
286         /* call the input callback if it exists */
287         if (port->in_func != NULL)
288         {
289            port->in = (*port->in_func)(device, port->in);
290         }
291         else
292            logerror("6530MIOT chip %s: Port %c is being read but has no handler.  PC: %08X\n", device->tag(), 'A' + (offset & 1), cpu_get_pc(device->machine->firstcpu));
293
294         /* apply the DDR to the result */
295         val = (out & port->ddr) | (port->in & ~port->ddr);
296      }
297   }
298   return val;
299}
300
301
302/*-------------------------------------------------
303    miot6530_porta_in_set - set port A input
304    value
305-------------------------------------------------*/
306
307void miot6530_porta_in_set(running_device *device, UINT8 data, UINT8 mask)
308{
309   miot6530_state *miot = get_safe_token(device);
310   miot->port[0].in = (miot->port[0].in & ~mask) | (data & mask);
311}
312
313
314/*-------------------------------------------------
315    miot6530_portb_in_set - set port B input
316    value
317-------------------------------------------------*/
318
319void miot6530_portb_in_set(running_device *device, UINT8 data, UINT8 mask)
320{
321   miot6530_state *miot = get_safe_token(device);
322   miot->port[1].in = (miot->port[1].in & ~mask) | (data & mask);
323}
324
325
326/*-------------------------------------------------
327    miot6530_porta_in_get - return port A input
328    value
329-------------------------------------------------*/
330
331UINT8 miot6530_porta_in_get(running_device *device)
332{
333   miot6530_state *miot = get_safe_token(device);
334   return miot->port[0].in;
335}
336
337
338/*-------------------------------------------------
339    miot6530_portb_in_get - return port B input
340    value
341-------------------------------------------------*/
342
343UINT8 miot6530_portb_in_get(running_device *device)
344{
345   miot6530_state *miot = get_safe_token(device);
346   return miot->port[1].in;
347}
348
349
350/*-------------------------------------------------
351    miot6530_porta_in_get - return port A output
352    value
353-------------------------------------------------*/
354
355UINT8 miot6530_porta_out_get(running_device *device)
356{
357   miot6530_state *miot = get_safe_token(device);
358   return miot->port[0].out;
359}
360
361
362/*-------------------------------------------------
363    miot6530_portb_in_get - return port B output
364    value
365-------------------------------------------------*/
366
367UINT8 miot6530_portb_out_get(running_device *device)
368{
369   miot6530_state *miot = get_safe_token(device);
370   return miot->port[1].out;
371}
372
373
374/***************************************************************************
375    DEVICE INTERFACE
376***************************************************************************/
377
378static DEVICE_START( miot6530 )
379{
380   miot6530_state *miot = get_safe_token(device);
381
382   /* validate arguments */
383   assert(device != NULL);
384   assert(device->tag() != NULL);
385
386   /* set static values */
387   miot->intf = (const miot6530_interface*)device->baseconfig().static_config;
388   miot->clock = device->clock;
389
390   /* configure the ports */
391   miot->port[0].in_func = miot->intf->in_a_func;
392   miot->port[0].out_func = miot->intf->out_a_func;
393   miot->port[1].in_func = miot->intf->in_b_func;
394   miot->port[1].out_func = miot->intf->out_b_func;
395
396   /* allocate timers */
397   miot->timer = timer_alloc(device->machine, timer_end_callback, (void *)device);
398
399   /* register for save states */
400   state_save_register_device_item(device, 0, miot->port[0].in);
401   state_save_register_device_item(device, 0, miot->port[0].out);
402   state_save_register_device_item(device, 0, miot->port[0].ddr);
403   state_save_register_device_item(device, 0, miot->port[1].in);
404   state_save_register_device_item(device, 0, miot->port[1].out);
405   state_save_register_device_item(device, 0, miot->port[1].ddr);
406
407   state_save_register_device_item(device, 0, miot->irqstate);
408   state_save_register_device_item(device, 0, miot->irqenable);
409
410   state_save_register_device_item(device, 0, miot->timershift);
411   state_save_register_device_item(device, 0, miot->timerstate);
412}
413
414
415static DEVICE_RESET( miot6530 )
416{
417   miot6530_state *miot = get_safe_token(device);
418
419   /* reset I/O states */
420   miot->port[0].out = 0;
421   miot->port[0].ddr = 0;
422   miot->port[1].out = 0;
423   miot->port[1].ddr = 0;
424
425   /* reset IRQ states */
426   miot->irqenable = 0;
427   miot->irqstate = TIMER_FLAG;
428   update_irqstate(device);
429
430   /* reset timer states */
431   miot->timershift = 0;
432   miot->timerstate = TIMER_IDLE;
433   timer_adjust_oneshot(miot->timer, attotime_never, 0);
434}
435
436
437DEVICE_GET_INFO( miot6530 )
438{
439   switch (state)
440   {
441      /* --- the following bits of info are returned as 64-bit signed integers --- */
442      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(miot6530_state);      break;
443      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                     break;
444      case DEVINFO_INT_CLASS:                     info->i = DEVICE_CLASS_PERIPHERAL;      break;
445
446      /* --- the following bits of info are returned as pointers to data or functions --- */
447      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(miot6530);break;
448      case DEVINFO_FCT_STOP:                     /* Nothing */                     break;
449      case DEVINFO_FCT_RESET:                     info->reset = DEVICE_RESET_NAME(miot6530);break;
450
451      /* --- the following bits of info are returned as NULL-terminated strings --- */
452      case DEVINFO_STR_NAME:                     strcpy(info->s, "6530 (MIOT)");            break;
453      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "I/O devices");            break;
454      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                  break;
455      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);                  break;
456      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
457   }
458}
src/mess/machine/6530miot.h
r7586r7587
1/**********************************************************************
2
3    MOS Technology 6530 Memory, I/O, Timer Array emulation
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************
9                            _____   _____
10                   Vss   1 |*    \_/     | 40  PA1
11                   PA0   2 |             | 39  PA2
12                  phi2   3 |             | 38  PA3
13                   RS0   4 |             | 37  PA4
14                    A9   5 |             | 36  PA5
15                    A8   6 |             | 35  PA6
16                    A7   7 |             | 34  PA7
17                    A6   8 |             | 33  DB0
18                   R/W   9 |             | 32  DB1
19                    A5  10 |   MCS6530   | 31  DB2
20                    A4  11 |             | 30  DB3
21                    A3  12 |             | 29  DB4
22                    A2  13 |             | 28  DB5
23                    A1  14 |             | 27  DB6
24                    A0  15 |             | 26  DB7
25                  _RES  16 |             | 25  PB0
26               IRQ/PB7  17 |             | 24  PB1
27               CS1/PB6  18 |             | 23  PB2
28               CS2/PB5  19 |             | 22  PB3
29                   Vcc  20 |_____________| 21  PB4
30
31**********************************************************************/
32
33#ifndef __MIOT6530_H__
34#define __MIOT6530_H__
35
36
37/***************************************************************************
38    TYPE DEFINITIONS
39***************************************************************************/
40
41typedef UINT8 (*miot_read_func)(running_device *device, UINT8 olddata);
42typedef void (*miot_write_func)(running_device *device, UINT8 newdata, UINT8 olddata);
43
44
45typedef struct _miot6530_interface miot6530_interface;
46struct _miot6530_interface
47{
48   miot_read_func      in_a_func;
49   miot_read_func      in_b_func;
50   miot_write_func      out_a_func;
51   miot_write_func      out_b_func;
52};
53
54
55
56/***************************************************************************
57    DEVICE CONFIGURATION MACROS
58***************************************************************************/
59
60#define MDRV_MIOT6530_ADD(_tag, _clock, _intrf) \
61   MDRV_DEVICE_ADD(_tag, MIOT6530, _clock) \
62   MDRV_DEVICE_CONFIG(_intrf)
63
64
65
66/***************************************************************************
67    FUNCTION PROTOTYPES
68***************************************************************************/
69
70READ8_DEVICE_HANDLER( miot6530_r );
71WRITE8_DEVICE_HANDLER( miot6530_w );
72
73void miot6530_porta_in_set(running_device *device, UINT8 data, UINT8 mask);
74void miot6530_portb_in_set(running_device *device, UINT8 data, UINT8 mask);
75
76UINT8 miot6530_porta_in_get(running_device *device);
77UINT8 miot6530_portb_in_get(running_device *device);
78
79UINT8 miot6530_porta_out_get(running_device *device);
80UINT8 miot6530_portb_out_get(running_device *device);
81
82
83/* ----- device interface ----- */
84
85#define MIOT6530 DEVICE_GET_INFO_NAME(miot6530)
86DEVICE_GET_INFO( miot6530 );
87
88#endif
src/mess/machine/mos6530.c
r7586r7587
1/**********************************************************************
1/***************************************************************************
22
3    MOS Technology 6530 Memory, I/O, Timer Array emulation
3  MIOT 6530 emulation
44
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
5The timer seems to follow these rules:
6- When the timer flag changes from 0 to 1 the timer continues to count
7  down at a 1 cycle rate.
8- When the timer is being read or written the timer flag is reset.
9- When the timer flag is set and the timer contents are 0, the counting
10  stops.
711
8**********************************************************************/
12From the operation of the KIM1 it expects the irqflag to be set whenever
13the unit is reset. This is something that is not clear from the datasheet
14and should be verified against real hardware.
915
10/*
16***************************************************************************/
1117
12    TODO:
18#include "emu.h"
19#include "mos6530.h"
1320
14    - interrupt flag register
15    - internal RAM
16    - internal ROM
1721
18*/
19
20#include "mos6530.h"
21
2222/***************************************************************************
23    PARAMETERS
23    CONSTANTS
2424***************************************************************************/
2525
26#define LOG 1
27
2826enum
2927{
30   REGISTER_PORT_A = 0,
31   REGISTER_PORT_A_DDR,
32   REGISTER_PORT_B,
33   REGISTER_PORT_B_DDR,
34   REGISTER_TIMER_1T, REGISTER_TIMER = REGISTER_TIMER_1T,
35   REGISTER_TIMER_8T, REGISTER_INTERRUPT_FLAG = REGISTER_TIMER_8T,
36   REGISTER_TIMER_64T,
37   REGISTER_TIMER_1024T
28   TIMER_IDLE,
29   TIMER_COUNTING,
30   TIMER_FINISHING
3831};
3932
40enum
41{
42   PORT_A = 0,
43   PORT_B,
44   PORT_COUNT
45};
33#define TIMER_FLAG      0x80
4634
47static const int PRESCALER[] = { 1, 8, 64, 1024 };
4835
36
4937/***************************************************************************
5038    TYPE DEFINITIONS
5139***************************************************************************/
5240
53typedef struct _mos6530_t mos6530_t;
54struct _mos6530_t
41typedef struct _mos6530_port mos6530_port;
42struct _mos6530_port
5543{
44   devcb_resolved_read8      in_port_func;
45   devcb_resolved_write8      out_port_func;
46
47   UINT8            in;
48   UINT8            out;
49   UINT8            ddr;
50};
51
52
53typedef struct _mos6530_state mos6530_state;
54struct _mos6530_state
55{
5656   devcb_resolved_write_line   out_irq_func;
5757
58   devcb_resolved_read8      in_port_func[PORT_COUNT];
59   devcb_resolved_write8      out_port_func[PORT_COUNT];
58   mos6530_port   port[2];
6059
61   /* registers */
62   UINT8 output[PORT_COUNT];   /* output latches */
63   UINT8 ddr[PORT_COUNT];      /* DDR latches */
64   UINT8 counter;            /* counter */
65   int irq_enabled;
60   UINT8         irqstate;
61   UINT8         irqenable;
6662
67   /* timers */
68   emu_timer *timer;         /* timer */
63   UINT8         timershift;
64   UINT8         timerstate;
65   emu_timer *      timer;
66
67   UINT32         clock;
6968};
7069
70
71
7172/***************************************************************************
7273    INLINE FUNCTIONS
7374***************************************************************************/
7475
75INLINE mos6530_t *get_safe_token(running_device *device)
76/*-------------------------------------------------
77    get_safe_token - convert a device's token
78    into a mos6530_state
79-------------------------------------------------*/
80
81INLINE mos6530_state *get_safe_token(running_device *device)
7682{
7783   assert(device != NULL);
7884   assert(device->token != NULL);
79   return (mos6530_t *)device->token;
85   assert(device->type == MIOT6530);
86   return (mos6530_state *)device->token;
8087}
8188
82INLINE const mos6530_interface *get_interface(running_device *device)
89
90/*-------------------------------------------------
91    update_irqstate - update the IRQ state
92    based on interrupt enables
93-------------------------------------------------*/
94
95INLINE void update_irqstate(running_device *device)
8396{
84   assert(device != NULL);
85   assert(device->type == MOS6530);
86   return (const mos6530_interface *) device->baseconfig().static_config;
97   mos6530_state *miot = get_safe_token(device);
98   UINT8 out = miot->port[1].out;
99
100   if ( miot->irqenable )
101      out = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( out & 0x7F );
102
103   if (miot->port[1].out_port_func.target != NULL)
104      devcb_call_write8(&miot->port[1].out_port_func, 0, out);
105   else
106      logerror("6530MIOT chip %s: Port B is being written to but has no handler.\n", device->tag());
87107}
88108
89INLINE UINT8 read_port(mos6530_t *mos6530, int port)
109
110/*-------------------------------------------------
111    get_timer - return the current timer value
112-------------------------------------------------*/
113
114INLINE UINT8 get_timer(mos6530_state *miot)
90115{
91   UINT8 data = mos6530->output[port] & mos6530->ddr[port];
116   /* if idle, return 0 */
117   if (miot->timerstate == TIMER_IDLE)
118      return 0;
92119
93   if (mos6530->ddr[port] != 0xff)
94   {
95      data |= devcb_call_read8(&mos6530->in_port_func[port], 0) & ~mos6530->ddr[port];
96   }
120   /* if counting, return the number of ticks remaining */
121   else if (miot->timerstate == TIMER_COUNTING)
122      return attotime_to_ticks(timer_timeleft(miot->timer), miot->clock) >> miot->timershift;
97123
98   return data;
124   /* if finishing, return the number of ticks without the shift */
125   else
126      return attotime_to_ticks(timer_timeleft(miot->timer), miot->clock);
99127}
100128
101INLINE void write_port(mos6530_t *mos6530, int port, UINT8 data)
129
130/***************************************************************************
131    INTERNAL FUNCTIONS
132***************************************************************************/
133
134/*-------------------------------------------------
135    timer_end_callback - callback to process the
136    timer
137-------------------------------------------------*/
138
139static TIMER_CALLBACK( timer_end_callback )
102140{
103   mos6530->output[port] = data;
141   running_device *device = (running_device *)ptr;
142   mos6530_state *miot = get_safe_token(device);
104143
105   devcb_call_write8(&mos6530->out_port_func[port], 0, mos6530->output[port] & mos6530->ddr[port]);
144   assert(miot->timerstate != TIMER_IDLE);
145
146   /* if we finished counting, switch to the finishing state */
147   if (miot->timerstate == TIMER_COUNTING)
148   {
149      miot->timerstate = TIMER_FINISHING;
150      timer_adjust_oneshot(miot->timer, ticks_to_attotime(256, miot->clock), 0);
151
152      /* signal timer IRQ as well */
153      miot->irqstate |= TIMER_FLAG;
154      update_irqstate(device);
155   }
156
157   /* if we finished finishing, switch to the idle state */
158   else if (miot->timerstate == TIMER_FINISHING)
159   {
160      miot->timerstate = TIMER_IDLE;
161      timer_adjust_oneshot(miot->timer, attotime_never, 0);
162   }
106163}
107164
165
166
108167/***************************************************************************
109    IMPLEMENTATION
168    I/O ACCESS
110169***************************************************************************/
111170
112171/*-------------------------------------------------
113    TIMER_CALLBACK( timer_tick )
172    mos6530_w - master I/O write access
114173-------------------------------------------------*/
115174
116static TIMER_CALLBACK( timer_tick )
175WRITE8_DEVICE_HANDLER( mos6530_w )
117176{
118   running_device *device = (running_device *)ptr;
119   mos6530_t *mos6530 = get_safe_token(device);
177   mos6530_state *miot = get_safe_token(device);
120178
121   if (mos6530->counter == 0xff)
179   /* if A2 == 1, we are writing to the timer */
180   if (offset & 0x04)
122181   {
123      if (mos6530->irq_enabled)
182      static const UINT8 timershift[4] = { 0, 3, 6, 10 };
183      attotime curtime = timer_get_time(device->machine);
184      INT64 target;
185
186      /* A0-A1 contain the timer divisor */
187      miot->timershift = timershift[offset & 3];
188
189      /* A3 contains the timer IRQ enable */
190      if (offset & 8)
191         miot->irqenable |= TIMER_FLAG;
192      else
193         miot->irqenable &= ~TIMER_FLAG;
194
195      /* writes here clear the timer flag */
196      if (miot->timerstate != TIMER_FINISHING || get_timer(miot) != 0xff)
197         miot->irqstate &= ~TIMER_FLAG;
198      update_irqstate(device);
199
200      /* update the timer */
201      miot->timerstate = TIMER_COUNTING;
202      target = attotime_to_ticks(curtime, miot->clock) + 1 + (data << miot->timershift);
203      timer_adjust_oneshot(miot->timer, attotime_sub(ticks_to_attotime(target, miot->clock), curtime), 0);
204   }
205
206   /* if A2 == 0, we are writing to the I/O section */
207   else
208   {
209      /* A1 selects the port */
210      mos6530_port *port = &miot->port[(offset >> 1) & 1];
211
212      /* if A0 == 1, we are writing to the port's DDR */
213      if (offset & 1)
214         port->ddr = data;
215
216      /* if A0 == 0, we are writing to the port's output */
217      else
124218      {
125         /* interrupt */
126         logerror("MOS6530 '%s' Interrupt\n", device->tag());
127         devcb_call_write_line(&mos6530->out_irq_func, ASSERT_LINE);
219         UINT8 olddata = port->out;
220         port->out = data;
221
222         if ( ( offset & 2 ) && miot->irqenable )
223         {
224            olddata = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( olddata & 0x7F );
225            data = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( data & 0x7F );
226         }
227
228         if (port->out_port_func.target != NULL)
229            devcb_call_write8(&port->out_port_func, 0, data);
230         else
231            logerror("6530MIOT chip %s: Port %c is being written to but has no handler.  PC: %08X - %02X\n", device->tag(), 'A' + (offset & 1), cpu_get_pc(device->machine->firstcpu), data);
128232      }
129233   }
130
131   mos6530->counter--;
132234}
133235
236
134237/*-------------------------------------------------
135    mos6530_register_r - register read
238    mos6530_r - master I/O read access
136239-------------------------------------------------*/
137240
138241READ8_DEVICE_HANDLER( mos6530_r )
139242{
140   mos6530_t *mos6530 = get_safe_token(device);
141   int port = BIT(offset, 1);
243   mos6530_state *miot = get_safe_token(device);
244   UINT8 val = 0;
142245
143   UINT8 data = 0;
246   /* if A2 == 1 and A0 == 1, we are reading interrupt flags */
247   if ((offset & 0x05) == 0x05)
248   {
249      val = miot->irqstate;
250   }
144251
145   switch (offset & 0x07)
252   /* if A2 == 1 and A0 == 0, we are reading the timer */
253   else if ((offset & 0x05) == 0x04)
146254   {
147   case REGISTER_PORT_A:
148   case REGISTER_PORT_B:
149      data = read_port(mos6530, port);
150      break;
255      val = get_timer(miot);
151256
152   case REGISTER_PORT_A_DDR:
153   case REGISTER_PORT_B_DDR:
154      data = mos6530->ddr[port];
155      break;
257      /* A3 contains the timer IRQ enable */
258      if (offset & 8)
259         miot->irqenable |= TIMER_FLAG;
260      else
261         miot->irqenable &= ~TIMER_FLAG;
156262
157   default:
158      switch (offset & 0x05)
263      /* implicitly clears the timer flag */
264      if (miot->timerstate != TIMER_FINISHING || val != 0xff)
265         miot->irqstate &= ~TIMER_FLAG;
266      update_irqstate(device);
267   }
268
269   /* if A2 == 0 and A0 == anything, we are reading from ports */
270   else
271   {
272      /* A1 selects the port */
273      mos6530_port *port = &miot->port[(offset >> 1) & 1];
274
275      /* if A0 == 1, we are reading the port's DDR */
276      if (offset & 1)
277         val = port->ddr;
278
279      /* if A0 == 0, we are reading the port as an input */
280      else
159281      {
160      case REGISTER_TIMER:
161         data = mos6530->counter;
162         devcb_call_write_line(&mos6530->out_irq_func, CLEAR_LINE);
163         logerror("MOS6530 '%s' Interrupt Cleared\n", device->tag());
164         break;
282         UINT8   out = port->out;
165283
166      case REGISTER_INTERRUPT_FLAG:
167         break;
284         if ( ( offset & 2 ) && miot->irqenable )
285            out = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( out & 0x7F );
286
287         /* call the input callback if it exists */
288         if (port->in_port_func.target != NULL)
289         {
290            port->in = devcb_call_read8(&port->in_port_func, 0);
291         }
292         else
293            logerror("6530MIOT chip %s: Port %c is being read but has no handler.  PC: %08X\n", device->tag(), 'A' + (offset & 1), cpu_get_pc(device->machine->firstcpu));
294
295         /* apply the DDR to the result */
296         val = (out & port->ddr) | (port->in & ~port->ddr);
168297      }
169298   }
299   return val;
300}
170301
171   return data;
302
303/*-------------------------------------------------
304    mos6530_porta_in_set - set port A input
305    value
306-------------------------------------------------*/
307
308void mos6530_porta_in_set(running_device *device, UINT8 data, UINT8 mask)
309{
310   mos6530_state *miot = get_safe_token(device);
311   miot->port[0].in = (miot->port[0].in & ~mask) | (data & mask);
172312}
173313
314
174315/*-------------------------------------------------
175    mos6530_register_w - register write
316    mos6530_portb_in_set - set port B input
317    value
176318-------------------------------------------------*/
177319
178WRITE8_DEVICE_HANDLER( mos6530_w )
320void mos6530_portb_in_set(running_device *device, UINT8 data, UINT8 mask)
179321{
180   mos6530_t *mos6530 = get_safe_token(device);
181   int port = BIT(offset, 1);
322   mos6530_state *miot = get_safe_token(device);
323   miot->port[1].in = (miot->port[1].in & ~mask) | (data & mask);
324}
182325
183   switch (offset & 0x07)
184   {
185   case REGISTER_PORT_A:
186   case REGISTER_PORT_B:
187      if (LOG) logerror("MOS6530 '%s' Port %c Write %02x\n", device->tag(), 'A' + port, data);
188      write_port(mos6530, port, data);
189      break;
190326
191   case REGISTER_PORT_A_DDR:
192   case REGISTER_PORT_B_DDR:
193      if (LOG) logerror("MOS6530 '%s' Port %c DDR: %02x\n", device->tag(), 'A' + port, data);
194      mos6530->ddr[port] = data;
195      write_port(mos6530, port, data);
196      break;
327/*-------------------------------------------------
328    mos6530_porta_in_get - return port A input
329    value
330-------------------------------------------------*/
197331
198   case REGISTER_TIMER_1T:
199   case REGISTER_TIMER_8T:
200   case REGISTER_TIMER_64T:
201   case REGISTER_TIMER_1024T:
202      if (LOG) logerror("MOS6530 '%s' Timer: %02x, %uT, IRQ %s\n", device->tag(), data, PRESCALER[offset & 0x03], BIT(offset, 3) ? "enabled" : "disabled");
203      mos6530->counter = data;
204      mos6530->irq_enabled = BIT(offset, 3);
205      timer_adjust_periodic(mos6530->timer, attotime_zero, 0, ATTOTIME_IN_HZ(device->clock / PRESCALER[offset & 0x03]));
206      devcb_call_write_line(&mos6530->out_irq_func, CLEAR_LINE);
207      break;
208   }
332UINT8 mos6530_porta_in_get(running_device *device)
333{
334   mos6530_state *miot = get_safe_token(device);
335   return miot->port[0].in;
209336}
210337
338
211339/*-------------------------------------------------
212    DEVICE_START( mos6530 )
340    mos6530_portb_in_get - return port B input
341    value
213342-------------------------------------------------*/
214343
215static DEVICE_START( mos6530 )
344UINT8 mos6530_portb_in_get(running_device *device)
216345{
217   mos6530_t *mos6530 = (mos6530_t *)device->token;
218   const mos6530_interface *intf = get_interface(device);
346   mos6530_state *miot = get_safe_token(device);
347   return miot->port[1].in;
348}
219349
220   /* resolve callbacks */
221   devcb_resolve_write_line(&mos6530->out_irq_func, &intf->out_irq_func, device);
222   devcb_resolve_read8(&mos6530->in_port_func[PORT_A], &intf->in_pa_func, device);
223   devcb_resolve_read8(&mos6530->in_port_func[PORT_B], &intf->in_pb_func, device);
224   devcb_resolve_write8(&mos6530->out_port_func[PORT_A], &intf->out_pa_func, device);
225   devcb_resolve_write8(&mos6530->out_port_func[PORT_B], &intf->out_pb_func, device);
226350
227   /* allocate timer */
228   mos6530->timer = timer_alloc(device->machine, timer_tick, (void *)device);
351/*-------------------------------------------------
352    mos6530_porta_in_get - return port A output
353    value
354-------------------------------------------------*/
229355
230   /* register for state saving */
231   state_save_register_device_item_array(device, 0, mos6530->output);
232   state_save_register_device_item_array(device, 0, mos6530->ddr);
356UINT8 mos6530_porta_out_get(running_device *device)
357{
358   mos6530_state *miot = get_safe_token(device);
359   return miot->port[0].out;
233360}
234361
362
235363/*-------------------------------------------------
236    DEVICE_RESET( mos6530 )
364    mos6530_portb_in_get - return port B output
365    value
237366-------------------------------------------------*/
238367
368UINT8 mos6530_portb_out_get(running_device *device)
369{
370   mos6530_state *miot = get_safe_token(device);
371   return miot->port[1].out;
372}
373
374
375/***************************************************************************
376    DEVICE INTERFACE
377***************************************************************************/
378
379static DEVICE_START( mos6530 )
380{
381   mos6530_state *miot = get_safe_token(device);
382   const mos6530_interface *intf = (const mos6530_interface*)device->baseconfig().static_config;
383
384   /* validate arguments */
385   assert(device != NULL);
386   assert(device->tag() != NULL);
387
388   /* set static values */
389   miot->clock = device->clock;
390
391   /* resolve callbacks */
392   devcb_resolve_read8(&miot->port[0].in_port_func, &intf->in_pa_func, device);
393   devcb_resolve_read8(&miot->port[1].in_port_func, &intf->in_pb_func, device);
394   devcb_resolve_write8(&miot->port[0].out_port_func, &intf->out_pa_func, device);
395   devcb_resolve_write8(&miot->port[1].out_port_func, &intf->out_pb_func, device);
396
397   /* allocate timers */
398   miot->timer = timer_alloc(device->machine, timer_end_callback, (void *)device);
399
400   /* register for save states */
401   state_save_register_device_item(device, 0, miot->port[0].in);
402   state_save_register_device_item(device, 0, miot->port[0].out);
403   state_save_register_device_item(device, 0, miot->port[0].ddr);
404   state_save_register_device_item(device, 0, miot->port[1].in);
405   state_save_register_device_item(device, 0, miot->port[1].out);
406   state_save_register_device_item(device, 0, miot->port[1].ddr);
407
408   state_save_register_device_item(device, 0, miot->irqstate);
409   state_save_register_device_item(device, 0, miot->irqenable);
410
411   state_save_register_device_item(device, 0, miot->timershift);
412   state_save_register_device_item(device, 0, miot->timerstate);
413}
414
415
239416static DEVICE_RESET( mos6530 )
240417{
241   mos6530_t *mos6530 = (mos6530_t *)device->token;
418   mos6530_state *miot = get_safe_token(device);
242419
243   /* set ports to input mode */
244   mos6530->ddr[PORT_A] = 0;
245   mos6530->ddr[PORT_B] = 0;
420   /* reset I/O states */
421   miot->port[0].out = 0;
422   miot->port[0].ddr = 0;
423   miot->port[1].out = 0;
424   miot->port[1].ddr = 0;
425
426   /* reset IRQ states */
427   miot->irqenable = 0;
428   miot->irqstate = TIMER_FLAG;
429   update_irqstate(device);
430
431   /* reset timer states */
432   miot->timershift = 0;
433   miot->timerstate = TIMER_IDLE;
434   timer_adjust_oneshot(miot->timer, attotime_never, 0);
246435}
247436
248/*-------------------------------------------------
249    DEVICE_GET_INFO( mos6530 )
250-------------------------------------------------*/
251437
252438DEVICE_GET_INFO( mos6530 )
253439{
254440   switch (state)
255441   {
256442      /* --- the following bits of info are returned as 64-bit signed integers --- */
443      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(mos6530_state);         break;
257444      case DEVINFO_INT_INLINE_CONFIG_BYTES:         info->i = 0;                        break;
258445      case DEVINFO_INT_CLASS:                     info->i = DEVICE_CLASS_PERIPHERAL;         break;
259      case DEVINFO_INT_TOKEN_BYTES:               info->i = sizeof(mos6530_t);            break;
260446
261447      /* --- the following bits of info are returned as pointers to data or functions --- */
262448      case DEVINFO_FCT_START:                     info->start = DEVICE_START_NAME(mos6530);   break;
r7586r7587
268454      case DEVINFO_STR_FAMILY:                  strcpy(info->s, "MOS6500");               break;
269455      case DEVINFO_STR_VERSION:                  strcpy(info->s, "1.0");                  break;
270456      case DEVINFO_STR_SOURCE_FILE:               strcpy(info->s, __FILE__);               break;
271      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright the MESS Team");   break;
457      case DEVINFO_STR_CREDITS:                  strcpy(info->s, "Copyright MESS Team");      break;
272458   }
273459}
src/mess/machine/mos6530.h
r7586r7587
3030
3131**********************************************************************/
3232
33#ifndef __MOS6530__
34#define __MOS6530__
33#ifndef __MIOT6530_H__
34#define __MIOT6530_H__
3535
36#include "emu.h"
37#include "devcb.h"
38
3936/***************************************************************************
4037    MACROS / CONSTANTS
4138***************************************************************************/
r7586r7587
5653typedef struct _mos6530_interface mos6530_interface;
5754struct _mos6530_interface
5855{
59   devcb_write_line      out_irq_func;
60
6156   devcb_read8            in_pa_func;
6257   devcb_write8         out_pa_func;
6358
r7586r7587
6964    PROTOTYPES
7065***************************************************************************/
7166
72/* device interface */
7367DEVICE_GET_INFO( mos6530 );
7468
75/* register access */
7669READ8_DEVICE_HANDLER( mos6530_r );
7770WRITE8_DEVICE_HANDLER( mos6530_w );
7871
79/* memory access */
80/*
81READ8_DEVICE_HANDLER( mos6530_ram_r );
82WRITE8_DEVICE_HANDLER( mos6530_ram_w );
72void mos6530_porta_in_set(running_device *device, UINT8 data, UINT8 mask);
73void mos6530_portb_in_set(running_device *device, UINT8 data, UINT8 mask);
8374
84READ8_DEVICE_HANDLER( mos6530_rom_r );
85*/
75UINT8 mos6530_porta_in_get(running_device *device);
76UINT8 mos6530_portb_in_get(running_device *device);
77
78UINT8 mos6530_porta_out_get(running_device *device);
79UINT8 mos6530_portb_out_get(running_device *device);
80
8681#endif
src/mess/machine/c2040.c
r7586r7587
2929#include "formats/g64_dsk.h"
3030#include "machine/6522via.h"
3131#include "machine/6532riot.h"
32#include "machine/6530miot.h"
32#include "machine/mos6530.h"
3333#include "machine/ieee488.h"
3434
3535/***************************************************************************
r7586r7587
422422   ADDRESS_MAP_GLOBAL_MASK(0x1fff)
423423   AM_RANGE(0x0000, 0x003f) AM_MIRROR(0x0300) AM_RAM // 6530
424424   AM_RANGE(0x0040, 0x004f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6522_TAG, via_r, via_w)
425   AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6530_TAG, miot6530_r, miot6530_w)
425   AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6530_TAG, mos6530_r, mos6530_w)
426426   AM_RANGE(0x0400, 0x07ff) AM_RAM AM_SHARE("share1")
427427   AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("share2")
428428   AM_RANGE(0x0c00, 0x0fff) AM_RAM AM_SHARE("share3")
r7586r7587
455455   ADDRESS_MAP_GLOBAL_MASK(0x1fff)
456456   AM_RANGE(0x0000, 0x003f) AM_MIRROR(0x0300) AM_RAM // 6530
457457   AM_RANGE(0x0040, 0x004f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6522_TAG, via_r, via_w)
458   AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6530_TAG, miot6530_r, miot6530_w)
458   AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6530_TAG, mos6530_r, mos6530_w)
459459   AM_RANGE(0x0400, 0x07ff) AM_RAM AM_SHARE("share1")
460460   AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("share2")
461461   AM_RANGE(0x0c00, 0x0fff) AM_RAM AM_SHARE("share3")
r7586r7587
487487   ADDRESS_MAP_GLOBAL_MASK(0x1fff)
488488   AM_RANGE(0x0000, 0x003f) AM_MIRROR(0x0300) AM_RAM // 6530
489489   AM_RANGE(0x0040, 0x004f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6522_TAG, via_r, via_w)
490   AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6530_TAG, miot6530_r, miot6530_w)
490   AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6530_TAG, mos6530_r, mos6530_w)
491491   AM_RANGE(0x0400, 0x07ff) AM_RAM AM_SHARE("share1")
492492   AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("share2")
493493   AM_RANGE(0x0c00, 0x0fff) AM_RAM AM_SHARE("share3")
r7586r7587
519519   ADDRESS_MAP_GLOBAL_MASK(0x1fff)
520520   AM_RANGE(0x0000, 0x003f) AM_MIRROR(0x0300) AM_RAM // 6530
521521   AM_RANGE(0x0040, 0x004f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6522_TAG, via_r, via_w)
522   AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6530_TAG, miot6530_r, miot6530_w)
522   AM_RANGE(0x0080, 0x008f) AM_MIRROR(0x0330) AM_DEVREADWRITE(M6530_TAG, mos6530_r, mos6530_w)
523523   AM_RANGE(0x0400, 0x07ff) AM_RAM AM_SHARE("share1")
524524   AM_RANGE(0x0800, 0x0bff) AM_RAM AM_SHARE("share2")
525525   AM_RANGE(0x0c00, 0x0fff) AM_RAM AM_SHARE("share3")
r7586r7587
946946    mos6530_interface miot_intf uk3
947947-------------------------------------------------*/
948948
949static UINT8 pi_r(running_device *device, UINT8 olddata)
949static READ8_DEVICE_HANDLER( pi_r )
950950{
951951   /*
952952
r7586r7587
968968   return c2040->pi;
969969}
970970
971static void pi_w(running_device *device, UINT8 newdata, UINT8 olddata)
971static WRITE8_DEVICE_HANDLER( pi_w )
972972{
973973   /*
974974
r7586r7587
987987
988988   c2040_t *c2040 = get_safe_token(device->owner);
989989
990   c2040->pi = newdata;
990   c2040->pi = data;
991991}
992992
993static UINT8 miot_pb_r(running_device *device, UINT8 olddata)
993static READ8_DEVICE_HANDLER( miot_pb_r )
994994{
995995   /*
996996
r7586r7587
10201020   return data;
10211021}
10221022
1023static void miot_pb_w(running_device *device, UINT8 newdata, UINT8 olddata)
1023static WRITE8_DEVICE_HANDLER( miot_pb_w )
10241024{
10251025   /*
10261026
r7586r7587
10401040   c2040_t *c2040 = get_safe_token(device->owner);
10411041
10421042   /* drive select */
1043   c2040->drive = BIT(newdata, 0);
1043   c2040->drive = BIT(data, 0);
10441044
10451045   /* density select */
1046   int ds = (newdata >> 1) & 0x03;
1046   int ds = (data >> 1) & 0x03;
10471047
10481048   if (c2040->ds != ds)
10491049   {
r7586r7587
10521052   }
10531053
10541054   /* interrupt */
1055   if (c2040->miot_irq != BIT(newdata, 7))
1055   if (c2040->miot_irq != BIT(data, 7))
10561056   {
1057      cpu_set_input_line(c2040->cpu_fdc, M6502_IRQ_LINE, BIT(newdata, 7) ? CLEAR_LINE : ASSERT_LINE);
1058      c2040->miot_irq = BIT(newdata, 7);
1057      cpu_set_input_line(c2040->cpu_fdc, M6502_IRQ_LINE, BIT(data, 7) ? CLEAR_LINE : ASSERT_LINE);
1058      c2040->miot_irq = BIT(data, 7);
10591059   }
10601060}
10611061
1062static const miot6530_interface miot_intf =
1062static MOS6530_INTERFACE( miot_intf )
10631063{
1064   pi_r,
1065   miot_pb_r,
1066   pi_w,
1067   miot_pb_w
1064   DEVCB_HANDLER(pi_r),
1065   DEVCB_HANDLER(pi_w),
1066   DEVCB_HANDLER(miot_pb_r),
1067   DEVCB_HANDLER(miot_pb_w)
10681068};
10691069
10701070/*-------------------------------------------------
10711071    mos6530_interface c8050_miot_intf uk3
10721072-------------------------------------------------*/
10731073
1074static UINT8 c8050_miot_pb_r(running_device *device, UINT8 olddata)
1074static READ8_DEVICE_HANDLER( c8050_miot_pb_r )
10751075{
10761076   /*
10771077
r7586r7587
11071107   return data;
11081108}
11091109
1110static void c8050_miot_pb_w(running_device *device, UINT8 newdata, UINT8 olddata)
1110static WRITE8_DEVICE_HANDLER( c8050_miot_pb_w )
11111111{
11121112   /*
11131113
r7586r7587
11291129   /* drive select */
11301130   if ((device->owner->type == C8050) || (device->owner->type == C8250))
11311131   {
1132      c2040->drive = BIT(newdata, 0);
1132      c2040->drive = BIT(data, 0);
11331133   }
11341134
11351135   /* density select */
1136   int ds = (newdata >> 1) & 0x03;
1136   int ds = (data >> 1) & 0x03;
11371137
11381138   if (c2040->ds != ds)
11391139   {
r7586r7587
11441144   /* side select */
11451145   if ((device->owner->type == C8250) || (device->owner->type == SFD1001))
11461146   {
1147      c2040->side = !BIT(newdata, 4);
1147      c2040->side = !BIT(data, 4);
11481148   }
11491149
11501150   /* interrupt */
1151   if (c2040->miot_irq != BIT(newdata, 7))
1151   if (c2040->miot_irq != BIT(data, 7))
11521152   {
1153      cpu_set_input_line(c2040->cpu_fdc, M6502_IRQ_LINE, BIT(newdata, 7) ? CLEAR_LINE : ASSERT_LINE);
1154      c2040->miot_irq = BIT(newdata, 7);
1153      cpu_set_input_line(c2040->cpu_fdc, M6502_IRQ_LINE, BIT(data, 7) ? CLEAR_LINE : ASSERT_LINE);
1154      c2040->miot_irq = BIT(data, 7);
11551155   }
11561156}
11571157
1158static const miot6530_interface c8050_miot_intf =
1158static MOS6530_INTERFACE( c8050_miot_intf )
11591159{
1160   pi_r,
1161   c8050_miot_pb_r,
1162   pi_w,
1163   c8050_miot_pb_w
1160   DEVCB_HANDLER(pi_r),
1161   DEVCB_HANDLER(pi_w),
1162   DEVCB_HANDLER(c8050_miot_pb_r),
1163   DEVCB_HANDLER(c8050_miot_pb_w)
11641164};
11651165
11661166/*-------------------------------------------------
r7586r7587
12791279   MDRV_CPU_PROGRAM_MAP(c2040_fdc_map)
12801280
12811281   MDRV_VIA6522_ADD(M6522_TAG, XTAL_16MHz/16, via_intf)
1282   MDRV_MIOT6530_ADD(M6530_TAG, XTAL_16MHz/16, miot_intf)
1282   MDRV_MOS6530_ADD(M6530_TAG, XTAL_16MHz/16, miot_intf)
12831283
12841284   MDRV_FLOPPY_2_DRIVES_ADD(c2040_floppy_config)
12851285MACHINE_DRIVER_END
r7586r7587
13011301   MDRV_CPU_PROGRAM_MAP(c4040_fdc_map)
13021302
13031303   MDRV_VIA6522_ADD(M6522_TAG, XTAL_16MHz/16, via_intf)
1304   MDRV_MIOT6530_ADD(M6530_TAG, XTAL_16MHz/16, miot_intf)
1304   MDRV_MOS6530_ADD(M6530_TAG, XTAL_16MHz/16, miot_intf)
13051305
13061306   MDRV_FLOPPY_2_DRIVES_ADD(c4040_floppy_config)
13071307MACHINE_DRIVER_END
r7586r7587
13231323   MDRV_CPU_PROGRAM_MAP(c8050_fdc_map)
13241324
13251325   MDRV_VIA6522_ADD(M6522_TAG, XTAL_12MHz/12, c8050_via_intf)
1326   MDRV_MIOT6530_ADD(M6530_TAG, XTAL_12MHz/12, c8050_miot_intf)
1326   MDRV_MOS6530_ADD(M6530_TAG, XTAL_12MHz/12, c8050_miot_intf)
13271327
13281328   MDRV_FLOPPY_2_DRIVES_ADD(c8050_floppy_config)
13291329MACHINE_DRIVER_END
r7586r7587
13451345   MDRV_CPU_PROGRAM_MAP(c8050_fdc_map)
13461346
13471347   MDRV_VIA6522_ADD(M6522_TAG, XTAL_12MHz/12, c8050_via_intf)
1348   MDRV_MIOT6530_ADD(M6530_TAG, XTAL_12MHz/12, c8050_miot_intf)
1348   MDRV_MOS6530_ADD(M6530_TAG, XTAL_12MHz/12, c8050_miot_intf)
13491349
13501350   MDRV_FLOPPY_2_DRIVES_ADD(c8250_floppy_config)
13511351MACHINE_DRIVER_END
r7586r7587
13671367   MDRV_CPU_PROGRAM_MAP(sfd1001_fdc_map)
13681368
13691369   MDRV_VIA6522_ADD(M6522_TAG, XTAL_12MHz/12, c8050_via_intf)
1370   MDRV_MIOT6530_ADD(M6530_TAG, XTAL_12MHz/12, c8050_miot_intf)
1370   MDRV_MOS6530_ADD(M6530_TAG, XTAL_12MHz/12, c8050_miot_intf)
13711371
13721372   MDRV_FLOPPY_DRIVE_ADD(FLOPPY_0, c8250_floppy_config)
13731373MACHINE_DRIVER_END
src/mess/mess.mak
r7586r7587
435435   $(MESS_FORMATS)/pc_dsk.o   \
436436   $(MESS_FORMATS)/rk_cas.o   \
437437   $(MESS_FORMATS)/wavfile.o   \
438   $(MESS_MACHINE)/6530miot.o   \
439438   $(MESS_MACHINE)/6551.o      \
440439   $(MESS_MACHINE)/68901mfp.o   \
441440   $(MESS_MACHINE)/74145.o      \
src/mess/drivers/kim1.c
r7586r7587
8282#include "emu.h"
8383#include "cpu/m6502/m6502.h"
8484#include "sound/dac.h"
85#include "machine/6530miot.h"
85#include "machine/mos6530.h"
8686#include "devices/cassette.h"
8787#include "formats/kim1_cas.h"
8888#include "kim1.lh"
r7586r7587
9696
9797static ADDRESS_MAP_START ( kim1_map , ADDRESS_SPACE_PROGRAM, 8)
9898   AM_RANGE(0x0000, 0x03ff) AM_MIRROR(0xe000) AM_RAM
99   AM_RANGE(0x1700, 0x173f) AM_MIRROR(0xe000) AM_DEVREADWRITE("miot_u3", miot6530_r, miot6530_w )
100   AM_RANGE(0x1740, 0x177f) AM_MIRROR(0xe000) AM_DEVREADWRITE("miot_u2", miot6530_r, miot6530_w )
99   AM_RANGE(0x1700, 0x173f) AM_MIRROR(0xe000) AM_DEVREADWRITE("miot_u3", mos6530_r, mos6530_w )
100   AM_RANGE(0x1740, 0x177f) AM_MIRROR(0xe000) AM_DEVREADWRITE("miot_u2", mos6530_r, mos6530_w )
101101   AM_RANGE(0x1780, 0x17bf) AM_MIRROR(0xe000) AM_RAM
102102   AM_RANGE(0x17c0, 0x17ff) AM_MIRROR(0xe000) AM_RAM
103103   AM_RANGE(0x1800, 0x1bff) AM_MIRROR(0xe000) AM_ROM
r7586r7587
157157INPUT_PORTS_END
158158
159159
160static UINT8 kim1_u2_read_a(running_device *device, UINT8 olddata)
160static READ8_DEVICE_HANDLER( kim1_u2_read_a )
161161{
162162   UINT8   data = 0xff;
163163
r7586r7587
177177}
178178
179179
180static void kim1_u2_write_a(running_device *device, UINT8 newdata, UINT8 olddata)
180static WRITE8_DEVICE_HANDLER( kim1_u2_write_a )
181181{
182182   UINT8 idx = ( kim1_u2_port_b >> 1 ) & 0x0f;
183183
184184   if ( idx >= 4 && idx < 10 )
185185   {
186      if ( newdata & 0x80 )
186      if ( data & 0x80 )
187187      {
188         output_set_digit_value( idx-4, newdata & 0x7f );
188         output_set_digit_value( idx-4, data & 0x7f );
189189         kim1_led_time[idx - 4] = 15;
190190      }
191191   }
192192}
193193
194
195static UINT8 kim1_u2_read_b(running_device *device, UINT8 olddata)
194static READ8_DEVICE_HANDLER( kim1_u2_read_b )
196195{
197   if ( miot6530_portb_out_get(device) & 0x20 )
196   if ( mos6530_portb_out_get(device) & 0x20 )
198197      return 0xFF;
199198
200199   return 0x7F | ( kim1_311_output ^ 0x80 );
201200}
202201
203202
204static void kim1_u2_write_b(running_device *device, UINT8 newdata, UINT8 olddata)
203static WRITE8_DEVICE_HANDLER( kim1_u2_write_b )
205204{
206   kim1_u2_port_b = newdata;
205   kim1_u2_port_b = data;
207206
208   if ( newdata & 0x20 )
207   if ( data & 0x20 )
209208   {
210209      /* cassette write/speaker update */
211      cassette_output( devtag_get_device(device->machine, "cassette"), ( newdata & 0x80 ) ? -1.0 : 1.0 );
210      cassette_output( devtag_get_device(device->machine, "cassette"), ( data & 0x80 ) ? -1.0 : 1.0 );
212211   }
213212
214213   /* Set IRQ when bit 7 is cleared */
215214}
216215
217216
218static const miot6530_interface kim1_u2_miot6530_interface =
217static MOS6530_INTERFACE( kim1_u2_mos6530_interface )
219218{
220   kim1_u2_read_a,
221   kim1_u2_read_b,
222   kim1_u2_write_a,
223   kim1_u2_write_b
219   DEVCB_HANDLER(kim1_u2_read_a),
220   DEVCB_HANDLER(kim1_u2_write_a),
221   DEVCB_HANDLER(kim1_u2_read_b),
222   DEVCB_HANDLER(kim1_u2_write_b)
224223};
225224
226
227static UINT8 kim1_u3_read_a(running_device *device, UINT8 olddata)
225static MOS6530_INTERFACE( kim1_u3_mos6530_interface )
228226{
229   return 0xFF;
230}
231
232
233static void kim1_u3_write_a(running_device *device, UINT8 newdata, UINT8 olddata)
234{
235}
236
237
238static UINT8 kim1_u3_read_b(running_device *device, UINT8 olddata)
239{
240   return 0xFF;
241}
242
243
244static void kim1_u3_write_b(running_device *device, UINT8 newdata, UINT8 olddata)
245{
246}
247
248
249static const miot6530_interface kim1_u3_miot6530_interface =
250{
251   kim1_u3_read_a,
252   kim1_u3_read_b,
253   kim1_u3_write_a,
254   kim1_u3_write_b
227   DEVCB_NULL,
228   DEVCB_NULL,
229   DEVCB_NULL,
230   DEVCB_NULL
255231};
256232
257233
r7586r7587
331307   MDRV_MACHINE_START( kim1 )
332308   MDRV_MACHINE_RESET( kim1 )
333309
334   MDRV_MIOT6530_ADD( "miot_u2", 1000000, kim1_u2_miot6530_interface )
335   MDRV_MIOT6530_ADD( "miot_u3", 1000000, kim1_u3_miot6530_interface )
310   MDRV_MOS6530_ADD( "miot_u2", 1000000, kim1_u2_mos6530_interface )
311   MDRV_MOS6530_ADD( "miot_u3", 1000000, kim1_u3_mos6530_interface )
336312
337313   /* sound hardware */
338314   MDRV_SPEAKER_STANDARD_MONO("mono")
src/mess/drivers/mk2.c
r7586r7587
33******************************************************************************/
44
55#include "emu.h"
6#include "machine/6530miot.h"
6#include "machine/mos6530.h"
77#include "cpu/m6502/m6502.h"
88#include "sound/dac.h"
99#include "mk2.lh"
r7586r7587
4444static ADDRESS_MAP_START(mk2_mem , ADDRESS_SPACE_PROGRAM, 8)
4545   ADDRESS_MAP_GLOBAL_MASK(0x1FFF) // m6504
4646   AM_RANGE( 0x0000, 0x01ff) AM_RAM // 2 2111, should be mirrored
47   AM_RANGE( 0x0b00, 0x0b0f) AM_DEVREADWRITE("miot", miot6530_r, miot6530_w)
47   AM_RANGE( 0x0b00, 0x0b0f) AM_DEVREADWRITE("miot", mos6530_r, mos6530_w)
4848   AM_RANGE( 0x0b80, 0x0bbf) AM_RAM // rriot ram
4949   AM_RANGE( 0x0c00, 0x0fff) AM_ROM // rriot rom
5050   AM_RANGE( 0x1000, 0x1fff) AM_ROM
r7586r7587
9696   timer_pulse(machine, ATTOTIME_IN_HZ(60), NULL, 0, update_leds);
9797}
9898
99
100static UINT8 mk2_read_a(running_device *device, UINT8 olddata)
99static READ8_DEVICE_HANDLER( mk2_read_a )
101100{
102101   int data=0xff;
103102   int help=input_port_read(device->machine, "BLACK")|input_port_read(device->machine, "WHITE"); // looks like white and black keys are the same!
104103
105   switch (miot6530_portb_out_get(device)&0x7) {
104   switch (mos6530_portb_out_get(device)&0x7) {
106105   case 4:
107106      if (help&0x20) data&=~0x1; //F
108107      if (help&0x10) data&=~0x2; //E
r7586r7587
129128   return data;
130129}
131130
132
133static void mk2_write_a(running_device *device, UINT8 newdata, UINT8 olddata)
131static WRITE8_DEVICE_HANDLER( mk2_write_a )
134132{
135   int temp = miot6530_portb_out_get(device);
133   int temp = mos6530_portb_out_get(device);
136134
137135   switch(temp&0x3) {
138136   case 0: case 1: case 2: case 3:
139      mk2_led[temp&3]|=newdata;
137      mk2_led[temp&3]|=data;
140138   }
141139}
142140
143141
144static UINT8 mk2_read_b(running_device *device, UINT8 olddata)
142static READ8_DEVICE_HANDLER( mk2_read_b )
145143{
146144   return 0xff&~0x40; // chip select mapped to pb6
147145}
148146
149147
150static void mk2_write_b(running_device *device, UINT8 newdata, UINT8 olddata)
148static WRITE8_DEVICE_HANDLER( mk2_write_b )
151149{
152150   running_device *dac_device = devtag_get_device(device->machine, "dac");
153151
154   if ((newdata&0x06)==0x06)
155      dac_data_w(dac_device,newdata&1?80:0);
156   mk2_led[4]|=newdata;
152   if ((data&0x06)==0x06)
153      dac_data_w(dac_device,data&1?80:0);
154   mk2_led[4]|=data;
157155
158   cputag_set_input_line( device->machine, "maincpu", M6502_IRQ_LINE, (newdata & 0x80) ? CLEAR_LINE : ASSERT_LINE );
156   cputag_set_input_line( device->machine, "maincpu", M6502_IRQ_LINE, (data & 0x80) ? CLEAR_LINE : ASSERT_LINE );
159157}
160158
161
162static const miot6530_interface mk2_miot6530_interface =
159static MOS6530_INTERFACE( mk2_mos6530_interface )
163160{
164   mk2_read_a,
165   mk2_read_b,
166   mk2_write_a,
167   mk2_write_b
161   DEVCB_HANDLER(mk2_read_a),
162   DEVCB_HANDLER(mk2_write_a),
163   DEVCB_HANDLER(mk2_read_b),
164   DEVCB_HANDLER(mk2_write_b)
168165};
169166
170167
r7586r7587
179176    /* video hardware */
180177   MDRV_DEFAULT_LAYOUT(layout_mk2)
181178
182   MDRV_MIOT6530_ADD( "miot", 1000000, mk2_miot6530_interface )
179   MDRV_MOS6530_ADD( "miot", 1000000, mk2_mos6530_interface )
183180
184181   /* sound hardware */
185182   MDRV_SPEAKER_STANDARD_MONO("mono")

Previous 15994 Revisions Next


© 1998-2018 The MESS Team