Previous 199869 Revisions Next

r21685 Thursday 7th March, 2013 at 15:28:25 UTC by Curt Coder
Moved some files to where they belong. (nw)
[src/emu]emu.mak
[src/emu/machine]74145.c* 74145.h* at29040a.c* at29040a.h* at45dbxx.c* at45dbxx.h* ay31015.c* ay31015.h* er59256.c* er59256.h* mc68328.c* mc68328.h* mc6843.c* mc6843.h* mc6846.c* mc6846.h* mc6854.c* mc6854.h* mm58274c.c* mm58274c.h* mos6530.c* mos6530.h* pcf8593.c* pcf8593.h* upd7002.c* upd7002.h* wd11c00_17.c* wd11c00_17.h* wd2010.c* wd2010.h*
[src/emu/video]dl1416.c* dl1416.h* hd44352.c* hd44352.h* hd44780.c* hd44780.h* hd66421.c* hd66421.h* mc6847.c* mc6847.h* tms3556.c* tms3556.h* upd7220.c* upd7220.h*
[src/mess]mess.mak
[src/mess/drivers]c65.c
[src/mess/includes]c64_legacy.h c65.h
[src/mess/machine]74145.c 74145.h at29040a.c at29040a.h at45dbxx.c at45dbxx.h ay31015.c ay31015.h c64_legacy.c c65.c er59256.c er59256.h mc68328.c mc68328.h mc6843.c mc6843.h mc6846.c mc6846.h mc6854.c mc6854.h mm58274c.c mm58274c.h mos6530.c mos6530.h pcf8593.c pcf8593.h upd7002.c upd7002.h wd11c00_17.c wd11c00_17.h wd2010.c wd2010.h
[src/mess/video]dl1416.c dl1416.h hd44352.c hd44352.h hd44780.c hd44780.h hd66421.c hd66421.h mc6847.c mc6847.h tms3556.c tms3556.h upd7220.c upd7220.h

trunk/src/emu/emu.mak
r21684r21685
151151   $(EMUMACHINE)/6840ptm.o     \
152152   $(EMUMACHINE)/6850acia.o    \
153153   $(EMUMACHINE)/68681.o       \
154   $(EMUMACHINE)/n68681.o      \
155154   $(EMUMACHINE)/74123.o       \
155   $(EMUMACHINE)/74145.o       \
156156   $(EMUMACHINE)/74148.o       \
157157   $(EMUMACHINE)/74153.o       \
158158   $(EMUMACHINE)/74181.o       \
r21684r21685
169169   $(EMUMACHINE)/am9517a.o     \
170170   $(EMUMACHINE)/amigafdc.o    \
171171   $(EMUMACHINE)/at28c16.o     \
172   $(EMUMACHINE)/at29040a.o    \
173   $(EMUMACHINE)/at45dbxx.o    \
174   $(EMUMACHINE)/ay31015.o     \
172175   $(EMUMACHINE)/cdp1852.o     \
173176   $(EMUMACHINE)/cdp1871.o     \
174177   $(EMUMACHINE)/com8116.o     \
r21684r21685
182185   $(EMUMACHINE)/e0516.o       \
183186   $(EMUMACHINE)/eeprom.o      \
184187   $(EMUMACHINE)/er2055.o      \
188   $(EMUMACHINE)/er59256.o     \
185189   $(EMUMACHINE)/f3853.o       \
186190   $(EMUMACHINE)/fdc_pll.o     \
187191   $(EMUMACHINE)/generic.o     \
r21684r21685
204208   $(EMUMACHINE)/k033906.o     \
205209   $(EMUMACHINE)/k053252.o     \
206210   $(EMUMACHINE)/k056230.o     \
211   $(EMUMACHINE)/laserdsc.o    \
207212   $(EMUMACHINE)/latch8.o      \
208   $(EMUMACHINE)/laserdsc.o    \
209213   $(EMUMACHINE)/lc89510.o     \
214   $(EMUMACHINE)/ldpr8210.o    \
210215   $(EMUMACHINE)/ldstub.o      \
211   $(EMUMACHINE)/ldpr8210.o    \
212216   $(EMUMACHINE)/ldv1000.o     \
213217   $(EMUMACHINE)/ldvp931.o     \
214218   $(EMUMACHINE)/m6m80011ap.o  \
r21684r21685
218222   $(EMUMACHINE)/mb87078.o     \
219223   $(EMUMACHINE)/mc146818.o    \
220224   $(EMUMACHINE)/mc2661.o      \
225   $(EMUMACHINE)/mc6843.o      \
226   $(EMUMACHINE)/mc6846.o      \
221227   $(EMUMACHINE)/mc6852.o      \
228   $(EMUMACHINE)/mc6854.o      \
229   $(EMUMACHINE)/mc68328.o     \
222230   $(EMUMACHINE)/mc68901.o     \
223231   $(EMUMACHINE)/mccs1850.o    \
232   $(EMUMACHINE)/microtch.o    \
233   $(EMUMACHINE)/mm58274c.o    \
224234   $(EMUMACHINE)/mm74c922.o    \
225   $(EMUMACHINE)/microtch.o    \
226235   $(EMUMACHINE)/mos6526.o     \
227236   $(EMUMACHINE)/mos6529.o     \
237   $(EMUMACHINE)/mos6530.o     \
228238   $(EMUMACHINE)/mos6551.o     \
229239   $(EMUMACHINE)/msm5832.o     \
230240   $(EMUMACHINE)/msm58321.o    \
231241   $(EMUMACHINE)/msm6242.o     \
242   $(EMUMACHINE)/n68681.o      \
232243   $(EMUMACHINE)/ncr539x.o     \
244   $(EMUMACHINE)/net_lib.o     \
233245   $(EMUMACHINE)/netlist.o     \
234   $(EMUMACHINE)/net_lib.o     \
235246   $(EMUMACHINE)/nmc9306.o     \
236247   $(EMUMACHINE)/nscsi_bus.o   \
237248   $(EMUMACHINE)/nscsi_cd.o    \
238249   $(EMUMACHINE)/nscsi_hd.o    \
239250   $(EMUMACHINE)/nvram.o       \
240251   $(EMUMACHINE)/pc16552d.o    \
252   $(EMUMACHINE)/pcf8593.o     \
241253   $(EMUMACHINE)/pci.o         \
242254   $(EMUMACHINE)/pd4990a.o     \
243255   $(EMUMACHINE)/pic8259.o     \
r21684r21685
251263   $(EMUMACHINE)/rtc4543.o     \
252264   $(EMUMACHINE)/rtc65271.o    \
253265   $(EMUMACHINE)/rtc9701.o     \
266   $(EMUMACHINE)/s3520cf.o     \
254267   $(EMUMACHINE)/s3c2400.o     \
255268   $(EMUMACHINE)/s3c2410.o     \
256269   $(EMUMACHINE)/s3c2440.o     \
257   $(EMUMACHINE)/s3520cf.o     \
258270   $(EMUMACHINE)/saturn.o      \
259271   $(EMUMACHINE)/scsibus.o     \
260272   $(EMUMACHINE)/scsicb.o      \
r21684r21685
276288   $(EMUMACHINE)/tms9902.o     \
277289   $(EMUMACHINE)/upd1990a.o    \
278290   $(EMUMACHINE)/upd4701.o     \
291   $(EMUMACHINE)/upd7002.o     \
279292   $(EMUMACHINE)/upd7201.o     \
280293   $(EMUMACHINE)/upd765.o      \
281294   $(EMUMACHINE)/v3021.o       \
295   $(EMUMACHINE)/wd_fdc.o      \
296   $(EMUMACHINE)/wd11c00_17.o  \
282297   $(EMUMACHINE)/wd17xx.o      \
298   $(EMUMACHINE)/wd2010.o      \
283299   $(EMUMACHINE)/wd33c93.o     \
284   $(EMUMACHINE)/wd_fdc.o      \
285300   $(EMUMACHINE)/x2212.o       \
286301   $(EMUMACHINE)/x76f041.o     \
287302   $(EMUMACHINE)/x76f100.o     \
r21684r21685
298313   $(EMUVIDEO)/bufsprite.o     \
299314   $(EMUVIDEO)/cdp1861.o       \
300315   $(EMUVIDEO)/cdp1862.o       \
316   $(EMUVIDEO)/cgapal.o        \
301317   $(EMUVIDEO)/crt9007.o       \
302318   $(EMUVIDEO)/crt9021.o       \
303319   $(EMUVIDEO)/crt9212.o       \
320   $(EMUVIDEO)/dl1416.o        \
304321   $(EMUVIDEO)/dm9368.o        \
305322   $(EMUVIDEO)/ef9340_1.o      \
306323   $(EMUVIDEO)/generic.o       \
307324   $(EMUVIDEO)/h63484.o        \
308325   $(EMUVIDEO)/hd44102.o       \
326   $(EMUVIDEO)/hd44352.o       \
327   $(EMUVIDEO)/hd44780.o       \
309328   $(EMUVIDEO)/hd61830.o       \
310329   $(EMUVIDEO)/hd63484.o       \
330   $(EMUVIDEO)/hd66421.o       \
311331   $(EMUVIDEO)/huc6202.o       \
312332   $(EMUVIDEO)/huc6260.o       \
313333   $(EMUVIDEO)/huc6261.o       \
r21684r21685
320340   $(EMUVIDEO)/m50458.o        \
321341   $(EMUVIDEO)/mb90082.o       \
322342   $(EMUVIDEO)/mc6845.o        \
343   $(EMUVIDEO)/mc6847.o        \
323344   $(EMUVIDEO)/msm6255.o       \
324345   $(EMUVIDEO)/pc_cga.o        \
325   $(EMUVIDEO)/cgapal.o        \
326346   $(EMUVIDEO)/pc_vga.o        \
327347   $(EMUVIDEO)/poly.o          \
328348   $(EMUVIDEO)/psx.o           \
r21684r21685
336356   $(EMUVIDEO)/stvvdp2.o       \
337357   $(EMUVIDEO)/tlc34076.o      \
338358   $(EMUVIDEO)/tms34061.o      \
359   $(EMUVIDEO)/tms3556.o       \
339360   $(EMUVIDEO)/tms9927.o       \
340361   $(EMUVIDEO)/tms9928a.o      \
341362   $(EMUVIDEO)/upd3301.o       \
363   $(EMUVIDEO)/upd7220.o       \
342364   $(EMUVIDEO)/v9938.o         \
343365   $(EMUVIDEO)/vector.o        \
344366   $(EMUVIDEO)/voodoo.o        \
trunk/src/emu/machine/pcf8593.c
r0r21685
1/*********************************************************************
2
3    Philips PCF8593 CMOS clock/calendar circuit
4
5    (c) 2001-2007 Tim Schuerewegen
6
7*********************************************************************/
8
9#include "pcf8593.h"
10
11
12/***************************************************************************
13    PARAMETERS/CONSTANTS/MACROS
14***************************************************************************/
15
16#define LOG_LEVEL  1
17#define _logerror(level,x)  do { if (LOG_LEVEL > level) logerror x; } while (0)
18
19// get/set date
20#define RTC_GET_DATE_YEAR       ((m_data[5] >> 6) & 3)
21#define RTC_SET_DATE_YEAR(x)    m_data[5] = (m_data[5] & 0x3F) | (((x) % 4) << 6)
22#define RTC_GET_DATE_MONTH      bcd_to_integer( m_data[6])
23#define RTC_SET_DATE_MONTH(x)   m_data[6] = convert_to_bcd( x)
24#define RTC_GET_DATE_DAY        (bcd_to_integer( m_data[5] & 0x3F))
25#define RTC_SET_DATE_DAY(x)     m_data[5] = (m_data[5] & 0xC0) | convert_to_bcd( x)
26
27// get/set time
28#define RTC_GET_TIME_HOUR       bcd_to_integer( m_data[4])
29#define RTC_SET_TIME_HOUR(x)    m_data[4] = convert_to_bcd( x)
30#define RTC_GET_TIME_MINUTE     bcd_to_integer( m_data[3])
31#define RTC_SET_TIME_MINUTE(x)  m_data[3] = convert_to_bcd( x)
32#define RTC_GET_TIME_SECOND     bcd_to_integer( m_data[2])
33#define RTC_SET_TIME_SECOND(x)  m_data[2] = convert_to_bcd( x)
34
35
36//**************************************************************************
37//  GLOBAL VARIABLES
38//**************************************************************************
39
40const device_type PCF8593 = &device_creator<pcf8593_device>;
41
42
43//-------------------------------------------------
44//  pcf8593_device - constructor
45//-------------------------------------------------
46
47pcf8593_device::pcf8593_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
48   : device_t(mconfig, PCF8593, "PCF8593 RTC", tag, owner, clock),
49      device_rtc_interface(mconfig, *this),
50      device_nvram_interface(mconfig, *this)
51{
52}
53
54
55//-------------------------------------------------
56//  device_start - device-specific startup
57//-------------------------------------------------
58
59void pcf8593_device::device_start()
60{
61   _logerror( 0, ("pcf8593_init\n"));
62   memset(m_register, 0, sizeof(m_register));
63   m_timer = timer_alloc(TIMER_UPDATE_COUNTER);
64   m_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
65}
66
67//-------------------------------------------------
68//  device_reset - device-specific reset
69//-------------------------------------------------
70
71void pcf8593_device::device_reset()
72{
73   _logerror( 0, ("pcf8593_reset\n"));
74   m_pin_scl = 1;
75   m_pin_sda = 1;
76   m_active  = FALSE;
77   m_inp     = 0;
78   m_mode    = RTC_MODE_RECV;
79   m_bits    = 0;
80   m_pos     = 0;
81   clear_buffer_rx();
82   set_time(true, RTC_GET_DATE_YEAR, RTC_GET_DATE_MONTH, RTC_GET_DATE_DAY, 0, RTC_GET_TIME_HOUR, RTC_GET_TIME_MINUTE, RTC_GET_TIME_SECOND);
83}
84
85
86//-------------------------------------------------
87//  device_timer - handler timer events
88//-------------------------------------------------
89
90void pcf8593_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
91{
92   switch(id)
93   {
94      case TIMER_UPDATE_COUNTER:
95         _logerror( 2, ("pcf8593_timer_callback (%d)\n", param));
96         // check if counting is enabled
97         if (!(m_data[0] & 0x80))
98            advance_seconds();
99         break;
100   }
101}
102
103
104//-------------------------------------------------
105//  rtc_clock_updated -
106//-------------------------------------------------
107
108void pcf8593_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
109{
110   RTC_SET_TIME_SECOND(second);
111   RTC_SET_TIME_MINUTE(minute);
112   RTC_SET_TIME_HOUR(hour);
113   RTC_SET_DATE_DAY(day);
114   RTC_SET_DATE_MONTH(month);
115   RTC_SET_DATE_YEAR(year);
116}
117
118
119//-------------------------------------------------
120//  nvram_default - called to initialize NVRAM to
121//  its default state
122//-------------------------------------------------
123
124void pcf8593_device::nvram_default()
125{
126   memset(m_data, 0, sizeof(m_data));
127}
128
129//-------------------------------------------------
130//  nvram_read - called to read NVRAM from the
131//  .nv file
132//-------------------------------------------------
133
134void pcf8593_device::nvram_read(emu_file &file)
135{
136   file.read(m_data, sizeof(m_data));
137}
138
139
140//-------------------------------------------------
141//  nvram_write - called to write NVRAM to the
142//  .nv file
143//-------------------------------------------------
144
145void pcf8593_device::nvram_write(emu_file &file)
146{
147   file.write(m_data, sizeof(m_data));
148}
149
150
151
152/*-------------------------------------------------
153    pcf8593_pin_scl
154-------------------------------------------------*/
155
156WRITE_LINE_MEMBER(pcf8593_device::scl_w)
157{
158   // send bit
159   if ((m_active) && (!m_pin_scl) && (state))
160   {
161      switch (m_mode)
162      {
163         // HOST -> RTC
164         case RTC_MODE_RECV :
165         {
166            // get bit
167            if (m_pin_sda) m_data_recv[m_data_recv_index] = m_data_recv[m_data_recv_index] | (0x80 >> m_bits);
168            m_bits++;
169            // bit 9 = end
170            if (m_bits > 8)
171            {
172               _logerror( 2, ("pcf8593_write_byte(%02X)\n", m_data_recv[m_data_recv_index]));
173               // enter receive mode when 1st byte = 0xA3
174               if ((m_data_recv[0] == 0xA3) && (m_data_recv_index == 0))
175               {
176                  m_mode = RTC_MODE_SEND;
177               }
178               // A2 + xx = "read from pos xx" command
179               if ((m_data_recv[0] == 0xA2) && (m_data_recv_index == 1))
180               {
181                  m_pos = m_data_recv[1];
182               }
183               // A2 + xx + .. = write byte
184               if ((m_data_recv[0] == 0xA2) && (m_data_recv_index >= 2))
185               {
186                  UINT8 rtc_pos, rtc_val;
187                  rtc_pos = m_data_recv[1] + (m_data_recv_index - 2);
188                  rtc_val = m_data_recv[m_data_recv_index];
189                  //if (rtc_pos == 0) rtc_val = rtc_val & 3; // what is this doing here?
190                  m_data[rtc_pos] = rtc_val;
191                  set_time(false, RTC_GET_DATE_YEAR, RTC_GET_DATE_MONTH, RTC_GET_DATE_DAY, 0, RTC_GET_TIME_HOUR, RTC_GET_TIME_MINUTE, RTC_GET_TIME_SECOND);
192               }
193               // next byte
194               m_bits = 0;
195               m_data_recv_index++;
196            }
197         }
198         break;
199         // RTC -> HOST
200         case RTC_MODE_SEND :
201         {
202            // set bit
203            m_inp = (m_data[m_pos] >> (7 - m_bits)) & 1;
204            m_bits++;
205            // bit 9 = end
206            if (m_bits > 8)
207            {
208               _logerror( 2, ("pcf8593_read_byte(%02X)\n", m_data[m_pos]));
209               // end ?
210               if (m_pin_sda)
211               {
212                  _logerror( 2, ("pcf8593 end\n"));
213                  m_mode = RTC_MODE_RECV;
214                  clear_buffer_rx();
215               }
216               // next byte
217               m_bits = 0;
218               m_pos++;
219            }
220         }
221         break;
222      }
223   }
224   // save scl
225   m_pin_scl = state;
226}
227
228
229
230/*-------------------------------------------------
231    pcf8593_pin_sda_w
232-------------------------------------------------*/
233
234WRITE_LINE_MEMBER(pcf8593_device::sda_w)
235{
236   // clock is high
237   if (m_pin_scl)
238   {
239      // log init I2C
240      if (state) _logerror( 1, ("pcf8593 init i2c\n"));
241      // start condition (high to low when clock is high)
242      if ((!state) && (m_pin_sda))
243      {
244         _logerror( 1, ("pcf8593 start condition\n"));
245         m_active          = TRUE;
246         m_bits            = 0;
247         m_data_recv_index = 0;
248         clear_buffer_rx();
249         //m_pos = 0;
250      }
251      // stop condition (low to high when clock is high)
252      if ((state) && (!m_pin_sda))
253      {
254         _logerror( 1, ("pcf8593 stop condition\n"));
255         m_active = FALSE;
256      }
257   }
258   // save sda
259   m_pin_sda = state;
260}
261
262
263
264/*-------------------------------------------------
265    pcf8593_pin_sda_r
266-------------------------------------------------*/
267
268READ_LINE_MEMBER(pcf8593_device::sda_r)
269{
270   return m_inp;
271}
272
273
274
275/*-------------------------------------------------
276    pcf8593_clear_buffer_rx
277-------------------------------------------------*/
278
279void pcf8593_device::clear_buffer_rx()
280{
281   memset(&m_data_recv[0], 0, sizeof( m_data_recv));
282   m_data_recv_index = 0;
283}
Property changes on: trunk/src/emu/machine/pcf8593.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/pcf8593.h
r0r21685
1/*********************************************************************
2
3    Philips PCF8593 CMOS clock/calendar circuit
4
5    (c) 2001-2007 Tim Schuerewegen
6
7*********************************************************************/
8
9#ifndef __PCF8593_H__
10#define __PCF8593_H__
11
12#include "emu.h"
13
14
15//**************************************************************************
16//  INTERFACE CONFIGURATION MACROS
17//**************************************************************************
18
19#define MCFG_PCF8593_ADD(_tag) \
20   MCFG_DEVICE_ADD(_tag, PCF8593, 0)
21
22#define MCFG_PCF8593_REMOVE(_tag) \
23   MCFG_DEVICE_REMOVE(_tag)
24
25
26// ======================> pcf8593_device
27
28class pcf8593_device :  public device_t,
29                  public device_rtc_interface,
30                  public device_nvram_interface
31{
32public:
33   pcf8593_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
34
35   DECLARE_WRITE_LINE_MEMBER(scl_w);
36   DECLARE_WRITE_LINE_MEMBER(sda_w);
37   DECLARE_READ_LINE_MEMBER(sda_r);
38
39protected:
40   // device-level overrides
41   virtual void device_start();
42   virtual void device_reset();
43   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
44
45   // device_rtc_interface overrides
46   virtual bool rtc_feature_y2k() { return true; }
47   virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second);
48
49   // device_nvram_interface overrides
50   virtual void nvram_default();
51   virtual void nvram_read(emu_file &file);
52   virtual void nvram_write(emu_file &file);
53
54private:
55   void clear_buffer_rx();
56
57   static const device_timer_id TIMER_UPDATE_COUNTER = 0;
58
59   // internal state
60   UINT8       m_data[16];
61   int         m_pin_scl;
62   int         m_pin_sda;
63   int         m_inp;
64   int         m_active;
65   int         m_bits;
66   UINT8       m_data_recv_index;
67   UINT8       m_data_recv[50];
68   UINT8       m_mode;
69   UINT8       m_pos;
70   emu_timer * m_timer;
71   enum        { RTC_MODE_NONE, RTC_MODE_SEND, RTC_MODE_RECV };
72};
73
74// device type definition
75extern const device_type PCF8593;
76
77#endif /* __PCF8593_H__ */
Property changes on: trunk/src/emu/machine/pcf8593.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/mc6843.c
r0r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2007
4
5  Motorola 6843 Floppy Disk Controller emulation.
6
7**********************************************************************/
8
9/*
10  Main MC 6843 features are:
11   - single density floppies
12   - IBM 3740 compatible
13   - DMA-able
14   - high-level commands (including multi-sector read/write)
15
16   CLONES: HD 46503S seems to be a clone of MC 6843
17
18   BUGS
19   The driver was designed with Thomson computer emulation in mind
20   (CD 90-015 5"1/4 floppy controller) and works in this context.
21   It might work in other contexts but has currently shortcomings:
22   - DMA is not emulated
23   - Free-Format Read is not emulated
24   - Free-Format Write only supports track formatting, in a specific
25   format (FWF=1, Thomson-like sector formats)
26   - very rough timing: basically, there is a fixed delay between
27   a command request (CMR write) and its response (first byte
28   available, seek complete, etc.); there is no delay between
29   read / write
30 */
31
32
33#include "emu.h"
34#include "mc6843.h"
35#include "imagedev/flopdrv.h"
36
37
38/******************* parameters ******************/
39
40#define VERBOSE 0
41
42
43/******************* internal chip data structure ******************/
44
45struct mc6843_t
46{
47   /* interface */
48   const mc6843_interface* iface;
49
50   /* registers */
51   UINT8 CTAR;       /* current track */
52   UINT8 CMR;        /* command */
53   UINT8 ISR;        /* interrupt status */
54   UINT8 SUR;        /* set-up */
55   UINT8 STRA;       /* status */
56   UINT8 STRB;       /* status */
57   UINT8 SAR;        /* sector address */
58   UINT8 GCR;        /* general count */
59   UINT8 CCR;        /* CRC control */
60   UINT8 LTAR;       /* logical address track (=track destination) */
61
62   /* internal state */
63   UINT8  drive;
64   UINT8  side;
65   UINT8  data[128];   /* sector buffer */
66   UINT32 data_size;   /* size of data */
67   UINT32 data_idx;    /* current read/write position in data */
68   UINT32 data_id;     /* chrd_id for sector write */
69   UINT8  index_pulse;
70
71   /* trigger delayed actions (bottom halves) */
72   emu_timer* timer_cont;
73
74};
75
76
77
78/* macro-command numbers */
79#define CMD_STZ 0x2 /* seek track zero */
80#define CMD_SEK 0x3 /* seek */
81#define CMD_SSR 0x4 /* single sector read */
82#define CMD_SSW 0x5 /* single sector write */
83#define CMD_RCR 0x6 /* read CRC */
84#define CMD_SWD 0x7 /* single sector write with delete data mark */
85#define CMD_MSW 0xd /* multiple sector write */
86#define CMD_MSR 0xc /* multiple sector read */
87#define CMD_FFW 0xb /* free format write */
88#define CMD_FFR 0xa /* free format read */
89
90/* coarse delays */
91#define DELAY_SEEK   attotime::from_usec( 100 )  /* track seek time */
92#define DELAY_ADDR   attotime::from_usec( 100 )  /* search-address time */
93
94
95
96static const char *const mc6843_cmd[16] =
97{
98   "---", "---", "STZ", "SEK", "SSR", "SSW", "RCR", "SWD",
99   "---", "---", "FFR", "FFW", "MSR", "MSW", "---", "---",
100};
101
102
103/******************* utility function and macros ********************/
104
105#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
106
107
108
109INLINE mc6843_t* get_safe_token( device_t *device )
110{
111   assert( device != NULL );
112   assert( device->type() == MC6843 );
113   return (mc6843_t*) downcast<mc6843_device *>(device)->token();
114}
115
116
117/************************** floppy interface ****************************/
118
119
120
121static device_t* mc6843_floppy_image ( device_t *device )
122{
123   mc6843_t* mc6843 = get_safe_token( device );
124   return floppy_get_device( device->machine(), mc6843->drive );
125}
126
127
128
129void mc6843_set_drive( device_t *device, int drive )
130{
131   mc6843_t* mc6843 = get_safe_token( device );
132   mc6843->drive = drive;
133}
134
135
136
137void mc6843_set_side( device_t *device, int side )
138{
139   mc6843_t* mc6843 = get_safe_token( device );
140   mc6843->side = side;
141}
142
143
144
145/* called after ISR or STRB has changed */
146static void mc6843_status_update( device_t *device )
147{
148   mc6843_t* mc6843 = get_safe_token( device );
149   int irq = 0;
150
151   /* ISR3 */
152   if ( (mc6843->CMR & 0x40) || ! mc6843->STRB )
153      mc6843->ISR &= ~8;
154   else
155      mc6843->ISR |=  8;
156
157   /* interrupts */
158   if ( mc6843->ISR & 4 )
159      irq = 1; /* unmaskable */
160   if ( ! (mc6843->CMR & 0x80) )
161   {
162      /* maskable */
163      if ( mc6843->ISR & ~4 )
164         irq = 1;
165   }
166
167   if ( mc6843->iface->irq_func )
168   {
169      mc6843->iface->irq_func( device, irq );
170      LOG(( "mc6843_status_update: irq=%i (CMR=%02X, ISR=%02X)\n", irq, mc6843->CMR, mc6843->ISR ));
171   }
172}
173
174
175void mc6843_set_index_pulse  ( device_t *device, int index_pulse )
176{
177   mc6843_t* mc6843 = get_safe_token( device );
178   mc6843->index_pulse = index_pulse;
179}
180
181
182/* called at end of command */
183static void mc6843_cmd_end( device_t *device )
184{
185   mc6843_t* mc6843 = get_safe_token( device );
186   int cmd = mc6843->CMR & 0x0f;
187   if ( ( cmd == CMD_STZ ) || ( cmd == CMD_SEK ) )
188   {
189      mc6843->ISR |= 0x02; /* set Settling Time Complete */
190   }
191   else
192   {
193      mc6843->ISR |= 0x01;  /* set Macro Command Complete */
194   }
195   mc6843->STRA &= ~0x80; /* clear Busy */
196   mc6843->CMR  &=  0xf0; /* clear command */
197   mc6843_status_update( device );
198}
199
200
201
202/* Seek Track Zero bottom half */
203static void mc6843_finish_STZ( device_t *device )
204{
205   mc6843_t* mc6843 = get_safe_token( device );
206   device_t* img = mc6843_floppy_image( device );
207   int i;
208
209   /* seek to track zero */
210   for ( i=0; i<83; i++ )
211   {
212      if (floppy_tk00_r(img) == CLEAR_LINE)
213         break;
214      floppy_drive_seek( img, -1 );
215   }
216
217   LOG(( "%f mc6843_finish_STZ: actual=%i\n", device->machine().time().as_double(), floppy_drive_get_current_track( img ) ));
218
219   /* update state */
220   mc6843->CTAR = 0;
221   mc6843->GCR = 0;
222   mc6843->SAR = 0;
223   mc6843->STRB |= floppy_tk00_r(img) << 4;
224
225   mc6843_cmd_end( device );
226}
227
228
229
230/* Seek bottom half */
231static void mc6843_finish_SEK( device_t *device )
232{
233   mc6843_t* mc6843 = get_safe_token( device );
234   device_t* img = mc6843_floppy_image( device );
235
236   /* seek to track */
237   floppy_drive_seek( img, mc6843->GCR - mc6843->CTAR );
238
239   LOG(( "%f mc6843_finish_SEK: from %i to %i (actual=%i)\n", device->machine().time().as_double(), mc6843->CTAR, mc6843->GCR, floppy_drive_get_current_track( img ) ));
240
241   /* update state */
242   mc6843->CTAR = mc6843->GCR;
243   mc6843->SAR = 0;
244   mc6843_cmd_end( device );
245}
246
247
248
249/* preamble to all sector read / write commands, returns 1 if found */
250static int mc6843_address_search( device_t *device, chrn_id* id )
251{
252   mc6843_t* mc6843 = get_safe_token( device );
253   device_t* img = mc6843_floppy_image( device );
254   int r = 0;
255
256   while ( 1 )
257   {
258      if ( ( ! floppy_drive_get_next_id( img, mc6843->side, id ) ) || ( id->flags & ID_FLAG_CRC_ERROR_IN_ID_FIELD ) || ( id->N != 0 ) )
259      {
260         /* read address error */
261         LOG(( "%f mc6843_address_search: get_next_id failed\n", device->machine().time().as_double() ));
262         mc6843->STRB |= 0x0a; /* set CRC error & Sector Address Undetected */
263         mc6843_cmd_end( device );
264         return 0;
265      }
266
267      if ( id->C != mc6843->LTAR )
268      {
269         /* track mismatch */
270         LOG(( "%f mc6843_address_search: track mismatch: logical=%i real=%i\n", device->machine().time().as_double(), mc6843->LTAR, id->C ));
271         mc6843->data[0] = id->C; /* make the track number available to the CPU */
272         mc6843->STRA |= 0x20;    /* set Track Not Equal */
273         mc6843_cmd_end( device );
274         return 0;
275      }
276
277      if ( id->R == mc6843->SAR )
278      {
279         /* found! */
280         LOG(( "%f mc6843_address_search: sector %i found on track %i\n", device->machine().time().as_double(), id->R, id->C ));
281         if ( ! (mc6843->CMR & 0x20) )
282         {
283            mc6843->ISR |= 0x04; /* if no DMA, set Status Sense */
284         }
285         return 1;
286      }
287
288      if ( floppy_drive_get_flag_state( img, FLOPPY_DRIVE_INDEX ) )
289      {
290         r++;
291         if ( r >= 4 )
292         {
293            /* time-out after 3 full revolutions */
294            LOG(( "%f mc6843_address_search: no sector %i found after 3 revolutions\n", device->machine().time().as_double(), mc6843->SAR ));
295            mc6843->STRB |= 0x08; /* set Sector Address Undetected */
296            mc6843_cmd_end( device );
297            return 0;
298         }
299      }
300   }
301
302   return 0; /* unreachable */
303}
304
305
306
307/* preamble specific to read commands (adds extra checks) */
308static int mc6843_address_search_read( device_t *device, chrn_id* id )
309{
310   mc6843_t* mc6843 = get_safe_token( device );
311   if ( ! mc6843_address_search( device, id ) )
312      return 0;
313
314   if ( id->flags & ID_FLAG_CRC_ERROR_IN_DATA_FIELD )
315   {
316      LOG(( "%f mc6843_address_search_read: data CRC error\n", device->machine().time().as_double() ));
317      mc6843->STRB |= 0x06; /* set CRC error & Data Mark Undetected */
318      mc6843_cmd_end( device );
319      return 0;
320   }
321
322   if ( id->flags & ID_FLAG_DELETED_DATA )
323   {
324      LOG(( "%f mc6843_address_search_read: deleted data\n", device->machine().time().as_double() ));
325      mc6843->STRA |= 0x02; /* set Delete Data Mark Detected */
326   }
327
328   return 1;
329}
330
331
332
333
334/* Read CRC bottom half */
335static void mc6843_finish_RCR( device_t *device )
336{
337   chrn_id id;
338   if ( ! mc6843_address_search_read( device, &id ) )
339      return;
340   mc6843_cmd_end( device );
341}
342
343
344
345/* Single / Multiple Sector Read bottom half */
346static void mc6843_cont_SR( device_t *device )
347{
348   mc6843_t* mc6843 = get_safe_token( device );
349   chrn_id id;
350   device_t* img = mc6843_floppy_image( device );
351
352   /* sector seek */
353   if ( ! mc6843_address_search_read( device, &id ) )
354      return;
355
356   /* sector read */
357   floppy_drive_read_sector_data( img, mc6843->side, id.data_id, mc6843->data, 128 );
358   mc6843->data_idx = 0;
359   mc6843->data_size = 128;
360   mc6843->STRA |= 0x01;     /* set Data Transfer Request */
361   mc6843_status_update( device );
362}
363
364
365
366/* Single / Multiple Sector Write bottom half */
367static void mc6843_cont_SW( device_t *device )
368{
369   mc6843_t* mc6843 = get_safe_token( device );
370   chrn_id id;
371
372   /* sector seek */
373   if ( ! mc6843_address_search( device, &id ) )
374      return;
375
376   /* setup sector write buffer */
377   mc6843->data_idx = 0;
378   mc6843->data_size = 128;
379   mc6843->STRA |= 0x01;         /* set Data Transfer Request */
380   mc6843->data_id = id.data_id; /* for subsequent write sector command */
381   mc6843_status_update( device );
382}
383
384
385
386/* bottom halves, called to continue / finish a command after some delay */
387static TIMER_CALLBACK( mc6843_cont )
388{
389   device_t* device = (device_t*) ptr;
390   mc6843_t* mc6843 = get_safe_token( device );
391   int cmd = mc6843->CMR & 0x0f;
392
393   LOG(( "%f mc6843_cont: timer called for cmd=%s(%i)\n", device->machine().time().as_double(), mc6843_cmd[cmd], cmd ));
394
395   mc6843->timer_cont->adjust( attotime::never );
396
397   switch ( cmd )
398   {
399   case CMD_STZ: mc6843_finish_STZ( device ); break;
400   case CMD_SEK: mc6843_finish_SEK( device ); break;
401   case CMD_SSR: mc6843_cont_SR( device );    break;
402   case CMD_SSW: mc6843_cont_SW( device );    break;
403   case CMD_RCR: mc6843_finish_RCR( device ); break;
404   case CMD_SWD: mc6843_cont_SW( device );    break;
405   case CMD_MSW: mc6843_cont_SW( device );    break;
406   case CMD_MSR: mc6843_cont_SR( device );    break;
407   }
408}
409
410
411
412/************************** CPU interface ****************************/
413
414
415
416READ8_DEVICE_HANDLER ( mc6843_r )
417{
418   mc6843_t* mc6843 = get_safe_token( device );
419   UINT8 data = 0;
420
421   switch ( offset ) {
422   case 0: /* Data Input Register (DIR) */
423   {
424      int cmd = mc6843->CMR & 0x0f;
425
426      LOG(( "%f $%04x mc6843_r: data input cmd=%s(%i), pos=%i/%i, GCR=%i, ",
427            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ),
428            mc6843_cmd[cmd], cmd, mc6843->data_idx,
429            mc6843->data_size, mc6843->GCR ));
430
431      if ( cmd == CMD_SSR || cmd == CMD_MSR )
432      {
433         /* sector read */
434         assert( mc6843->data_size > 0 );
435         assert( mc6843->data_idx < mc6843->data_size );
436         assert( mc6843->data_idx < sizeof(mc6843->data) );
437         data = mc6843->data[ mc6843->data_idx ];
438         mc6843->data_idx++;
439
440         if ( mc6843->data_idx >= mc6843->data_size )
441         {
442            /* end of sector read */
443
444            mc6843->STRA &= ~0x01; /* clear Data Transfer Request */
445
446            if ( cmd == CMD_MSR )
447            {
448               /* schedule next sector in multiple sector read */
449               mc6843->GCR--;
450               mc6843->SAR++;
451               if ( mc6843->GCR == 0xff )
452               {
453                  mc6843_cmd_end( device );
454               }
455               else if ( mc6843->SAR > 26 )
456
457               {
458                  mc6843->STRB |= 0x08; /* set Sector Address Undetected */
459                  mc6843_cmd_end( device );
460               }
461               else
462               {
463                  mc6843->timer_cont->adjust( DELAY_ADDR );
464               }
465            }
466            else
467            {
468               mc6843_cmd_end( device );
469            }
470         }
471      }
472      else if ( cmd == 0 )
473      {
474         data = mc6843->data[0];
475      }
476      else
477      {
478         /* XXX TODO: other read modes */
479         data = mc6843->data[0];
480         logerror( "$%04x mc6843 read in unsupported command mode %i\n", space.machine().firstcpu->pcbase( ), cmd );
481      }
482
483      LOG(( "data=%02X\n", data ));
484
485      break;
486   }
487
488   case 1: /* Current-Track Address Register (CTAR) */
489      data = mc6843->CTAR;
490      LOG(( "%f $%04x mc6843_r: read CTAR %i (actual=%i)\n",
491            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
492            floppy_drive_get_current_track( mc6843_floppy_image( device ) ) ));
493      break;
494
495   case 2: /* Interrupt Status Register (ISR) */
496      data = mc6843->ISR;
497      LOG(( "%f $%04x mc6843_r: read ISR %02X: cmd=%scomplete settle=%scomplete sense-rq=%i STRB=%i\n",
498            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
499            (data & 1) ? "" : "not-" , (data & 2) ? "" : "not-",
500            (data >> 2) & 1, (data >> 3) & 1 ));
501
502      /* reset */
503      mc6843->ISR &= 8; /* keep STRB */
504      mc6843_status_update( device );
505      break;
506
507   case 3: /* Status Register A (STRA) */
508   {
509      /* update */
510      device_t* img = mc6843_floppy_image( device );
511      int flag = floppy_drive_get_flag_state( img, FLOPPY_DRIVE_READY);
512      mc6843->STRA &= 0xa3;
513      if ( flag & FLOPPY_DRIVE_READY )
514         mc6843->STRA |= 0x04;
515
516      mc6843->STRA |= !floppy_tk00_r(img) << 3;
517      mc6843->STRA |= !floppy_wpt_r(img) << 4;
518
519      if ( mc6843->index_pulse )
520         mc6843->STRA |= 0x40;
521
522      data = mc6843->STRA;
523      LOG(( "%f $%04x mc6843_r: read STRA %02X: data-rq=%i del-dta=%i ready=%i t0=%i wp=%i trk-dif=%i idx=%i busy=%i\n",
524            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
525            data & 1, (data >> 1) & 1, (data >> 2) & 1, (data >> 3) & 1,
526            (data >> 4) & 1, (data >> 5) & 1, (data >> 6) & 1, (data >> 7) & 1 ));
527      break;
528   }
529
530   case 4: /* Status Register B (STRB) */
531      data = mc6843->STRB;
532      LOG(( "%f $%04x mc6843_r: read STRB %02X: data-err=%i CRC-err=%i dta--mrk-err=%i sect-mrk-err=%i seek-err=%i fi=%i wr-err=%i hard-err=%i\n",
533            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
534            data & 1, (data >> 1) & 1, (data >> 2) & 1, (data >> 3) & 1,
535            (data >> 4) & 1, (data >> 5) & 1, (data >> 6) & 1, (data >> 7) & 1 ));
536
537      /* (partial) reset */
538      mc6843->STRB &= ~0xfb;
539      mc6843_status_update( device );
540      break;
541
542   case 7: /* Logical-Track Address Register (LTAR) */
543      data = mc6843->LTAR;
544      LOG(( "%f $%04x mc6843_r: read LTAR %i (actual=%i)\n",
545            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
546            floppy_drive_get_current_track( mc6843_floppy_image( device ) ) ));
547      break;
548
549   default:
550      logerror( "$%04x mc6843 invalid read offset %i\n", space.machine().firstcpu->pcbase( ), offset );
551   }
552
553   return data;
554}
555
556WRITE8_DEVICE_HANDLER ( mc6843_w )
557{
558   mc6843_t* mc6843 = get_safe_token( device );
559   switch ( offset ) {
560   case 0: /* Data Output Register (DOR) */
561   {
562      int cmd = mc6843->CMR & 0x0f;
563      int FWF = (mc6843->CMR >> 4) & 1;
564
565      LOG(( "%f $%04x mc6843_w: data output cmd=%s(%i), pos=%i/%i, GCR=%i, data=%02X\n",
566            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ),
567            mc6843_cmd[cmd], cmd, mc6843->data_idx,
568            mc6843->data_size, mc6843->GCR, data ));
569
570      if ( cmd == CMD_SSW || cmd == CMD_MSW || cmd == CMD_SWD )
571      {
572         /* sector write */
573         assert( mc6843->data_size > 0 );
574         assert( mc6843->data_idx < mc6843->data_size );
575         assert( mc6843->data_idx < sizeof(mc6843->data) );
576         mc6843->data[ mc6843->data_idx ] = data;
577         mc6843->data_idx++;
578         if ( mc6843->data_idx >= mc6843->data_size )
579         {
580            /* end of sector write */
581            device_t* img = mc6843_floppy_image( device );
582
583            LOG(( "%f $%04x mc6843_w: write sector %i\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6843->data_id ));
584
585            floppy_drive_write_sector_data(
586               img, mc6843->side, mc6843->data_id,
587               mc6843->data, mc6843->data_size,
588               (cmd == CMD_SWD) ? ID_FLAG_DELETED_DATA : 0 );
589
590            mc6843->STRA &= ~0x01; /* clear Data Transfer Request */
591
592            if ( cmd == CMD_MSW )
593            {
594               mc6843->GCR--;
595               mc6843->SAR++;
596               if ( mc6843->GCR == 0xff )
597               {
598                  mc6843_cmd_end( device );
599               }
600               else if ( mc6843->SAR > 26 )
601
602               {
603                  mc6843->STRB |= 0x08; /* set Sector Address Undetected */
604                  mc6843_cmd_end( device );
605               }
606               else
607               {
608                  mc6843->timer_cont->adjust( DELAY_ADDR );
609               }
610            }
611            else
612            {
613               mc6843_cmd_end( device );
614            }
615         }
616      }
617      else if ( (cmd == CMD_FFW) && FWF )
618      {
619         /* assume we are formatting */
620         UINT8 nibble;
621         nibble =
622            (data & 0x01) |
623            ((data & 0x04) >> 1 )|
624            ((data & 0x10) >> 2 )|
625            ((data & 0x40) >> 3 );
626
627         assert( mc6843->data_idx < sizeof(mc6843->data) );
628
629         mc6843->data[mc6843->data_idx / 2] =
630            (mc6843->data[mc6843->data_idx / 2] << 4) | nibble;
631
632         if ( (mc6843->data_idx == 0) && (mc6843->data[0] == 0xfe ) )
633         {
634            /* address mark detected */
635            mc6843->data_idx = 2;
636         }
637         else if ( mc6843->data_idx == 9 )
638         {
639            /* address id field complete */
640            if ( (mc6843->data[2] == 0) && (mc6843->data[4] == 0) )
641            {
642               /* valid address id field */
643               device_t* img = mc6843_floppy_image( device );
644               UINT8 track  = mc6843->data[1];
645               UINT8 sector = mc6843->data[3];
646               UINT8 filler = 0xe5; /* standard Thomson filler */
647               LOG(( "%f $%04x mc6843_w: address id detected track=%i sector=%i\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), track, sector));
648               floppy_drive_format_sector( img, mc6843->side, sector, track, 0, sector, 0, filler );
649            }
650            else
651            {
652               /* abort */
653               mc6843->data_idx = 0;
654            }
655         }
656         else if ( mc6843->data_idx > 0 )
657         {
658            /* accumulate address id field */
659            mc6843->data_idx++;
660         }
661      }
662      else if ( cmd == 0 )
663      {
664         /* nothing */
665      }
666      else
667      {
668         /* XXX TODO: other write modes */
669         logerror( "$%04x mc6843 write %02X in unsupported command mode %i (FWF=%i)\n", space.machine().firstcpu->pcbase( ), data, cmd, FWF );
670      }
671      break;
672   }
673
674   case 1: /* Current-Track Address Register (CTAR) */
675      mc6843->CTAR = data & 0x7f;
676      LOG(( "%f $%04x mc6843_w: set CTAR to %i %02X (actual=%i) \n",
677            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6843->CTAR, data,
678            floppy_drive_get_current_track( mc6843_floppy_image( device ) ) ));
679      break;
680
681   case 2: /* Command Register (CMR) */
682   {
683      int cmd = data & 15;
684
685      LOG(( "%f $%04x mc6843_w: set CMR to $%02X: cmd=%s(%i) FWF=%i DMA=%i ISR3-intr=%i fun-intr=%i\n",
686            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ),
687            data, mc6843_cmd[cmd], cmd, (data >> 4) & 1, (data >> 5) & 1,
688            (data >> 6) & 1, (data >> 7) & 1 ));
689
690      /* sanitize state */
691      mc6843->STRA &= ~0x81; /* clear Busy & Data Transfer Request */
692      mc6843->data_idx = 0;
693      mc6843->data_size = 0;
694
695      /* commands are initiated by updating some flags and scheduling
696         a bottom-half (mc6843_cont) after some delay */
697
698      switch (cmd)
699      {
700      case CMD_SSW:
701      case CMD_SSR:
702      case CMD_SWD:
703      case CMD_RCR:
704      case CMD_MSR:
705      case CMD_MSW:
706         mc6843->STRA |=  0x80; /* set Busy */
707         mc6843->STRA &= ~0x22; /* clear Track Not Equal & Delete Data Mark Detected */
708         mc6843->STRB &= ~0x04; /* clear Data Mark Undetected */
709         mc6843->timer_cont->adjust( DELAY_ADDR );
710         break;
711      case CMD_STZ:
712      case CMD_SEK:
713         mc6843->STRA |= 0x80; /* set Busy */
714         mc6843->timer_cont->adjust( DELAY_SEEK );
715         break;
716      case CMD_FFW:
717      case CMD_FFR:
718         mc6843->data_idx = 0;
719         mc6843->STRA |= 0x01; /* set Data Transfer Request */
720         break;
721      }
722
723      mc6843->CMR = data;
724      mc6843_status_update( device );
725      break;
726   }
727
728   case 3: /* Set-Up Register (SUR) */
729      mc6843->SUR = data;
730
731      /* assume CLK freq = 1MHz (IBM 3740 compatibility) */
732      LOG(( "%f $%04x mc6843_w: set SUR to $%02X: head settling time=%fms, track-to-track seek time=%f\n",
733            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ),
734            data, 4.096 * (data & 15), 1.024 * ((data >> 4) & 15) ));
735      break;
736
737   case 4: /* Sector Address Register (SAR) */
738      mc6843->SAR = data & 0x1f;
739      LOG(( "%f $%04x mc6843_w: set SAR to %i (%02X)\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6843->SAR, data ));
740      break;
741
742   case 5: /* General Count Register (GCR) */
743      mc6843->GCR = data & 0x7f;
744      LOG(( "%f $%04x mc6843_w: set GCR to %i (%02X)\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6843->GCR, data ));
745      break;
746
747   case 6: /* CRC Control Register (CCR) */
748      mc6843->CCR = data & 3;
749      LOG(( "%f $%04x mc6843_w: set CCR to %02X: CRC=%s shift=%i\n",
750            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
751            (data & 1) ? "enabled" : "disabled", (data >> 1) & 1 ));
752      break;
753
754   case 7: /* Logical-Track Address Register (LTAR) */
755      mc6843->LTAR = data & 0x7f;
756      LOG(( "%f $%04x mc6843_w: set LTAR to %i %02X (actual=%i)\n",
757            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6843->LTAR, data,
758            floppy_drive_get_current_track( mc6843_floppy_image( device ) ) ));
759      break;
760
761   default:
762      logerror( "$%04x mc6843 invalid write offset %i (data=$%02X)\n", space.machine().firstcpu->pcbase( ), offset, data );
763   }
764}
765
766
767
768/************************ reset *****************************/
769
770static DEVICE_RESET( mc6843 )
771{
772   mc6843_t* mc6843 = get_safe_token( device );
773   int i;
774   LOG (( "mc6843 reset\n" ));
775
776   /* setup/reset floppy drive */
777   for ( i = 0; i < 4; i++ )
778   {
779      device_t * img = floppy_get_device( device->machine(), i );
780      floppy_mon_w(img, CLEAR_LINE);
781      floppy_drive_set_ready_state( img, FLOPPY_DRIVE_READY, 0 );
782      floppy_drive_set_rpm( img, 300. );
783   }
784
785   /* reset registers */
786   mc6843->CMR &= 0xf0; /* zero only command */
787   mc6843->ISR = 0;
788   mc6843->STRA &= 0x5c;
789   mc6843->SAR = 0;
790   mc6843->STRB &= 0x20;
791   mc6843_status_update( device );
792
793   mc6843->data_size = 0;
794   mc6843->data_idx = 0;
795   mc6843->timer_cont->adjust( attotime::never );
796}
797
798
799
800/************************ start *****************************/
801
802static DEVICE_START( mc6843 )
803{
804   mc6843_t* mc6843 = get_safe_token( device );
805
806   mc6843->iface = (const mc6843_interface*)device->static_config();
807
808   mc6843->timer_cont = device->machine().scheduler().timer_alloc(FUNC(mc6843_cont), (void*) device) ;
809
810   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->CTAR );
811   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->CMR );
812   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->ISR );
813   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->SUR );
814   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->STRA );
815   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->STRB );
816   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->SAR );
817   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->GCR );
818   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->CCR );
819   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->LTAR );
820   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->drive );
821   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->side );
822   state_save_register_item_array( device->machine(),"mc6843", device->tag(), 0, mc6843->data );
823   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->data_size );
824   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->data_idx );
825   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->data_id );
826}
827
828
829const device_type MC6843 = &device_creator<mc6843_device>;
830
831mc6843_device::mc6843_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
832   : device_t(mconfig, MC6843, "Motorola MC6843 floppy controller", tag, owner, clock)
833{
834   m_token = global_alloc_clear(mc6843_t);
835}
836
837//-------------------------------------------------
838//  device_config_complete - perform any
839//  operations now that the configuration is
840//  complete
841//-------------------------------------------------
842
843void mc6843_device::device_config_complete()
844{
845}
846
847//-------------------------------------------------
848//  device_start - device-specific startup
849//-------------------------------------------------
850
851void mc6843_device::device_start()
852{
853   DEVICE_START_NAME( mc6843 )(this);
854}
855
856//-------------------------------------------------
857//  device_reset - device-specific reset
858//-------------------------------------------------
859
860void mc6843_device::device_reset()
861{
862   DEVICE_RESET_NAME( mc6843 )(this);
863}
Property changes on: trunk/src/emu/machine/mc6843.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/wd11c00_17.c
r0r21685
1/**********************************************************************
2
3    Western Digital WD11C00-17 PC/XT Host Interface Logic Device
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10#include "machine/wd11c00_17.h"
11
12
13
14//**************************************************************************
15//  MACROS / CONSTANTS
16//**************************************************************************
17
18#define LOG 1
19
20
21// status register
22#define STATUS_IRQ      0x20
23#define STATUS_DRQ      0x10
24#define STATUS_BUSY     0x08
25#define STATUS_C_D      0x04
26#define STATUS_I_O      0x02
27#define STATUS_REQ      0x01
28
29
30// mask register
31#define MASK_IRQ        0x02
32#define MASK_DMA        0x01
33
34
35
36//**************************************************************************
37//  DEVICE DEFINITIONS
38//**************************************************************************
39
40const device_type WD11C00_17 = &device_creator<wd11c00_17_device>;
41
42
43//-------------------------------------------------
44//  device_config_complete - perform any
45//  operations now that the configuration is
46//  complete
47//-------------------------------------------------
48
49void wd11c00_17_device::device_config_complete()
50{
51   // inherit a copy of the static data
52   const wd11c00_17_interface *intf = reinterpret_cast<const wd11c00_17_interface *>(static_config());
53   if (intf != NULL)
54      *static_cast<wd11c00_17_interface *>(this) = *intf;
55
56   // or initialize to defaults if none provided
57   else
58   {
59      memset(&m_out_irq5_cb, 0, sizeof(m_out_irq5_cb));
60      memset(&m_out_drq3_cb, 0, sizeof(m_out_drq3_cb));
61      memset(&m_out_mr_cb, 0, sizeof(m_out_mr_cb));
62      memset(&m_out_busy_cb, 0, sizeof(m_out_busy_cb));
63      memset(&m_out_req_cb, 0, sizeof(m_out_req_cb));
64      memset(&m_out_ra3_cb, 0, sizeof(m_out_ra3_cb));
65      memset(&m_in_rd322_cb, 0, sizeof(m_in_rd322_cb));
66      memset(&m_in_ramcs_cb, 0, sizeof(m_in_ramcs_cb));
67      memset(&m_out_ramwr_cb, 0, sizeof(m_out_ramwr_cb));
68      memset(&m_in_cs1010_cb, 0, sizeof(m_in_cs1010_cb));
69      memset(&m_out_cs1010_cb, 0, sizeof(m_out_cs1010_cb));
70   }
71}
72
73
74
75//**************************************************************************
76//  INLINE HELPERS
77//**************************************************************************
78
79//-------------------------------------------------
80//  check_interrupt -
81//-------------------------------------------------
82
83inline void wd11c00_17_device::check_interrupt()
84{
85   if (BIT(m_ra, 10))
86   {
87      m_status &= ~STATUS_DRQ;
88   }
89
90   int ra3 = BIT(m_ra, 3);
91
92   if (m_ra3 != ra3)
93   {
94      m_out_ra3_func(ra3 ? ASSERT_LINE : CLEAR_LINE);
95      m_ra3 = ra3;
96   }
97
98   int irq5 = ((m_status & STATUS_IRQ) && (m_mask & MASK_IRQ)) ? ASSERT_LINE : CLEAR_LINE;
99
100   if (m_irq5 != irq5)
101   {
102      m_out_irq5_func(irq5);
103      m_irq5 = irq5;
104   }
105
106   int drq3 = ((m_status & STATUS_DRQ) && (m_mask & MASK_DMA)) ? ASSERT_LINE : CLEAR_LINE;
107
108   if (m_drq3 != drq3)
109   {
110      m_out_drq3_func(drq3);
111      m_drq3 = drq3;
112   }
113
114   int busy = (m_status & STATUS_BUSY) ? 0 : 1;
115
116   if (m_busy != busy)
117   {
118      m_out_busy_func(busy);
119      m_busy = busy;
120   }
121
122   int req = (m_status & STATUS_REQ) ? 1 : 0;
123
124   if (m_req != req)
125   {
126      m_out_req_func(req);
127      m_req = req;
128   }
129}
130
131
132//-------------------------------------------------
133//  increment_address -
134//-------------------------------------------------
135
136inline void wd11c00_17_device::increment_address()
137{
138   m_ra++;
139   check_interrupt();
140}
141
142
143//-------------------------------------------------
144//  read_data -
145//-------------------------------------------------
146
147inline UINT8 wd11c00_17_device::read_data()
148{
149   UINT8 data = 0;
150
151   if (m_status & STATUS_BUSY)
152   {
153      data = m_in_ramcs_func(m_ra & 0x7ff);
154
155      increment_address();
156   }
157
158   return data;
159}
160
161
162//-------------------------------------------------
163//  write_data -
164//-------------------------------------------------
165
166inline void wd11c00_17_device::write_data(UINT8 data)
167{
168   if (m_status & STATUS_BUSY)
169   {
170      m_out_ramwr_func(m_ra & 0x7ff, data);
171
172      increment_address();
173   }
174}
175
176
177//-------------------------------------------------
178//  software_reset -
179//-------------------------------------------------
180
181inline void wd11c00_17_device::software_reset()
182{
183   m_out_mr_func(ASSERT_LINE);
184   m_out_mr_func(CLEAR_LINE);
185
186   device_reset();
187}
188
189
190//-------------------------------------------------
191//  select -
192//-------------------------------------------------
193
194inline void wd11c00_17_device::select()
195{
196   m_status = STATUS_BUSY | STATUS_C_D | STATUS_REQ;
197
198   check_interrupt();
199}
200
201
202
203//**************************************************************************
204//  LIVE DEVICE
205//**************************************************************************
206
207//-------------------------------------------------
208//  wd11c00_17_device - constructor
209//-------------------------------------------------
210
211wd11c00_17_device::wd11c00_17_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
212   : device_t(mconfig, WD11C00_17, "Western Digital WD11C00-17", tag, owner, clock),
213      m_status(0),
214      m_ra(0),
215      m_irq5(CLEAR_LINE),
216      m_drq3(CLEAR_LINE),
217      m_busy(1),
218      m_req(0),
219      m_ra3(0)
220{
221}
222
223
224//-------------------------------------------------
225//  device_start - device-specific startup
226//-------------------------------------------------
227
228void wd11c00_17_device::device_start()
229{
230   // resolve callbacks
231   m_out_irq5_func.resolve(m_out_irq5_cb, *this);
232   m_out_drq3_func.resolve(m_out_drq3_cb, *this);
233   m_out_mr_func.resolve(m_out_mr_cb, *this);
234   m_out_busy_func.resolve(m_out_busy_cb, *this);
235   m_out_req_func.resolve(m_out_req_cb, *this);
236   m_out_ra3_func.resolve(m_out_ra3_cb, *this);
237   m_in_rd322_func.resolve(m_in_rd322_cb, *this);
238   m_in_ramcs_func.resolve(m_in_ramcs_cb, *this);
239   m_out_ramwr_func.resolve(m_out_ramwr_cb, *this);
240   m_in_cs1010_func.resolve(m_in_cs1010_cb, *this);
241   m_out_cs1010_func.resolve(m_out_cs1010_cb, *this);
242}
243
244
245//-------------------------------------------------
246//  device_reset - device-specific reset
247//-------------------------------------------------
248
249void wd11c00_17_device::device_reset()
250{
251   m_status &= ~(STATUS_IRQ | STATUS_DRQ | STATUS_BUSY);
252   m_mask = 0;
253   m_ra = 0;
254
255   check_interrupt();
256}
257
258
259//-------------------------------------------------
260//  io_r -
261//-------------------------------------------------
262
263READ8_MEMBER( wd11c00_17_device::io_r )
264{
265   UINT8 data = 0xff;
266
267   switch (offset)
268   {
269   case 0: // Read Data, Board to Host
270      if (LOG) logerror("%s WD11C00-17 '%s' Read Data %03x:", machine().describe_context(), tag(), m_ra);
271      data = read_data();
272      if (LOG) logerror("%02x\n", data);
273      break;
274
275   case 1: // Read Board Hardware Status
276      data = m_status;
277      check_interrupt();
278      break;
279
280   case 2: // Read Drive Configuration Information
281      data = m_in_rd322_func(0);
282      break;
283
284   case 3: // Not Used
285      break;
286   }
287
288   return data;
289}
290
291
292//-------------------------------------------------
293//  io_w -
294//-------------------------------------------------
295
296WRITE8_MEMBER( wd11c00_17_device::io_w )
297{
298   switch (offset)
299   {
300   case 0: // Write Data, Host to Board
301      if (LOG) logerror("%s WD11C00-17 '%s' Write Data %03x:%02x\n", machine().describe_context(), tag(), m_ra, data);
302      write_data(data);
303      break;
304
305   case 1: // Board Software Reset
306      if (LOG) logerror("%s WD11C00-17 '%s' Software Reset\n", machine().describe_context(), tag());
307      software_reset();
308      break;
309
310   case 2: // Board Select
311      if (LOG) logerror("%s WD11C00-17 '%s' Select\n", machine().describe_context(), tag());
312      increment_address(); // HACK
313      select();
314      break;
315
316   case 3: // Set/Reset DMA, IRQ Masks
317      if (LOG) logerror("%s WD11C00-17 '%s' Mask IRQ %u DMA %u\n", machine().describe_context(), tag(), BIT(data, 1), BIT(data, 0));
318      m_mask = data;
319      check_interrupt();
320      break;
321   }
322}
323
324
325//-------------------------------------------------
326//  dack_r -
327//-------------------------------------------------
328
329UINT8 wd11c00_17_device::dack_r()
330{
331   return read_data();
332}
333
334
335//-------------------------------------------------
336//  dack_w -
337//-------------------------------------------------
338
339void wd11c00_17_device::dack_w(UINT8 data)
340{
341   write_data(data);
342}
343
344
345//-------------------------------------------------
346//  read -
347//-------------------------------------------------
348
349READ8_MEMBER( wd11c00_17_device::read )
350{
351   UINT8 data = 0;
352
353   switch (offset)
354   {
355   case 0x00:
356      if (LOG) logerror("%s WD11C00-17 '%s' Read RAM %03x:", machine().describe_context(), tag(), m_ra);
357      data = read_data();
358      if (LOG) logerror("%02x\n", data);
359      break;
360
361   case 0x20:
362      data = m_in_cs1010_func(m_ra >> 8);
363      break;
364   }
365
366   return data;
367}
368
369
370//-------------------------------------------------
371//  write -
372//-------------------------------------------------
373
374WRITE8_MEMBER( wd11c00_17_device::write )
375{
376   switch (offset)
377   {
378   case 0x00:
379      if (LOG) logerror("%s WD11C00-17 '%s' Write RAM %03x:%02x\n", machine().describe_context(), tag(), m_ra, data);
380      write_data(data);
381      if (m_ra > 0x400) m_ecc_not_0 = 0; // HACK
382      break;
383
384   case 0x20:
385      m_out_cs1010_func(m_ra >> 8, data);
386      break;
387
388   case 0x60:
389      m_ra = (data & 0x07) << 8;
390      if (LOG) logerror("%s WD11C00-17 '%s' RA %03x\n", machine().describe_context(), tag(), m_ra);
391      check_interrupt();
392      break;
393   }
394}
395
396
397//-------------------------------------------------
398//  ireq_w -
399//-------------------------------------------------
400
401WRITE_LINE_MEMBER( wd11c00_17_device::ireq_w )
402{
403   if (LOG) logerror("%s WD11C00-17 '%s' IREQ %u\n", machine().describe_context(), tag(), state);
404
405   if (state) m_status |= STATUS_REQ; else m_status &= ~STATUS_REQ;
406
407   if (m_status & STATUS_BUSY)
408   {
409      if (state)
410      {
411         m_status |= STATUS_IRQ | STATUS_I_O;
412      }
413      else
414      {
415         if (m_status & STATUS_I_O)
416         {
417            m_status &= ~(STATUS_BUSY | STATUS_I_O);
418         }
419      }
420   }
421
422   check_interrupt();
423}
424
425
426//-------------------------------------------------
427//  io_w -
428//-------------------------------------------------
429
430WRITE_LINE_MEMBER( wd11c00_17_device::io_w )
431{
432   if (LOG) logerror("%s WD11C00-17 '%s' I/O %u\n", machine().describe_context(), tag(), state);
433
434   if (state) m_status |= STATUS_I_O; else m_status &= ~STATUS_I_O;
435}
436
437
438//-------------------------------------------------
439//  cd_w -
440//-------------------------------------------------
441
442WRITE_LINE_MEMBER( wd11c00_17_device::cd_w )
443{
444   if (LOG) logerror("%s WD11C00-17 '%s' C/D %u\n", machine().describe_context(), tag(), state);
445
446   if (state) m_status |= STATUS_C_D; else m_status &= ~STATUS_C_D;
447}
448
449
450//-------------------------------------------------
451//  clct_w -
452//-------------------------------------------------
453
454WRITE_LINE_MEMBER( wd11c00_17_device::clct_w )
455{
456   if (LOG) logerror("%s WD11C00-17 '%s' CLCT %u\n", machine().describe_context(), tag(), state);
457
458   if (state)
459   {
460      m_ra &= 0xff00;
461      check_interrupt();
462   }
463}
464
465
466//-------------------------------------------------
467//  mode_w -
468//-------------------------------------------------
469
470WRITE_LINE_MEMBER( wd11c00_17_device::mode_w )
471{
472   if (LOG) logerror("%s WD11C00-17 '%s' MODE %u\n", machine().describe_context(), tag(), state);
473
474   m_mode = state;
475   m_ecc_not_0 = state; // HACK
476}
477
478
479//-------------------------------------------------
480//  busy_r -
481//-------------------------------------------------
482
483READ_LINE_MEMBER( wd11c00_17_device::busy_r )
484{
485   return (m_status & STATUS_BUSY) ? 0 : 1;
486}
487
488
489//-------------------------------------------------
490//  ecc_not_0_r -
491//-------------------------------------------------
492
493READ_LINE_MEMBER( wd11c00_17_device::ecc_not_0_r )
494{
495   return m_ecc_not_0;
496}
Property changes on: trunk/src/emu/machine/wd11c00_17.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/mc6843.h
r0r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2007
4
5  Motorola 6843 Floppy Disk Controller emulation.
6
7**********************************************************************/
8
9#ifndef MC6843_H
10#define MC6843_H
11
12class mc6843_device : public device_t
13{
14public:
15   mc6843_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
16   ~mc6843_device() { global_free(m_token); }
17
18   // access to legacy token
19   void *token() const { assert(m_token != NULL); return m_token; }
20protected:
21   // device-level overrides
22   virtual void device_config_complete();
23   virtual void device_start();
24   virtual void device_reset();
25private:
26   // internal state
27   void *m_token;
28};
29
30extern const device_type MC6843;
31
32
33
34/* ---------- configuration ------------ */
35
36struct mc6843_interface
37{
38   void ( * irq_func ) ( device_t *device, int state );
39};
40
41
42#define MCFG_MC6843_ADD(_tag, _intrf) \
43   MCFG_DEVICE_ADD(_tag, MC6843, 0)          \
44   MCFG_DEVICE_CONFIG(_intrf)
45
46#define MCFG_MC6843_REMOVE(_tag)        \
47   MCFG_DEVICE_REMOVE(_tag)
48
49
50/* ---------- functions ------------ */
51
52extern DECLARE_READ8_DEVICE_HANDLER  ( mc6843_r );
53extern DECLARE_WRITE8_DEVICE_HANDLER ( mc6843_w );
54
55extern void mc6843_set_drive ( device_t *device, int drive );
56extern void mc6843_set_side  ( device_t *device, int side );
57extern void mc6843_set_index_pulse ( device_t *device, int index_pulse );
58
59#endif
Property changes on: trunk/src/emu/machine/mc6843.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/wd11c00_17.h
r0r21685
1/**********************************************************************
2
3    Western Digital WD11C00-17 PC/XT Host Interface Logic Device
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10#pragma once
11
12#ifndef __WD11C00_17__
13#define __WD11C00_17__
14
15
16#include "emu.h"
17
18
19
20//**************************************************************************
21//  INTERFACE CONFIGURATION MACROS
22//**************************************************************************
23
24#define MCFG_WD11C00_17_ADD(_tag, _clock, _config) \
25   MCFG_DEVICE_ADD(_tag, WD11C00_17, _clock) \
26   MCFG_DEVICE_CONFIG(_config)
27
28
29#define WD11C00_17_INTERFACE(_name) \
30   const wd11c00_17_interface (_name) =
31
32
33
34//**************************************************************************
35//  TYPE DEFINITIONS
36//**************************************************************************
37
38// ======================> wd11c00_17_interface
39
40struct wd11c00_17_interface
41{
42   devcb_write_line    m_out_irq5_cb;
43   devcb_write_line    m_out_drq3_cb;
44   devcb_write_line    m_out_mr_cb;
45   devcb_write_line    m_out_busy_cb;
46   devcb_write_line    m_out_req_cb;
47   devcb_write_line    m_out_ra3_cb;
48   devcb_read8         m_in_rd322_cb;
49   devcb_read8         m_in_ramcs_cb;
50   devcb_write8        m_out_ramwr_cb;
51   devcb_read8         m_in_cs1010_cb;
52   devcb_write8        m_out_cs1010_cb;
53};
54
55
56// ======================> wd11c00_17_device
57
58class wd11c00_17_device :   public device_t,
59                     public wd11c00_17_interface
60{
61public:
62   // construction/destruction
63   wd11c00_17_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
64
65   DECLARE_READ8_MEMBER( io_r );
66   DECLARE_WRITE8_MEMBER( io_w );
67
68   UINT8 dack_r();
69   void dack_w(UINT8 data);
70
71   DECLARE_READ8_MEMBER( read );
72   DECLARE_WRITE8_MEMBER( write );
73
74   DECLARE_WRITE_LINE_MEMBER( ireq_w );
75   DECLARE_WRITE_LINE_MEMBER( io_w );
76   DECLARE_WRITE_LINE_MEMBER( cd_w );
77   DECLARE_WRITE_LINE_MEMBER( clct_w );
78   DECLARE_WRITE_LINE_MEMBER( mode_w );
79
80   DECLARE_READ_LINE_MEMBER( busy_r );
81   DECLARE_READ_LINE_MEMBER( ecc_not_0_r );
82
83protected:
84   // device-level overrides
85   virtual void device_start();
86   virtual void device_reset();
87   virtual void device_config_complete();
88
89private:
90   inline void check_interrupt();
91   inline void increment_address();
92   inline UINT8 read_data();
93   inline void write_data(UINT8 data);
94   inline void software_reset();
95   inline void select();
96
97   devcb_resolved_write_line   m_out_irq5_func;
98   devcb_resolved_write_line   m_out_drq3_func;
99   devcb_resolved_write_line   m_out_mr_func;
100   devcb_resolved_write_line   m_out_busy_func;
101   devcb_resolved_write_line   m_out_req_func;
102   devcb_resolved_write_line   m_out_ra3_func;
103   devcb_resolved_read8        m_in_rd322_func;
104   devcb_resolved_read8        m_in_ramcs_func;
105   devcb_resolved_write8       m_out_ramwr_func;
106   devcb_resolved_read8        m_in_cs1010_func;
107   devcb_resolved_write8       m_out_cs1010_func;
108
109   UINT8 m_status;
110   UINT8 m_mask;
111
112   offs_t m_ra;
113
114   int m_mode;
115   int m_ecc_not_0;
116
117   int m_irq5;
118   int m_drq3;
119   int m_busy;
120   int m_req;
121   int m_ra3;
122};
123
124
125// device type definition
126extern const device_type WD11C00_17;
127
128#endif
Property changes on: trunk/src/emu/machine/wd11c00_17.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/upd7002.c
r0r21685
1/******************************************************************************
2    uPD7002 Analogue to Digital Converter
3
4    MESS Driver By:
5
6    Gordon Jefferyes
7    mess_bbc@gjeffery.dircon.co.uk
8
9******************************************************************************/
10
11#include "emu.h"
12#include "upd7002.h"
13
14
15struct uPD7002_t
16{
17   /* Pointer to our interface */
18   const uPD7002_interface *intf;
19
20   /* Status Register
21       D0 and D1 define the currently selected input channel
22       D2 flag output
23       D3 0 = 8 bit mode   1 = 12 bit mode
24       D4 2nd MSB of conversion
25       D5     MSB of conversion
26       D6 0 = busy, 1 = not busy    (~busy)
27       D7 0 = conversion completed, 1 = conversion not completed  (~EOC)
28   */
29   int status;
30
31   /* High data byte
32       This byte contains the 8 most significant bits of the analogue to digital conversion. */
33   int data1;
34
35   /* Low data byte
36       In 12 bit mode: Bits 7 to 4 define the four low order bits of the conversion.
37       In  8 bit mode. All bits 7 to 4 are inaccurate.
38       Bits 3 to 0 are always set to low. */
39   int data0;
40
41
42   /* temporary store of the next A to D conversion */
43   int digitalvalue;
44
45   /* this counter is used to check a full end of conversion has been reached
46   if the uPD7002 is half way through one conversion and a new conversion is requested
47   the counter at the end of the first conversion will not match and not be processed
48   only then at the end of the second conversion will the conversion complete function run */
49   int conversion_counter;
50};
51
52
53/*****************************************************************************
54 Implementation
55*****************************************************************************/
56
57INLINE uPD7002_t *get_safe_token(device_t *device)
58{
59   assert(device != NULL);
60   assert(device->type() == UPD7002);
61
62   return (uPD7002_t *)downcast<uPD7002_device *>(device)->token();
63}
64
65READ8_DEVICE_HANDLER ( uPD7002_EOC_r )
66{
67   uPD7002_t *uPD7002 = get_safe_token(device);
68   return (uPD7002->status>>7)&0x01;
69}
70
71
72static TIMER_CALLBACK(uPD7002_conversioncomplete)
73{
74   device_t *device = (device_t *)ptr;
75   uPD7002_t *uPD7002 = get_safe_token(device);
76
77   int counter_value = param;
78   if (counter_value==uPD7002->conversion_counter)
79   {
80      // this really always does a 12 bit conversion
81      uPD7002->data1 = uPD7002->digitalvalue>>8;
82      uPD7002->data0 = uPD7002->digitalvalue&0xf0;
83
84      // set the status register with top 2 MSB, not busy and conversion complete
85      uPD7002->status = (uPD7002->status & 0x0f)|((uPD7002->data1 & 0xc0)>>2)|0x40;
86
87      // call the EOC function with EOC from status
88      // uPD7002_EOC_r(0) this has just been set to 0
89      if (uPD7002->intf->EOC_func) (uPD7002->intf->EOC_func)(device,0);
90      uPD7002->conversion_counter=0;
91   }
92}
93
94
95READ8_DEVICE_HANDLER ( uPD7002_r )
96{
97   uPD7002_t *uPD7002 = get_safe_token(device);
98
99   switch(offset&0x03)
100   {
101      case 0:
102         return uPD7002->status;
103
104      case 1:
105         return uPD7002->data1;
106
107      case 2: case 3:
108         return uPD7002->data0;
109   }
110   return 0;
111}
112
113
114
115WRITE8_DEVICE_HANDLER ( uPD7002_w )
116{
117   uPD7002_t *uPD7002 = get_safe_token(device);
118   /* logerror("write to uPD7002 $%02X = $%02X\n",offset,data); */
119
120   switch(offset&0x03)
121   {
122      case 0:
123      /*
124      Data Latch/AD start
125          D0 and D1 together define which one of the four input channels is selected
126          D2 flag input, normally set to 0????
127          D3 defines whether an 8 (0) or 12 (1) bit resolution conversion should occur
128          D4 to D7 not used.
129
130          an 8  bit conversion typically takes 4ms
131          an 12 bit conversion typically takes 10ms
132
133          writing to this register will initiate a conversion.
134      */
135
136      /* set D6=0 busy ,D7=1 conversion not complete */
137      uPD7002->status=(data & 0x0f) | 0x80;
138
139      // call the EOC function with EOC from status
140      // uPD7002_EOC_r(0) this has just been set to 1
141      if (uPD7002->intf->EOC_func) uPD7002->intf->EOC_func(device, 1);
142
143      /* the uPD7002 works by sampling the analogue value at the start of the conversion
144         so it is read hear and stored until the end of the A to D conversion */
145
146      // this function should return a 16 bit value.
147      uPD7002->digitalvalue = uPD7002->intf->get_analogue_func(device, uPD7002->status & 0x03);
148
149      uPD7002->conversion_counter++;
150
151      // call a timer to start the conversion
152      if (uPD7002->status & 0x08)
153      {
154         // 12 bit conversion takes 10ms
155         space.machine().scheduler().timer_set(attotime::from_msec(10), FUNC(uPD7002_conversioncomplete), uPD7002->conversion_counter, (void *)device);
156      } else {
157         // 8 bit conversion takes 4ms
158         space.machine().scheduler().timer_set(attotime::from_msec(4), FUNC(uPD7002_conversioncomplete), uPD7002->conversion_counter, (void *)device);
159      }
160      break;
161
162      case 1: case 2:
163      /* Nothing */
164      break;
165
166      case 3:
167      /* Test Mode: Used for inspecting the device, The data input-output terminals assume an input
168            state and are connected to the A/D counter. Therefore, the A/D conversion data
169            read out after this is meaningless.
170      */
171      break;
172   }
173}
174
175/* Device Interface */
176
177static DEVICE_START( uPD7002 )
178{
179   uPD7002_t *uPD7002 = get_safe_token(device);
180   // validate arguments
181
182   assert(device != NULL);
183   assert(device->tag() != NULL);
184   assert(device->static_config() != NULL);
185
186   uPD7002->intf = (const uPD7002_interface*)device->static_config();
187   uPD7002->status = 0;
188   uPD7002->data1 = 0;
189   uPD7002->data0 = 0;
190   uPD7002->digitalvalue = 0;
191   uPD7002->conversion_counter = 0;
192
193   // register for state saving
194   state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->status);
195   state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->data1);
196   state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->data0);
197   state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->digitalvalue);
198   state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->conversion_counter);
199}
200
201static DEVICE_RESET( uPD7002 )
202{
203   uPD7002_t *uPD7002 = get_safe_token(device);
204   uPD7002->status = 0;
205   uPD7002->data1 = 0;
206   uPD7002->data0 = 0;
207   uPD7002->digitalvalue = 0;
208   uPD7002->conversion_counter = 0;
209}
210
211const device_type UPD7002 = &device_creator<uPD7002_device>;
212
213uPD7002_device::uPD7002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
214   : device_t(mconfig, UPD7002, "uPD7002", tag, owner, clock)
215{
216   m_token = global_alloc_clear(uPD7002_t);
217}
218
219//-------------------------------------------------
220//  device_config_complete - perform any
221//  operations now that the configuration is
222//  complete
223//-------------------------------------------------
224
225void uPD7002_device::device_config_complete()
226{
227}
228
229//-------------------------------------------------
230//  device_start - device-specific startup
231//-------------------------------------------------
232
233void uPD7002_device::device_start()
234{
235   DEVICE_START_NAME( uPD7002 )(this);
236}
237
238//-------------------------------------------------
239//  device_reset - device-specific reset
240//-------------------------------------------------
241
242void uPD7002_device::device_reset()
243{
244   DEVICE_RESET_NAME( uPD7002 )(this);
245}
Property changes on: trunk/src/emu/machine/upd7002.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/upd7002.h
r0r21685
1/*****************************************************************************
2 *
3 * machine/upd7002.h
4 *
5 * uPD7002 Analogue to Digital Converter
6 *
7 * Driver by Gordon Jefferyes <mess_bbc@gjeffery.dircon.co.uk>
8 *
9 ****************************************************************************/
10
11#ifndef UPD7002_H_
12#define UPD7002_H_
13
14/***************************************************************************
15    MACROS
16***************************************************************************/
17
18class uPD7002_device : public device_t
19{
20public:
21   uPD7002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
22   ~uPD7002_device() { global_free(m_token); }
23
24   // access to legacy token
25   void *token() const { assert(m_token != NULL); return m_token; }
26protected:
27   // device-level overrides
28   virtual void device_config_complete();
29   virtual void device_start();
30   virtual void device_reset();
31private:
32   // internal state
33   void *m_token;
34};
35
36extern const device_type UPD7002;
37
38
39/***************************************************************************
40    TYPE DEFINITIONS
41***************************************************************************/
42
43typedef int (*uPD7002_get_analogue_func)(device_t *device, int channel_number);
44#define UPD7002_GET_ANALOGUE(name)  int name(device_t *device, int channel_number )
45
46typedef void (*uPD7002_eoc_func)(device_t *device, int data);
47#define UPD7002_EOC(name)   void name(device_t *device, int data )
48
49
50struct uPD7002_interface
51{
52   uPD7002_get_analogue_func get_analogue_func;
53   uPD7002_eoc_func          EOC_func;
54};
55
56/***************************************************************************
57    FUNCTION PROTOTYPES
58***************************************************************************/
59
60/* Standard handlers */
61
62DECLARE_READ8_DEVICE_HANDLER ( uPD7002_EOC_r );
63DECLARE_READ8_DEVICE_HANDLER ( uPD7002_r );
64DECLARE_WRITE8_DEVICE_HANDLER ( uPD7002_w );
65
66
67/***************************************************************************
68    DEVICE CONFIGURATION MACROS
69***************************************************************************/
70
71#define MCFG_UPD7002_ADD(_tag, _intrf) \
72   MCFG_DEVICE_ADD(_tag, UPD7002, 0) \
73   MCFG_DEVICE_CONFIG(_intrf)
74
75
76#endif /* UPD7002_H_ */
Property changes on: trunk/src/emu/machine/upd7002.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/ay31015.c
r0r21685
1/****************************************************************************
2
3    ay31015.c by Robbbert, May 2008. Bugs fixed by Judge.
4
5    Code for the AY-3-1014A, AY-3-1015(D), AY-5-1013(A), and AY-6-1013 UARTs
6    The HD6402 UART is compatible with the AY-3-1015 UART.
7
8    This is cycle-accurate according to the specifications.
9
10    It supports independent receive and transmit clocks,
11    and transmission and reception can occur simultaneously if desired.
12
13*****************************************************************************
14
15Differences between the chip types:
16- All units have pull-up resistors on the inputs, except for the AY-3-1014A which is CMOS-compatible.
17- AY-3-1014A and AY-3-1015 - 1.5 stop bits mode available.
18- Max baud rate of 30k, except AY-5-1013 which has 20k.
19- AY-5-1013 has extended temperature ratings.
20- AY-5-1013 and AY-6-1013 require a -12 volt supply on pin 2. Pin is not used otherwise.
21- AY-5-1013 and AY-6-1013 do not reset the received data register when XR pin is used.
22
23******************************************************************************
24
25It is not clear in the documentation as to which settings will reset the device.
26    To be safe, we will always reset whenever the control register changes.
27
28    Also, it not clear exactly what happens under various error conditions.
29
30********************************************************************************
31
32Device Data:
33
34* Common Controls:
35-- Pin 1 - Vcc - 5 volts
36-- Pin 2 - not used (on AY-5-1013 and AY-6-1013 this is Voo = -12 volts)
37-- Pin 3 - Gnd - 0 volts
38-- Pin 21 - XR - External Reset - resets all registers to initial state except for the control register
39-- Pin 35 - NP - No Parity - "1" will kill any parity processing
40-- Pin 36 - TSB - Number of Stop Bits - "0" = 1 stop bit; "1" = 2 stop bits. If "1", and 5 bits per character, then we have 1.5 stop bits
41-- pin 37 - NB1
42-- pin 38 - NB2 - Number of bits per character = NB1 + (NB2 * 2) + 5
43-- pin 39 - EPS - Odd or Even Parity Select - "0" = Odd parity; "1" = Even parity. Has no effect if NP is high.
44-- Pin 34 - CS - Control Strobe - Read NP, TSB, EPS, NB1, NB2 into the control register.
45
46Format of data stream:
47Start bit (low), Bit 0, Bit 1... highest bit, Parity bit (if enabled), 1-2 stop bits (high)
48
49
50* Receiver Controls:
51-- Pin 17 - RCP - Clock which is 16x the desired baud rate
52-- Pin 20 - SI - Serial input stream - "1" = Mark (waiting for input), "0" = Space (Start bit) initiates the transfer of a byte
53-- Pin 4 - RDE - "0" causes the received data to appear on RD1 to RD8.
54-- Pins 5 to 12 - RD8 to RD1 - These are the data lines (bits 7 to 0). Data is right-justified.
55-- Pin 16 - SWE - Status word enable - causes the status bits (PE, FE, OR, DAV, TBMT) to appear at the pins.
56-- Pin 19 - DAV - "1" indicates that a byte has been received by the UART, and should now be accepted by the computer
57-- Pin 18 - RDAV - "0" will force DAV low.
58-- Pin 13 - PE - Parity error - "1" indicates that a parity error occurred
59-- Pin 14 - FE - Framing error - "1" Indicates that the stop bit was missing
60-- Pin 15 - OR - overrun - "1" indicates that a new character has become available before the computer had accepted the previous character
61
62* Transmitter controls:
63-- Pin 40 - TCP - Clock which is 16x the desired baud rate
64-- Pin 25 - SO - Serial output stream - it will stay at "1" while no data is being transmitted
65-- Pins 26 to 33 - DB1 to DB8 - These are the data lines containing the byte to be sent
66-- Pin 23 - DS - Data Strobe - "0" will copy DB1 to DB8 into the transmit buffer
67-- Pin 22 - TBMT - Transmit buffer Empty - "1" indicates to the computer that another byte may be sent to the UART
68-- Pin 24 - EOC - End of Character - "0" means that a character is being sent.
69
70******************************************* COMMON CONTROLS ********************************************************/
71
72#include "emu.h"
73#include "ay31015.h"
74
75enum state_t
76{
77   IDLE,
78   START_BIT,
79   PROCESSING,
80   PARITY_BIT,
81   FIRST_STOP_BIT,
82   SECOND_STOP_BIT,
83   PREP_TIME
84};
85
86
87struct ay31015_t
88{
89   const ay31015_config    *config;
90
91   int pins[41];
92
93   UINT8 control_reg;
94   UINT8 status_reg;
95   UINT16 second_stop_bit; // 0, 8, 16
96   UINT16 total_pulses;    // bits * 16
97   UINT8 internal_sample;
98
99   state_t rx_state;
100   UINT8 rx_data;      // byte being received
101   UINT8 rx_buffer;    // received byte waiting to be accepted by computer
102   UINT8 rx_bit_count;
103   UINT8 rx_parity;
104   UINT16 rx_pulses;   // total pulses left
105   double rx_clock;
106   emu_timer *rx_timer;
107
108   state_t tx_state;
109   UINT8 tx_data;      // byte being sent
110   UINT8 tx_buffer;    // next byte to send
111   UINT8 tx_parity;
112   UINT16 tx_pulses;   // total pulses left
113   double tx_clock;
114   emu_timer *tx_timer;
115
116   devcb_resolved_read8    read_si;                /* SI - pin 20 - This will be called whenever the SI pin is sampled. Optional */
117   devcb_resolved_write8   write_so;               /* SO - pin 25 - This will be called whenever data is put on the SO pin. Optional */
118   devcb_resolved_write8   status_changed;         /* This will be called whenever one of the status pins may have changed. Optional */
119};
120
121
122/* control reg */
123#define CONTROL_NB1     0x01
124#define CONTROL_NB2     0x02
125#define CONTROL_TSB     0x04
126#define CONTROL_EPS     0x08
127#define CONTROL_NP      0x10
128
129
130/* status reg */
131#define STATUS_TBMT     0x01
132#define STATUS_DAV      0x02
133#define STATUS_OR       0x04
134#define STATUS_FE       0x08
135#define STATUS_PE       0x10
136#define STATUS_EOC      0x20
137
138
139/*-------------------------------------------------
140    get_safe_token - safely gets the data
141-------------------------------------------------*/
142
143INLINE ay31015_t *get_safe_token(device_t *device)
144{
145   assert(device != NULL);
146   assert(device->type() == AY31015);
147   return (ay31015_t *) downcast<ay31015_device *>(device)->token();
148}
149
150
151INLINE UINT8 ay31015_get_si( device_t *device )
152{
153   ay31015_t   *ay31015 = get_safe_token( device );
154
155   if ( !ay31015->read_si.isnull() )
156      ay31015->pins[AY31015_SI] = ay31015->read_si( 0 ) ? 1 : 0;
157
158   return ay31015->pins[AY31015_SI];
159}
160
161
162INLINE void ay31015_set_so( device_t *device, int data )
163{
164   ay31015_t   *ay31015 = get_safe_token( device );
165
166   ay31015->pins[AY31015_SO] = data ? 1 : 0;
167
168   if ( !ay31015->write_so.isnull() )
169      ay31015->write_so( 0, ay31015->pins[AY31015_SO] );
170}
171
172
173INLINE int ay31015_update_status_pin( ay31015_t *ay31015, UINT8 reg_bit, ay31015_output_pin_t pin )
174{
175   int new_value = ( ay31015->status_reg & reg_bit ) ? 1 : 0;
176
177   if ( new_value == ay31015->pins[pin] )
178      return 0;
179
180   ay31015->pins[pin] = new_value;
181   return 1;
182}
183
184
185/*-------------------------------------------------
186    ay31015_update_status_pins - Update the status pins
187-------------------------------------------------*/
188static void ay31015_update_status_pins( device_t *device )
189{
190   ay31015_t   *ay31015 = get_safe_token( device );
191   int status_pins_changed = 0;
192
193   /* Should status pins be updated? */
194   if ( ! ay31015->pins[AY31015_SWE] )
195   {
196      status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_PE, AY31015_PE );
197      status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_FE, AY31015_FE );
198      status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_OR, AY31015_OR );
199      status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_DAV, AY31015_DAV );
200      status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_TBMT, AY31015_TBMT );
201   }
202   status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_EOC, AY31015_EOC );
203
204   if ( status_pins_changed && !ay31015->status_changed.isnull() )
205   {
206      ay31015->status_changed( 0, status_pins_changed );
207   }
208}
209
210
211/*************************************************** RECEIVE CONTROLS *************************************************/
212
213
214/*-------------------------------------------------
215    ay31015_rx_process - convert serial to parallel
216-------------------------------------------------*/
217static TIMER_CALLBACK( ay31015_rx_process )
218{
219   device_t *device = (device_t *)ptr;
220   ay31015_t           *ay31015 = get_safe_token( device );
221
222   switch (ay31015->rx_state)
223   {
224      case PREP_TIME:                         // assist sync by ensuring high bit occurs
225         ay31015->rx_pulses--;
226         if (ay31015_get_si( device ))
227            ay31015->rx_state = IDLE;
228         return;
229
230      case IDLE:
231         ay31015->rx_pulses--;
232         if (!ay31015_get_si( device ))
233         {
234            ay31015->rx_state = START_BIT;
235            ay31015->rx_pulses = 16;
236         }
237         return;
238
239      case START_BIT:
240         ay31015->rx_pulses--;
241         if (ay31015->rx_pulses == 8)            // start bit must be low at sample time
242         {
243            if ( ay31015_get_si( device ) )
244               ay31015->rx_state = IDLE;
245         }
246         else
247         if (!ay31015->rx_pulses)                    // end of start bit
248         {
249            ay31015->rx_state = PROCESSING;
250            ay31015->rx_pulses = ay31015->total_pulses;
251            ay31015->rx_bit_count = 0;
252            ay31015->rx_parity = 0;
253            ay31015->rx_data = 0;
254         }
255         return;
256
257      case PROCESSING:
258         ay31015->rx_pulses--;
259         if (!ay31015->rx_pulses)                    // end of a byte
260         {
261            ay31015->rx_pulses = 16;
262            if (ay31015->control_reg & CONTROL_NP)      // see if we need to get a parity bit
263               ay31015->rx_state = FIRST_STOP_BIT;
264            else
265               ay31015->rx_state = PARITY_BIT;
266         }
267         else
268         if (!(ay31015->rx_pulses & 15))             // end of a bit
269            ay31015->rx_bit_count++;
270         else
271         if ((ay31015->rx_pulses & 15) == 8)             // sample input stream
272         {
273            ay31015->internal_sample = ay31015_get_si( device );
274            ay31015->rx_parity ^= ay31015->internal_sample;     // calculate cumulative parity
275            ay31015->rx_data |= ay31015->internal_sample << ay31015->rx_bit_count;
276         }
277         return;
278
279      case PARITY_BIT:
280         ay31015->rx_pulses--;
281
282         if (ay31015->rx_pulses == 8)                    // sample input stream
283         {
284            ay31015->rx_parity ^= ay31015_get_si( device );             // calculate cumulative parity
285         }
286         else
287         if (!ay31015->rx_pulses)                    // end of a byte
288         {
289            ay31015->rx_pulses = 16;
290            ay31015->rx_state = FIRST_STOP_BIT;
291
292            if ((!(ay31015->control_reg & CONTROL_EPS)) && (ay31015->rx_parity))
293               ay31015->rx_parity = 0;         // odd parity, ok
294            else
295            if ((ay31015->control_reg & CONTROL_EPS) && (!ay31015->rx_parity))
296               ay31015->rx_parity = 0;         // even parity, ok
297            else
298               ay31015->rx_parity = 1;         // parity error
299         }
300         return;
301
302      case FIRST_STOP_BIT:
303         ay31015->rx_pulses--;
304         if (ay31015->rx_pulses == 8)                // sample input stream
305            ay31015->internal_sample = ay31015_get_si( device );
306         else
307         if (ay31015->rx_pulses == 7)                // set error flags
308         {
309            if (!ay31015->internal_sample)
310            {
311               ay31015->status_reg |= STATUS_FE;       // framing error - the stop bit not high
312               ay31015->rx_state = PREP_TIME;      // lost sync - start over
313         //      return;
314            }
315            else
316               ay31015->status_reg &= ~STATUS_FE;
317
318            if ((ay31015->rx_parity) && (!(ay31015->control_reg & CONTROL_NP)))
319               ay31015->status_reg |= STATUS_PE;       // parity error
320            else
321               ay31015->status_reg &= ~STATUS_PE;
322
323            if (ay31015->status_reg & STATUS_DAV)
324               ay31015->status_reg |= STATUS_OR;       // overrun error - previous byte still in buffer
325            else
326               ay31015->status_reg &= ~STATUS_OR;
327
328            ay31015->rx_buffer = ay31015->rx_data;      // bring received byte out for computer to read
329
330            ay31015_update_status_pins( device );
331         }
332         else
333         if (ay31015->rx_pulses == 6)
334         {
335            ay31015->status_reg |= STATUS_DAV;      // tell computer that new byte is ready
336            ay31015_update_status_pins( device );
337         }
338         else
339         if (ay31015->rx_pulses == 4)
340         {
341            if (ay31015->second_stop_bit)
342            {
343               /* We should wait for the full first stop bit and
344                  the beginning of the second stop bit */
345               ay31015->rx_state = SECOND_STOP_BIT;
346               ay31015->rx_pulses += ay31015->second_stop_bit - 7;
347            }
348            else
349            {
350               /* We have seen a STOP bit, go back to PREP_TIME */
351               ay31015->rx_state = PREP_TIME;
352            }
353         }
354         return;
355
356      case SECOND_STOP_BIT:
357         ay31015->rx_pulses--;
358         if (!ay31015->rx_pulses)
359            ay31015->rx_state = PREP_TIME;
360         return;
361
362   }
363}
364
365
366/*************************************************** TRANSMIT CONTROLS *************************************************/
367
368
369/*-------------------------------------------------
370    ay31015_tx_process - convert parallel to serial
371-------------------------------------------------*/
372static TIMER_CALLBACK( ay31015_tx_process )
373{
374   device_t *device = (device_t *)ptr;
375   ay31015_t           *ay31015 = get_safe_token( device );
376
377   UINT8 t1;
378   switch (ay31015->tx_state)
379   {
380      case IDLE:
381         if (!(ay31015->status_reg & STATUS_TBMT))
382         {
383            ay31015->tx_state = PREP_TIME;      // When idle, see if a byte has been sent to us
384            ay31015->tx_pulses = 1;
385         }
386         return;
387
388      case PREP_TIME:                     // This phase lets the transmitter regain sync after an idle period
389         ay31015->tx_pulses--;
390         if (!ay31015->tx_pulses)
391         {
392            ay31015->tx_state = START_BIT;
393            ay31015->tx_pulses = 16;
394         }
395         return;
396
397      case START_BIT:
398         if (ay31015->tx_pulses == 16)               // beginning of start bit
399         {
400            ay31015->tx_data = ay31015->tx_buffer;          // load the shift register
401            ay31015->status_reg |= STATUS_TBMT;         // tell computer that another byte can be sent to uart
402            ay31015_set_so( device, 0 );                /* start bit begins now (we are "spacing") */
403            ay31015->status_reg &= ~STATUS_EOC;         // we are no longer idle
404            ay31015->tx_parity = 0;
405            ay31015_update_status_pins( device );
406         }
407
408         ay31015->tx_pulses--;
409         if (!ay31015->tx_pulses)                    // end of start bit
410         {
411            ay31015->tx_state = PROCESSING;
412            ay31015->tx_pulses = ay31015->total_pulses;
413         }
414         return;
415
416      case PROCESSING:
417         if (!(ay31015->tx_pulses & 15))             // beginning of a data bit
418         {
419            if (ay31015->tx_data & 1)
420            {
421               ay31015_set_so( device, 1 );
422               ay31015->tx_parity++;               // calculate cumulative parity
423            }
424            else
425               ay31015_set_so( device, 0 );
426
427            ay31015->tx_data >>= 1;             // adjust the shift register
428         }
429
430         ay31015->tx_pulses--;
431         if (!ay31015->tx_pulses)                    // all data bits sent
432         {
433            ay31015->tx_pulses = 16;
434            if (ay31015->control_reg & CONTROL_NP)      // see if we need to make a parity bit
435               ay31015->tx_state = FIRST_STOP_BIT;
436            else
437               ay31015->tx_state = PARITY_BIT;
438         }
439
440         return;
441
442      case PARITY_BIT:
443         if (ay31015->tx_pulses == 16)
444         {
445            t1 = (ay31015->control_reg & CONTROL_EPS) ? 0 : 1;
446            t1 ^= (ay31015->tx_parity & 1);
447            if (t1)
448               ay31015_set_so( device, 1 );            /* extra bit to set the correct parity */
449            else
450               ay31015_set_so( device, 0 );            /* it was already correct */
451         }
452
453         ay31015->tx_pulses--;
454         if (!ay31015->tx_pulses)
455         {
456            ay31015->tx_state = FIRST_STOP_BIT;
457            ay31015->tx_pulses = 16;
458         }
459         return;
460
461      case FIRST_STOP_BIT:
462         if (ay31015->tx_pulses == 16)
463            ay31015_set_so( device, 1 );                /* create a stop bit (marking and soon idle) */
464         ay31015->tx_pulses--;
465         if (!ay31015->tx_pulses)
466         {
467            ay31015->status_reg |= STATUS_EOC;          // character is completely sent
468            if (ay31015->second_stop_bit)
469            {
470               ay31015->tx_state = SECOND_STOP_BIT;
471               ay31015->tx_pulses = ay31015->second_stop_bit;
472            }
473            else
474            if (ay31015->status_reg & STATUS_TBMT)
475               ay31015->tx_state = IDLE;           // if nothing to send, go idle
476            else
477            {
478               ay31015->tx_pulses = 16;
479               ay31015->tx_state = START_BIT;      // otherwise immediately start next byte
480            }
481            ay31015_update_status_pins( device );
482         }
483         return;
484
485      case SECOND_STOP_BIT:
486         ay31015->tx_pulses--;
487         if (!ay31015->tx_pulses)
488         {
489            if (ay31015->status_reg & STATUS_TBMT)
490               ay31015->tx_state = IDLE;           // if nothing to send, go idle
491            else
492            {
493               ay31015->tx_pulses = 16;
494               ay31015->tx_state = START_BIT;      // otherwise immediately start next byte
495            }
496         }
497         return;
498
499   }
500}
501
502
503/*-------------------------------------------------
504    ay31015_reset - reset internal state
505-------------------------------------------------*/
506static void ay31015_reset( device_t *device )
507{
508   ay31015_t   *ay31015 = get_safe_token( device );
509
510   /* total pulses = 16 * data-bits */
511   UINT8 t1;
512
513   if ( ay31015->control_reg & CONTROL_NB2 )
514      t1 = ( ay31015->control_reg & CONTROL_NB1 ) ? 8 : 7;
515   else
516      t1 = ( ay31015->control_reg & CONTROL_NB1 ) ? 6 : 5;
517
518   ay31015->total_pulses = t1 << 4;                    /* total clock pulses to load a byte */
519   ay31015->second_stop_bit = ((ay31015->control_reg & CONTROL_TSB) ? 16 : 0);     /* 2nd stop bit */
520   if ((t1 == 5) && (ay31015->second_stop_bit == 16))
521      ay31015->second_stop_bit = 8;               /* 5 data bits and 2 stop bits = 1.5 stop bits */
522   ay31015->status_reg = STATUS_EOC | STATUS_TBMT;
523   ay31015->tx_data = 0;
524   ay31015->rx_state = PREP_TIME;
525   ay31015->tx_state = IDLE;
526   ay31015->pins[AY31015_SI] = 1;
527   ay31015_set_so( device, 1 );
528
529   if ( ay31015->config->type == AY_3_1015 )
530      ay31015->rx_data = 0;
531
532}
533
534
535/*-------------------------------------------------
536    ay31015_transfer_control_pins - transfers contents of controls pins to the control register
537-------------------------------------------------*/
538static void ay31015_transfer_control_pins( device_t *device )
539{
540   ay31015_t   *ay31015 = get_safe_token( device );
541   UINT8 control = 0;
542
543   control |= ay31015->pins[AY31015_NP ] ? CONTROL_NP  : 0;
544   control |= ay31015->pins[AY31015_TSB] ? CONTROL_TSB : 0;
545   control |= ay31015->pins[AY31015_NB1] ? CONTROL_NB1 : 0;
546   control |= ay31015->pins[AY31015_NB2] ? CONTROL_NB2 : 0;
547   control |= ay31015->pins[AY31015_EPS] ? CONTROL_EPS : 0;
548
549   if ( ay31015->control_reg != control )
550   {
551      ay31015->control_reg = control;
552      ay31015_reset( device );
553   }
554}
555
556
557/*-------------------------------------------------
558    ay31015_set_input_pin - set an input pin
559-------------------------------------------------*/
560void ay31015_set_input_pin( device_t *device, ay31015_input_pin_t pin, int data )
561{
562   ay31015_t   *ay31015 = get_safe_token(device);
563
564   data = data ? 1 : 0;
565
566   switch ( pin )
567   {
568   case AY31015_SWE:
569      ay31015->pins[pin] = data;
570      ay31015_update_status_pins( device );
571      break;
572   case AY31015_RDAV:
573      ay31015->pins[pin] = data;
574      if ( ! data )
575      {
576         ay31015->status_reg &= ~STATUS_DAV;
577         ay31015->pins[AY31015_DAV] = 0;
578      }
579      break;
580   case AY31015_SI:
581      ay31015->pins[pin] = data;
582      break;
583   case AY31015_XR:
584      ay31015->pins[pin] = data;
585      if ( data )
586         ay31015_reset( device );
587      break;
588   case AY31015_CS:
589   case AY31015_NP:
590   case AY31015_TSB:
591   case AY31015_NB1:
592   case AY31015_NB2:
593   case AY31015_EPS:
594      ay31015->pins[pin] = data;
595      if ( ay31015->pins[AY31015_CS] )
596         ay31015_transfer_control_pins( device );
597      break;
598   }
599}
600
601
602/*-------------------------------------------------
603    ay31015_get_output_pin - get the status of an output pin
604-------------------------------------------------*/
605int ay31015_get_output_pin( device_t *device, ay31015_output_pin_t pin )
606{
607   ay31015_t   *ay31015 = get_safe_token(device);
608
609   return ay31015->pins[pin];
610}
611
612
613INLINE void ay31015_update_rx_timer( device_t *device )
614{
615   ay31015_t   *ay31015 = get_safe_token( device );
616
617   if ( ay31015->rx_clock > 0.0 )
618   {
619      ay31015->rx_timer->adjust( attotime::from_hz( ay31015->rx_clock ), 0, attotime::from_hz( ay31015->rx_clock ) );
620   }
621   else
622   {
623      ay31015->rx_timer->enable( 0 );
624   }
625}
626
627
628INLINE void ay31015_update_tx_timer( device_t *device )
629{
630   ay31015_t   *ay31015 = get_safe_token( device );
631
632   if ( ay31015->tx_clock > 0.0 )
633   {
634      ay31015->tx_timer->adjust( attotime::from_hz( ay31015->tx_clock ), 0, attotime::from_hz( ay31015->tx_clock ) );
635   }
636   else
637   {
638      ay31015->tx_timer->enable( 0 );
639   }
640}
641
642
643/*-------------------------------------------------
644    ay31015_set_receiver_clock - set receive clock
645-------------------------------------------------*/
646void ay31015_set_receiver_clock( device_t *device, double new_clock )
647{
648   ay31015_t   *ay31015 = get_safe_token(device);
649
650   ay31015->rx_clock = new_clock;
651   ay31015_update_rx_timer( device );
652}
653
654
655/*-------------------------------------------------
656    ay31015_set_transmitter_clock - set transmit clock
657-------------------------------------------------*/
658void ay31015_set_transmitter_clock( device_t *device, double new_clock )
659{
660   ay31015_t   *ay31015 = get_safe_token(device);
661
662   ay31015->tx_clock = new_clock;
663   ay31015_update_tx_timer( device );
664}
665
666
667/*-------------------------------------------------
668    ay31015_get_received_data - return a byte to the computer
669-------------------------------------------------*/
670UINT8 ay31015_get_received_data( device_t *device )
671{
672   ay31015_t   *ay31015 = get_safe_token(device);
673
674   return ay31015->rx_buffer;
675}
676
677
678/*-------------------------------------------------
679    ay31015_set_transmit_data - accept a byte to transmit, if able
680-------------------------------------------------*/
681void ay31015_set_transmit_data( device_t *device, UINT8 data )
682{
683   ay31015_t   *ay31015 = get_safe_token(device);
684
685   if (ay31015->status_reg & STATUS_TBMT)
686   {
687      ay31015->tx_buffer = data;
688      ay31015->status_reg &= ~STATUS_TBMT;
689      ay31015_update_status_pins( device );
690   }
691}
692
693
694static DEVICE_START(ay31015)
695{
696   ay31015_t   *ay31015 = get_safe_token(device);
697
698   ay31015->config = (const ay31015_config*)device->static_config();
699
700   ay31015->read_si.resolve(ay31015->config->read_si_cb, *device);
701   ay31015->write_so.resolve(ay31015->config->write_so_cb, *device);
702   ay31015->status_changed.resolve(ay31015->config->status_changed_cb, *device);
703
704   ay31015->tx_clock = ay31015->config->transmitter_clock;
705   ay31015->rx_clock = ay31015->config->receiver_clock;
706
707   ay31015->rx_timer = device->machine().scheduler().timer_alloc(FUNC(ay31015_rx_process), (void *)device );
708   ay31015->tx_timer = device->machine().scheduler().timer_alloc(FUNC(ay31015_tx_process), (void *)device );
709
710   ay31015_update_rx_timer( device );
711   ay31015_update_tx_timer( device );
712}
713
714
715static DEVICE_RESET( ay31015 )
716{
717   ay31015_t   *ay31015 = get_safe_token(device);
718
719   ay31015->control_reg = 0;
720   ay31015->rx_data = 0;
721
722   ay31015_reset( device );
723}
724
725
726const device_type AY31015 = &device_creator<ay31015_device>;
727
728ay31015_device::ay31015_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
729   : device_t(mconfig, AY31015, "AY-3-1015", tag, owner, clock)
730{
731   m_token = global_alloc_clear(ay31015_t);
732}
733
734//-------------------------------------------------
735//  device_config_complete - perform any
736//  operations now that the configuration is
737//  complete
738//-------------------------------------------------
739
740void ay31015_device::device_config_complete()
741{
742}
743
744//-------------------------------------------------
745//  device_start - device-specific startup
746//-------------------------------------------------
747
748void ay31015_device::device_start()
749{
750   DEVICE_START_NAME( ay31015 )(this);
751}
752
753//-------------------------------------------------
754//  device_reset - device-specific reset
755//-------------------------------------------------
756
757void ay31015_device::device_reset()
758{
759   DEVICE_RESET_NAME( ay31015 )(this);
760}
Property changes on: trunk/src/emu/machine/ay31015.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/ay31015.h
r0r21685
1/* ay31015.h
2
3    Written for MESS by Robbbert on May 29th, 2008.
4
5*/
6
7#ifndef __AY31015_H_
8#define __AY31015_H_
9
10/***************************************************************************
11    TYPE DEFINITIONS
12***************************************************************************/
13
14
15enum ay31015_type_t
16{
17   /* For AY-3-1014A, AY-3-1015(D) and HD6402 variants */
18   AY_3_1015,
19
20   /* For AY-3-1014, AY-5-1013 and AY-6-1013 variants */
21   AY_5_1013
22};
23
24
25enum ay31015_input_pin_t
26{
27   AY31015_SWE=16,         /* -SWE  - Pin 16 - Status word enable */
28   AY31015_RDAV=18,        /* -RDAV - Pin 18 - Reset data available */
29   AY31015_SI=20,          /*  SI   - Pin 20 - Serial input */
30   AY31015_XR=21,          /*  XR   - Pin 21 - External reset */
31   AY31015_CS=34,          /*  CS   - Pin 34 - Control strobe */
32   AY31015_NP=35,          /*  NP   - Pin 35 - No parity */
33   AY31015_TSB=36,         /*  TSB  - Pin 36 - Number of stop bits */
34   AY31015_NB1=37,         /*  NB1  - Pin 37 - Number of bits #1 */
35   AY31015_NB2=38,         /*  NB2  - Pin 38 - Number of bits #2 */
36   AY31015_EPS=39          /*  EPS  - Pin 39 - Odd/Even parity select */
37};
38
39
40enum ay31015_output_pin_t
41{
42   AY31015_PE=13,          /* PE   - Pin 13 - Parity error */
43   AY31015_FE=14,          /* FE   - Pin 14 - Framing error */
44   AY31015_OR=15,          /* OR   - Pin 15 - Over-run */
45   AY31015_DAV=19,         /* DAV  - Pin 19 - Data available */
46   AY31015_TBMT=22,        /* TBMT - Pin 22 - Transmit buffer empty */
47   AY31015_EOC=24,         /* EOC  - Pin 24 - End of character */
48   AY31015_SO=25           /* SO   - Pin 25 - Serial output */
49};
50
51
52struct  ay31015_config
53{
54   ay31015_type_t      type;                   /* Type of chip */
55   double              transmitter_clock;      /* TCP - pin 40 */
56   double              receiver_clock;         /* RCP - pin 17 */
57   devcb_read8         read_si_cb;             /* SI - pin 20 - This will be called whenever the SI pin is sampled. Optional */
58   devcb_write8        write_so_cb;                /* SO - pin 25 - This will be called whenever data is put on the SO pin. Optional */
59   devcb_write8        status_changed_cb;          /* This will be called whenever one of the status pins may have changed. Optional */
60};
61
62
63/***************************************************************************
64    DEVICE CONFIGURATION MACROS
65***************************************************************************/
66
67#define MCFG_AY31015_ADD(_tag, _config) \
68   MCFG_DEVICE_ADD(_tag, AY31015, 0)       \
69   MCFG_DEVICE_CONFIG(_config)
70
71
72/***************************************************************************
73    FUNCTION PROTOTYPES
74***************************************************************************/
75
76/* Set an input pin */
77void ay31015_set_input_pin( device_t *device, ay31015_input_pin_t pin, int data );
78
79
80/* Get an output pin */
81int ay31015_get_output_pin( device_t *device, ay31015_output_pin_t pin );
82
83
84/* Set a new transmitter clock (new_clock is in Hz) */
85void ay31015_set_transmitter_clock( device_t *device, double new_clock );
86
87
88/* Set a new receiver clock (new_clock is in Hz) */
89void ay31015_set_receiver_clock( device_t *device, double new_clock );
90
91
92/* Reead the received data */
93/* The received data is available on RD8-RD1 (pins 5-12) */
94UINT8 ay31015_get_received_data( device_t *device );
95
96
97/* Set the transmitter buffer */
98/* The data to transmit is set on DB1-DB8 (pins 26-33) */
99void ay31015_set_transmit_data( device_t *device, UINT8 data );
100
101
102/***************************************************************************
103    DEVICE INTERFACE
104***************************************************************************/
105
106class ay31015_device : public device_t
107{
108public:
109   ay31015_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
110   ~ay31015_device() { global_free(m_token); }
111
112   // access to legacy token
113   void *token() const { assert(m_token != NULL); return m_token; }
114protected:
115   // device-level overrides
116   virtual void device_config_complete();
117   virtual void device_start();
118   virtual void device_reset();
119private:
120   // internal state
121   void *m_token;
122};
123
124extern const device_type AY31015;
125
126#endif
Property changes on: trunk/src/emu/machine/ay31015.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/mc68328.c
r0r21685
1/**********************************************************************
2
3    Motorola 68328 ("DragonBall") System-on-a-Chip implementation
4
5    By MooglyGuy
6    contact mooglyguy@gmail.com with licensing and usage questions.
7
8**********************************************************************/
9
10#include "emu.h"
11#include "cpu/m68000/m68000.h"
12#include "includes/mc68328.h"
13#include "mc68328.h"
14
15#define VERBOSE_LEVEL   (0)
16
17INLINE void verboselog(running_machine &machine, int n_level, const char *s_fmt, ...)
18{
19   if( VERBOSE_LEVEL >= n_level )
20   {
21      va_list v;
22      char buf[ 32768 ];
23      va_start( v, s_fmt );
24      vsprintf( buf, s_fmt, v );
25      va_end( v );
26      logerror( "%s: %s", machine.describe_context(), buf );
27   }
28}
29
30static void mc68328_set_interrupt_line(device_t *device, UINT32 line, UINT32 active)
31{
32   mc68328_t* mc68328 = mc68328_get_safe_token( device );
33   device_t *cpu = device->machine().device(mc68328->iface->m68k_cpu_tag);
34
35   if(active)
36   {
37      mc68328->regs.ipr |= line;
38
39      if(!(mc68328->regs.imr & line) && !(mc68328->regs.isr & line))
40      {
41         mc68328->regs.isr |= line;
42
43         if(mc68328->regs.isr & INT_M68K_LINE7)
44         {
45            cpu->execute().set_input_line_and_vector(M68K_IRQ_7, ASSERT_LINE, mc68328->regs.ivr | 0x07);
46         }
47         else if(mc68328->regs.isr & INT_M68K_LINE6)
48         {
49            cpu->execute().set_input_line_and_vector(M68K_IRQ_6, ASSERT_LINE, mc68328->regs.ivr | 0x06);
50         }
51         else if(mc68328->regs.isr & INT_M68K_LINE5)
52         {
53            cpu->execute().set_input_line_and_vector(M68K_IRQ_5, ASSERT_LINE, mc68328->regs.ivr | 0x05);
54         }
55         else if(mc68328->regs.isr & INT_M68K_LINE4)
56         {
57            cpu->execute().set_input_line_and_vector(M68K_IRQ_4, ASSERT_LINE, mc68328->regs.ivr | 0x04);
58         }
59         else if(mc68328->regs.isr & INT_M68K_LINE3)
60         {
61            cpu->execute().set_input_line_and_vector(M68K_IRQ_3, ASSERT_LINE, mc68328->regs.ivr | 0x03);
62         }
63         else if(mc68328->regs.isr & INT_M68K_LINE2)
64         {
65            cpu->execute().set_input_line_and_vector(M68K_IRQ_2, ASSERT_LINE, mc68328->regs.ivr | 0x02);
66         }
67         else if(mc68328->regs.isr & INT_M68K_LINE1)
68         {
69            cpu->execute().set_input_line_and_vector(M68K_IRQ_1, ASSERT_LINE, mc68328->regs.ivr | 0x01);
70         }
71      }
72   }
73   else
74   {
75      mc68328->regs.isr &= ~line;
76
77      if((line & INT_M68K_LINE7) && !(mc68328->regs.isr & INT_M68K_LINE7))
78      {
79         cpu->execute().set_input_line(M68K_IRQ_7, CLEAR_LINE);
80      }
81      if((line & INT_M68K_LINE6) && !(mc68328->regs.isr & INT_M68K_LINE6))
82      {
83         cpu->execute().set_input_line(M68K_IRQ_6, CLEAR_LINE);
84      }
85      if((line & INT_M68K_LINE5) && !(mc68328->regs.isr & INT_M68K_LINE5))
86      {
87         cpu->execute().set_input_line(M68K_IRQ_5, CLEAR_LINE);
88      }
89      if((line & INT_M68K_LINE4) && !(mc68328->regs.isr & INT_M68K_LINE4))
90      {
91         cpu->execute().set_input_line(M68K_IRQ_4, CLEAR_LINE);
92      }
93      if((line & INT_M68K_LINE3) && !(mc68328->regs.isr & INT_M68K_LINE3))
94      {
95         cpu->execute().set_input_line(M68K_IRQ_3, CLEAR_LINE);
96      }
97      if((line & INT_M68K_LINE2) && !(mc68328->regs.isr & INT_M68K_LINE2))
98      {
99         cpu->execute().set_input_line(M68K_IRQ_2, CLEAR_LINE);
100      }
101      if((line & INT_M68K_LINE1) && !(mc68328->regs.isr & INT_M68K_LINE1))
102      {
103         cpu->execute().set_input_line(M68K_IRQ_1, CLEAR_LINE);
104      }
105   }
106}
107
108static void mc68328_poll_port_d_interrupts(device_t *device)
109{
110   mc68328_t* mc68328 = mc68328_get_safe_token( device );
111   UINT8 line_transitions = mc68328->regs.pddataedge & mc68328->regs.pdirqedge;
112   UINT8 line_holds = mc68328->regs.pddata &~ mc68328->regs.pdirqedge;
113   UINT8 line_interrupts = (line_transitions | line_holds) & mc68328->regs.pdirqen;
114
115   if(line_interrupts)
116   {
117      mc68328_set_interrupt_line(device, line_interrupts << 8, 1);
118   }
119   else
120   {
121      mc68328_set_interrupt_line(device, INT_KBDINTS, 0);
122   }
123}
124
125void mc68328_set_penirq_line(device_t *device, int state)
126{
127   mc68328_t* mc68328 = mc68328_get_safe_token( device );
128
129   if(state)
130   {
131      mc68328_set_interrupt_line(device, INT_PEN, 1);
132   }
133   else
134   {
135      mc68328->regs.ipr &= ~INT_PEN;
136      mc68328_set_interrupt_line(device, INT_PEN, 0);
137   }
138}
139
140void mc68328_set_port_d_lines(device_t *device, UINT8 state, int bit)
141{
142   mc68328_t* mc68328 = mc68328_get_safe_token( device );
143   UINT8 old_button_state = mc68328->regs.pddata;
144
145   if(state & (1 << bit))
146   {
147      mc68328->regs.pddata |= (1 << bit);
148   }
149   else
150   {
151      mc68328->regs.pddata &= ~(1 << bit);
152   }
153
154   mc68328->regs.pddataedge |= ~old_button_state & mc68328->regs.pddata;
155
156   mc68328_poll_port_d_interrupts(device);
157}
158
159static UINT32 mc68328_get_timer_frequency(device_t *device, UINT32 index)
160{
161   mc68328_t* mc68328 = mc68328_get_safe_token( device );
162   UINT32 frequency = 0;
163
164   switch(mc68328->regs.tctl[index] & TCTL_CLKSOURCE)
165   {
166      case TCTL_CLKSOURCE_SYSCLK:
167         frequency = 32768 * 506;
168         break;
169
170      case TCTL_CLKSOURCE_SYSCLK16:
171         frequency = (32768 * 506) / 16;
172         break;
173
174      case TCTL_CLKSOURCE_32KHZ4:
175      case TCTL_CLKSOURCE_32KHZ5:
176      case TCTL_CLKSOURCE_32KHZ6:
177      case TCTL_CLKSOURCE_32KHZ7:
178         frequency = 32768;
179         break;
180   }
181   frequency /= (mc68328->regs.tprer[index] + 1);
182
183   return frequency;
184}
185
186static void mc68328_maybe_start_timer(device_t *device, UINT32 index, UINT32 new_enable)
187{
188   mc68328_t* mc68328 = mc68328_get_safe_token( device );
189
190   if((mc68328->regs.tctl[index] & TCTL_TEN) == TCTL_TEN_ENABLE && (mc68328->regs.tctl[index] & TCTL_CLKSOURCE) > TCTL_CLKSOURCE_STOP)
191   {
192      if((mc68328->regs.tctl[index] & TCTL_CLKSOURCE) == TCTL_CLKSOURCE_TIN)
193      {
194         mc68328->gptimer[index]->adjust(attotime::never);
195      }
196      else if(mc68328->regs.tcmp[index] == 0)
197      {
198         mc68328->gptimer[index]->adjust(attotime::never);
199      }
200      else
201      {
202         UINT32 frequency = mc68328_get_timer_frequency(device, index);
203         attotime period = (attotime::from_hz(frequency) *  mc68328->regs.tcmp[index]);
204
205         if(new_enable)
206         {
207            mc68328->regs.tcn[index] = 0x0000;
208         }
209
210         mc68328->gptimer[index]->adjust(period);
211      }
212   }
213   else
214   {
215      mc68328->gptimer[index]->adjust(attotime::never);
216   }
217}
218
219static void mc68328_timer_compare_event(device_t *device, UINT32 index)
220{
221   mc68328_t* mc68328 = mc68328_get_safe_token( device );
222
223   mc68328->regs.tcn[index] = mc68328->regs.tcmp[index];
224   mc68328->regs.tstat[index] |= TSTAT_COMP;
225
226   if((mc68328->regs.tctl[index] & TCTL_FRR) == TCTL_FRR_RESTART)
227   {
228      UINT32 frequency = mc68328_get_timer_frequency(device, index);
229
230      if(frequency > 0)
231      {
232         attotime period = attotime::from_hz(frequency) * mc68328->regs.tcmp[index];
233
234         mc68328->regs.tcn[index] = 0x0000;
235
236         mc68328->gptimer[index]->adjust(period);
237      }
238      else
239      {
240         mc68328->gptimer[index]->adjust(attotime::never);
241      }
242   }
243   else
244   {
245      UINT32 frequency = mc68328_get_timer_frequency(device, index);
246
247      if(frequency > 0)
248      {
249         attotime period = attotime::from_hz(frequency) * 0x10000;
250
251         mc68328->gptimer[index]->adjust(period);
252      }
253      else
254      {
255         mc68328->gptimer[index]->adjust(attotime::never);
256      }
257   }
258   if((mc68328->regs.tctl[index] & TCTL_IRQEN) == TCTL_IRQEN_ENABLE)
259   {
260      mc68328_set_interrupt_line(device, (index == 0) ? INT_TIMER1 : INT_TIMER2, 1);
261   }
262}
263
264static TIMER_CALLBACK( mc68328_timer1_hit )
265{
266   device_t *device = machine.device(MC68328_TAG);
267
268   mc68328_timer_compare_event(device, 0);
269}
270
271static TIMER_CALLBACK( mc68328_timer2_hit )
272{
273   device_t *device = machine.device(MC68328_TAG);
274
275   mc68328_timer_compare_event(device, 1);
276}
277
278static TIMER_CALLBACK( mc68328_pwm_transition )
279{
280   device_t *device = machine.device(MC68328_TAG);
281   mc68328_t* mc68328 = mc68328_get_safe_token( device );
282
283   if(mc68328->regs.pwmw >= mc68328->regs.pwmp || mc68328->regs.pwmw == 0 || mc68328->regs.pwmp == 0)
284   {
285      mc68328->pwm->adjust(attotime::never);
286      return;
287   }
288
289   if(((mc68328->regs.pwmc & PWMC_POL) == 0 && (mc68328->regs.pwmc & PWMC_PIN) != 0) ||
290      ((mc68328->regs.pwmc & PWMC_POL) != 0 && (mc68328->regs.pwmc & PWMC_PIN) == 0))
291   {
292      UINT32 frequency = 32768 * 506;
293      UINT32 divisor = 4 << (mc68328->regs.pwmc & PWMC_CLKSEL); // ?? Datasheet says 2 <<, but then we're an octave higher than CoPilot.
294      attotime period;
295
296      frequency /= divisor;
297      period = attotime::from_hz(frequency) * (mc68328->regs.pwmp - mc68328->regs.pwmw);
298
299      mc68328->pwm->adjust(period);
300
301      if(mc68328->regs.pwmc & PWMC_IRQEN)
302      {
303         mc68328_set_interrupt_line(device, INT_PWM, 1);
304      }
305   }
306   else
307   {
308      UINT32 frequency = 32768 * 506;
309      UINT32 divisor = 4 << (mc68328->regs.pwmc & PWMC_CLKSEL); // ?? Datasheet says 2 <<, but then we're an octave higher than CoPilot.
310      attotime period;
311
312      frequency /= divisor;
313      period = attotime::from_hz(frequency) * mc68328->regs.pwmw;
314
315      mc68328->pwm->adjust(period);
316   }
317
318   mc68328->regs.pwmc ^= PWMC_PIN;
319
320   if( !mc68328->out_pwm.isnull() )
321   {
322      mc68328->out_pwm( 0, (mc68328->regs.pwmc & PWMC_PIN) ? 1 : 0 );
323   }
324}
325
326static TIMER_CALLBACK( mc68328_rtc_tick )
327{
328   device_t *device = machine.device(MC68328_TAG);
329   mc68328_t* mc68328 = mc68328_get_safe_token( device );
330
331   if(mc68328->regs.rtcctl & RTCCTL_ENABLE)
332   {
333      UINT32 set_int = 0;
334
335      mc68328->regs.hmsr++;
336
337      if(mc68328->regs.rtcienr & RTCINT_SECOND)
338      {
339         set_int = 1;
340         mc68328->regs.rtcisr |= RTCINT_SECOND;
341      }
342
343      if((mc68328->regs.hmsr & 0x0000003f) == 0x0000003c)
344      {
345         mc68328->regs.hmsr &= 0xffffffc0;
346         mc68328->regs.hmsr += 0x00010000;
347
348         if(mc68328->regs.rtcienr & RTCINT_MINUTE)
349         {
350            set_int = 1;
351            mc68328->regs.rtcisr |= RTCINT_MINUTE;
352         }
353
354         if((mc68328->regs.hmsr & 0x003f0000) == 0x003c0000)
355         {
356            mc68328->regs.hmsr &= 0xffc0ffff;
357            mc68328->regs.hmsr += 0x0100000;
358
359            if((mc68328->regs.hmsr & 0x1f000000) == 0x18000000)
360            {
361               mc68328->regs.hmsr &= 0xe0ffffff;
362
363               if(mc68328->regs.rtcienr & RTCINT_DAY)
364               {
365                  set_int = 1;
366                  mc68328->regs.rtcisr |= RTCINT_DAY;
367               }
368            }
369         }
370
371         if(mc68328->regs.stpwtch != 0x003f)
372         {
373            mc68328->regs.stpwtch--;
374            mc68328->regs.stpwtch &= 0x003f;
375
376            if(mc68328->regs.stpwtch == 0x003f)
377            {
378               if(mc68328->regs.rtcienr & RTCINT_STOPWATCH)
379               {
380                  set_int = 1;
381                  mc68328->regs.rtcisr |= RTCINT_STOPWATCH;
382               }
383            }
384         }
385      }
386
387      if(mc68328->regs.hmsr == mc68328->regs.alarm)
388      {
389         if(mc68328->regs.rtcienr & RTCINT_ALARM)
390         {
391            set_int = 1;
392            mc68328->regs.rtcisr |= RTCINT_STOPWATCH;
393         }
394      }
395
396      if(set_int)
397      {
398         mc68328_set_interrupt_line(device, INT_RTC, 1);
399      }
400      else
401      {
402         mc68328_set_interrupt_line(device, INT_RTC, 0);
403      }
404   }
405}
406
407WRITE16_DEVICE_HANDLER( mc68328_w )
408{
409   mc68328_t* mc68328 = mc68328_get_safe_token( device );
410   UINT32 address = offset << 1;
411   UINT16 temp16[4] = { 0 };
412   UINT32 imr_old = mc68328->regs.imr, imr_diff;
413
414   switch(address)
415   {
416      case 0x000:
417         if( mem_mask & 0x00ff )
418         {
419            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff001) = %02x\n", data & 0x00ff);
420         }
421         else
422         {
423            verboselog(space.machine(), 2, "mc68328_w: SCR = %02x\n", (data >> 8) & 0x00ff);
424         }
425         break;
426
427      case 0x100:
428         verboselog(space.machine(), 2, "mc68328_w: GRPBASEA = %04x\n", data);
429         mc68328->regs.grpbasea = data;
430         break;
431
432      case 0x102:
433         verboselog(space.machine(), 2, "mc68328_w: GRPBASEB = %04x\n", data);
434         mc68328->regs.grpbaseb = data;
435         break;
436
437      case 0x104:
438         verboselog(space.machine(), 2, "mc68328_w: GRPBASEC = %04x\n", data);
439         mc68328->regs.grpbasec = data;
440         break;
441
442      case 0x106:
443         verboselog(space.machine(), 2, "mc68328_w: GRPBASED = %04x\n", data);
444         mc68328->regs.grpbased = data;
445         break;
446
447      case 0x108:
448         verboselog(space.machine(), 2, "mc68328_w: GRPMASKA = %04x\n", data);
449         mc68328->regs.grpmaska = data;
450         break;
451
452      case 0x10a:
453         verboselog(space.machine(), 2, "mc68328_w: GRPMASKB = %04x\n", data);
454         mc68328->regs.grpmaskb = data;
455         break;
456
457      case 0x10c:
458         verboselog(space.machine(), 2, "mc68328_w: GRPMASKC = %04x\n", data);
459         mc68328->regs.grpmaskc = data;
460         break;
461
462      case 0x10e:
463         verboselog(space.machine(), 2, "mc68328_w: GRPMASKD = %04x\n", data);
464         mc68328->regs.grpmaskd = data;
465         break;
466
467      case 0x110:
468         verboselog(space.machine(), 5, "mc68328_w: CSA0(0) = %04x\n", data);
469         mc68328->regs.csa0 &= 0xffff0000 | (~mem_mask);
470         mc68328->regs.csa0 |= data & mem_mask;
471         break;
472
473      case 0x112:
474         verboselog(space.machine(), 5, "mc68328_w: CSA0(16) = %04x\n", data);
475         mc68328->regs.csa0 &= ~(mem_mask << 16);
476         mc68328->regs.csa0 |= (data & mem_mask) << 16;
477         break;
478
479      case 0x114:
480         verboselog(space.machine(), 5, "mc68328_w: CSA1(0) = %04x\n", data);
481         mc68328->regs.csa1 &= 0xffff0000 | (~mem_mask);
482         mc68328->regs.csa1 |= data & mem_mask;
483         break;
484
485      case 0x116:
486         verboselog(space.machine(), 5, "mc68328_w: CSA1(16) = %04x\n", data);
487         mc68328->regs.csa1 &= ~(mem_mask << 16);
488         mc68328->regs.csa1 |= (data & mem_mask) << 16;
489         break;
490
491      case 0x118:
492         verboselog(space.machine(), 5, "mc68328_w: CSA2(0) = %04x\n", data);
493         mc68328->regs.csa2 &= 0xffff0000 | (~mem_mask);
494         mc68328->regs.csa2 |= data & mem_mask;
495         break;
496
497      case 0x11a:
498         verboselog(space.machine(), 5, "mc68328_w: CSA2(16) = %04x\n", data);
499         mc68328->regs.csa2 &= ~(mem_mask << 16);
500         mc68328->regs.csa2 |= (data & mem_mask) << 16;
501         break;
502
503      case 0x11c:
504         verboselog(space.machine(), 5, "mc68328_w: CSA3(0) = %04x\n", data);
505         mc68328->regs.csa3 &= 0xffff0000 | (~mem_mask);
506         mc68328->regs.csa3 |= data & mem_mask;
507         break;
508
509      case 0x11e:
510         verboselog(space.machine(), 5, "mc68328_w: CSA3(16) = %04x\n", data);
511         mc68328->regs.csa3 &= ~(mem_mask << 16);
512         mc68328->regs.csa3 |= (data & mem_mask) << 16;
513         break;
514
515      case 0x120:
516         verboselog(space.machine(), 5, "mc68328_w: CSB0(0) = %04x\n", data);
517         mc68328->regs.csb0 &= 0xffff0000 | (~mem_mask);
518         mc68328->regs.csb0 |= data & mem_mask;
519         break;
520
521      case 0x122:
522         verboselog(space.machine(), 5, "mc68328_w: CSB0(16) = %04x\n", data);
523         mc68328->regs.csb0 &= ~(mem_mask << 16);
524         mc68328->regs.csb0 |= (data & mem_mask) << 16;
525         break;
526
527      case 0x124:
528         verboselog(space.machine(), 5, "mc68328_w: CSB1(0) = %04x\n", data);
529         mc68328->regs.csb1 &= 0xffff0000 | (~mem_mask);
530         mc68328->regs.csb1 |= data & mem_mask;
531         break;
532
533      case 0x126:
534         verboselog(space.machine(), 5, "mc68328_w: CSB1(16) = %04x\n", data);
535         mc68328->regs.csb1 &= ~(mem_mask << 16);
536         mc68328->regs.csb1 |= (data & mem_mask) << 16;
537         break;
538
539      case 0x128:
540         verboselog(space.machine(), 5, "mc68328_w: CSB2(0) = %04x\n", data);
541         mc68328->regs.csb2 &= 0xffff0000 | (~mem_mask);
542         mc68328->regs.csb2 |= data & mem_mask;
543         break;
544
545      case 0x12a:
546         verboselog(space.machine(), 5, "mc68328_w: CSB2(16) = %04x\n", data);
547         mc68328->regs.csb2 &= ~(mem_mask << 16);
548         mc68328->regs.csb2 |= (data & mem_mask) << 16;
549         break;
550
551      case 0x12c:
552         verboselog(space.machine(), 5, "mc68328_w: CSB3(0) = %04x\n", data);
553         mc68328->regs.csb3 &= 0xffff0000 | (~mem_mask);
554         mc68328->regs.csb3 |= data & mem_mask;
555         break;
556
557      case 0x12e:
558         verboselog(space.machine(), 5, "mc68328_w: CSB3(16) = %04x\n", data);
559         mc68328->regs.csb3 &= ~(mem_mask << 16);
560         mc68328->regs.csb3 |= (data & mem_mask) << 16;
561         break;
562
563      case 0x130:
564         verboselog(space.machine(), 5, "mc68328_w: CSC0(0) = %04x\n", data);
565         mc68328->regs.csc0 &= 0xffff0000 | (~mem_mask);
566         mc68328->regs.csc0 |= data & mem_mask;
567         break;
568
569      case 0x132:
570         verboselog(space.machine(), 5, "mc68328_w: CSC0(16) = %04x\n", data);
571         mc68328->regs.csc0 &= ~(mem_mask << 16);
572         mc68328->regs.csc0 |= (data & mem_mask) << 16;
573         break;
574
575      case 0x134:
576         verboselog(space.machine(), 5, "mc68328_w: CSC1(0) = %04x\n", data);
577         mc68328->regs.csc1 &= 0xffff0000 | (~mem_mask);
578         mc68328->regs.csc1 |= data & mem_mask;
579         break;
580
581      case 0x136:
582         verboselog(space.machine(), 5, "mc68328_w: CSC1(16) = %04x\n", data);
583         mc68328->regs.csc1 &= ~(mem_mask << 16);
584         mc68328->regs.csc1 |= (data & mem_mask) << 16;
585         break;
586
587      case 0x138:
588         verboselog(space.machine(), 5, "mc68328_w: CSC2(0) = %04x\n", data);
589         mc68328->regs.csc2 &= 0xffff0000 | (~mem_mask);
590         mc68328->regs.csc2 |= data & mem_mask;
591         break;
592
593      case 0x13a:
594         verboselog(space.machine(), 5, "mc68328_w: CSC2(16) = %04x\n", data);
595         mc68328->regs.csc2 &= ~(mem_mask << 16);
596         mc68328->regs.csc2 |= (data & mem_mask) << 16;
597         break;
598
599      case 0x13c:
600         verboselog(space.machine(), 5, "mc68328_w: CSC3(0) = %04x\n", data);
601         mc68328->regs.csc3 &= 0xffff0000 | (~mem_mask);
602         mc68328->regs.csc3 |= data & mem_mask;
603         break;
604
605      case 0x13e:
606         verboselog(space.machine(), 5, "mc68328_w: CSC3(16) = %04x\n", data);
607         mc68328->regs.csc3 &= ~(mem_mask << 16);
608         mc68328->regs.csc3 |= (data & mem_mask) << 16;
609         break;
610
611      case 0x140:
612         verboselog(space.machine(), 5, "mc68328_w: CSD0(0) = %04x\n", data);
613         mc68328->regs.csd0 &= 0xffff0000 | (~mem_mask);
614         mc68328->regs.csd0 |= data & mem_mask;
615         break;
616
617      case 0x142:
618         verboselog(space.machine(), 5, "mc68328_w: CSD0(16) = %04x\n", data);
619         mc68328->regs.csd0 &= ~(mem_mask << 16);
620         mc68328->regs.csd0 |= (data & mem_mask) << 16;
621         break;
622
623      case 0x144:
624         verboselog(space.machine(), 5, "mc68328_w: CSD1(0) = %04x\n", data);
625         mc68328->regs.csd1 &= 0xffff0000 | (~mem_mask);
626         mc68328->regs.csd1 |= data & mem_mask;
627         break;
628
629      case 0x146:
630         verboselog(space.machine(), 5, "mc68328_w: CSD1(16) = %04x\n", data);
631         mc68328->regs.csd1 &= ~(mem_mask << 16);
632         mc68328->regs.csd1 |= (data & mem_mask) << 16;
633         break;
634
635      case 0x148:
636         verboselog(space.machine(), 5, "mc68328_w: CSD2(0) = %04x\n", data);
637         mc68328->regs.csd2 &= 0xffff0000 | (~mem_mask);
638         mc68328->regs.csd2 |= data & mem_mask;
639         break;
640
641      case 0x14a:
642         verboselog(space.machine(), 5, "mc68328_w: CSD2(16) = %04x\n", data);
643         mc68328->regs.csd2 &= ~(mem_mask << 16);
644         mc68328->regs.csd2 |= (data & mem_mask) << 16;
645         break;
646
647      case 0x14c:
648         verboselog(space.machine(), 5, "mc68328_w: CSD3(0) = %04x\n", data);
649         mc68328->regs.csd3 &= 0xffff0000 | (~mem_mask);
650         mc68328->regs.csd3 |= data & mem_mask;
651         break;
652
653      case 0x14e:
654         verboselog(space.machine(), 5, "mc68328_w: CSD3(16) = %04x\n", data);
655         mc68328->regs.csd3 &= ~(mem_mask << 16);
656         mc68328->regs.csd3 |= (data & mem_mask) << 16;
657         break;
658
659      case 0x200:
660         verboselog(space.machine(), 2, "mc68328_w: PLLCR = %04x\n", data);
661         mc68328->regs.pllcr = data;
662         break;
663
664      case 0x202:
665         verboselog(space.machine(), 2, "mc68328_w: PLLFSR = %04x\n", data);
666         mc68328->regs.pllfsr = data;
667         break;
668
669      case 0x206:
670         if( mem_mask & 0x00ff )
671         {
672            verboselog(space.machine(), 2, "mc68328_w: PCTLR = %02x\n", data & 0x00ff);
673            mc68328->regs.pctlr = data & 0x00ff;
674         }
675         else
676         {
677            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff206) = %02x\n", (data >> 8) & 0x00ff);
678         }
679         break;
680
681      case 0x300:
682         if( mem_mask & 0x00ff )
683         {
684            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff301) = %02x\n", data & 0x00ff);
685         }
686         else
687         {
688            verboselog(space.machine(), 2, "mc68328_w: IVR = %02x\n", (data >> 8) & 0x00ff);
689            mc68328->regs.ivr = (data >> 8) & 0x00ff;
690         }
691         break;
692
693      case 0x302:
694         verboselog(space.machine(), 2, "mc68328_w: ICR = %04x\n", data);
695         mc68328->regs.icr = data;
696         break;
697
698      case 0x304:
699         verboselog(space.machine(), 2, "mc68328_w: IMR(16) = %04x\n", data);
700         mc68328->regs.imr &= ~(mem_mask << 16);
701         mc68328->regs.imr |= (data & mem_mask) << 16;
702         mc68328->regs.isr &= ~((data & mem_mask) << 16);
703
704         imr_diff = imr_old ^ mc68328->regs.imr;
705         mc68328_set_interrupt_line(device, imr_diff, 0);
706         break;
707
708      case 0x306:
709         verboselog(space.machine(), 2, "mc68328_w: IMR(0) = %04x\n", data);
710         mc68328->regs.imr &= 0xffff0000 | (~mem_mask);
711         mc68328->regs.imr |= data & mem_mask;
712         mc68328->regs.isr &= ~(data & mem_mask);
713
714         imr_diff = imr_old ^ mc68328->regs.imr;
715         mc68328_set_interrupt_line(device, imr_diff, 0);
716         break;
717
718      case 0x308:
719      {
720         verboselog(space.machine(), 2, "mc68328_w: IWR(16) = %04x\n", data);
721         mc68328->regs.iwr &= ~(mem_mask << 16);
722         mc68328->regs.iwr |= (data & mem_mask) << 16;
723      }
724      break;
725
726      case 0x30a:
727         verboselog(space.machine(), 2, "mc68328_w: IWR(0) = %04x\n", data);
728         mc68328->regs.iwr &= 0xffff0000 | (~mem_mask);
729         mc68328->regs.iwr |= data & mem_mask;
730         break;
731
732      case 0x30c:
733         verboselog(space.machine(), 2, "mc68328_w: ISR(16) = %04x\n", data);
734         // Clear edge-triggered IRQ1
735         if((mc68328->regs.icr & ICR_ET1) == ICR_ET1 && (data & INT_IRQ1_SHIFT) == INT_IRQ1_SHIFT)
736         {
737            mc68328->regs.isr &= ~INT_IRQ1;
738         }
739
740         // Clear edge-triggered IRQ2
741         if((mc68328->regs.icr & ICR_ET2) == ICR_ET2 && (data & INT_IRQ2_SHIFT) == INT_IRQ2_SHIFT)
742         {
743            mc68328->regs.isr &= ~INT_IRQ2;
744         }
745
746         // Clear edge-triggered IRQ3
747         if((mc68328->regs.icr & ICR_ET3) == ICR_ET3 && (data & INT_IRQ3_SHIFT) == INT_IRQ3_SHIFT)
748         {
749            mc68328->regs.isr &= ~INT_IRQ3;
750         }
751
752         // Clear edge-triggered IRQ6
753         if((mc68328->regs.icr & ICR_ET6) == ICR_ET6 && (data & INT_IRQ6_SHIFT) == INT_IRQ6_SHIFT)
754         {
755            mc68328->regs.isr &= ~INT_IRQ6;
756         }
757
758         // Clear edge-triggered IRQ7
759         if((data & INT_IRQ7_SHIFT) == INT_IRQ7_SHIFT)
760         {
761            mc68328->regs.isr &= ~INT_IRQ7;
762         }
763         break;
764
765      case 0x30e:
766         verboselog(space.machine(), 2, "mc68328_w: ISR(0) = %04x (Ignored)\n", data);
767         break;
768
769      case 0x310:
770         verboselog(space.machine(), 2, "mc68328_w: IPR(16) = %04x (Ignored)\n");
771         break;
772
773      case 0x312:
774         verboselog(space.machine(), 2, "mc68328_w: IPR(0) = %04x (Ignored)\n");
775         break;
776
777      case 0x400:
778         if( mem_mask & 0x00ff )
779         {
780            verboselog(space.machine(), 2, "mc68328_w: PADATA = %02x\n", data & 0x00ff);
781            mc68328->regs.padata = data & 0x00ff;
782            if(!mc68328->out_port_a.isnull())
783            {
784               mc68328->out_port_a( 0, data & 0x00ff );
785            }
786         }
787         else
788         {
789            verboselog(space.machine(), 2, "mc68328_w: PADIR = %02x\n", (data >> 8) & 0x00ff);
790            mc68328->regs.padir = (data >> 8) & 0x00ff;
791         }
792         break;
793
794      case 0x402:
795         if( mem_mask & 0x00ff )
796         {
797            verboselog(space.machine(), 2, "mc68328_w: PASEL = %02x\n", data & 0x00ff);
798            mc68328->regs.pasel = data & 0x00ff;
799         }
800         else
801         {
802            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff402) = %02x\n", (data >> 8) & 0x00ff);
803         }
804         break;
805
806      case 0x408:
807         if( mem_mask & 0x00ff )
808         {
809            verboselog(space.machine(), 2, "mc68328_w: PBDATA = %02x\n", data & 0x00ff);
810            mc68328->regs.pbdata = data & 0x00ff;
811            if(!mc68328->out_port_b.isnull())
812            {
813               mc68328->out_port_b( 0, data & 0x00ff );
814            }
815         }
816         else
817         {
818            verboselog(space.machine(), 2, "mc68328_w: PBDIR = %02x\n", (data >> 8) & 0x00ff);
819            mc68328->regs.pbdir = (data >> 8) & 0x00ff;
820         }
821         break;
822
823      case 0x40a:
824         if( mem_mask & 0x00ff )
825         {
826            verboselog(space.machine(), 2, "mc68328_w: PBSEL = %02x\n", data & 0x00ff);
827            mc68328->regs.pbsel = data & 0x00ff;
828         }
829         else
830         {
831            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff40a) = %02x\n", (data >> 8) & 0x00ff);
832         }
833         break;
834
835      case 0x410:
836         if( mem_mask & 0x00ff )
837         {
838            verboselog(space.machine(), 2, "mc68328_w: PCDATA = %02x\n", data & 0x00ff);
839            mc68328->regs.pcdata = data & 0x00ff;
840            if(!mc68328->out_port_c.isnull())
841            {
842               mc68328->out_port_c( 0, data & 0x00ff );
843            }
844         }
845         else
846         {
847            verboselog(space.machine(), 2, "mc68328_w: PCDIR = %02x\n", (data >> 8) & 0x00ff);
848            mc68328->regs.pcdir = (data >> 8) & 0x00ff;
849         }
850         break;
851
852      case 0x412:
853         if( mem_mask & 0x00ff )
854         {
855            verboselog(space.machine(), 2, "mc68328_w: PCSEL = %02x\n", data & 0x00ff);
856            mc68328->regs.pcsel = data & 0x00ff;
857         }
858         else
859         {
860            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff412) = %02x\n", (data >> 8) & 0x00ff);
861         }
862         break;
863
864      case 0x418:
865         if( mem_mask & 0x00ff )
866         {
867            verboselog(space.machine(), 2, "mc68328_w: PDDATA = %02x\n", data & 0x00ff);
868
869            mc68328->regs.pddataedge &= ~(data & 0x00ff);
870            mc68328_poll_port_d_interrupts(device);
871         }
872         else
873         {
874            verboselog(space.machine(), 2, "mc68328_w: PDDIR = %02x\n", (data >> 8) & 0x00ff);
875            mc68328->regs.pddir = (data >> 8) & 0x00ff;
876         }
877         break;
878
879      case 0x41a:
880         if( mem_mask & 0x00ff )
881         {
882            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff41b) = %02x\n", data & 0x00ff);
883         }
884         else
885         {
886            verboselog(space.machine(), 2, "mc68328_w: PDPUEN = %02x\n", (data >> 8) & 0x00ff);
887            mc68328->regs.pdpuen = (data >> 8) & 0x00ff;
888         }
889         break;
890
891      case 0x41c:
892         if( mem_mask & 0x00ff )
893         {
894            verboselog(space.machine(), 2, "mc68328_w: PDIRQEN = %02x\n", data & 0x00ff);
895            mc68328->regs.pdirqen = data & 0x00ff;
896
897            mc68328_poll_port_d_interrupts(device);
898         }
899         else
900         {
901            verboselog(space.machine(), 2, "mc68328_w: PDPOL = %02x\n", (data >> 8) & 0x00ff);
902            mc68328->regs.pdpol = (data >> 8) & 0x00ff;
903         }
904         break;
905
906      case 0x41e:
907         if( mem_mask & 0x00ff )
908         {
909            verboselog(space.machine(), 2, "mc68328_w: PDIRQEDGE = %02x\n", data & 0x00ff);
910            mc68328->regs.pdirqedge = data & 0x00ff;
911         }
912         else
913         {
914            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff41e) = %02x\n", (data >> 8) & 0x00ff);
915         }
916         break;
917
918      case 0x420:
919         if( mem_mask & 0x00ff )
920         {
921            verboselog(space.machine(), 2, "mc68328_w: PEDATA = %02x\n", data & 0x00ff);
922            mc68328->regs.pedata = data & 0x00ff;
923            if(!mc68328->out_port_e.isnull())
924            {
925               mc68328->out_port_e( 0, data & 0x00ff );
926            }
927         }
928         else
929         {
930            verboselog(space.machine(), 2, "mc68328_w: PEDIR = %02x\n", (data >> 8) & 0x00ff);
931            mc68328->regs.pedir = (data >> 8) & 0x00ff;
932         }
933         break;
934
935      case 0x422:
936         if( mem_mask & 0x00ff )
937         {
938            verboselog(space.machine(), 2, "mc68328_w: PESEL = %02x\n", data & 0x00ff);
939            mc68328->regs.pesel = data & 0x00ff;
940         }
941         else
942         {
943            verboselog(space.machine(), 2, "mc68328_w: PEPUEN = %02x\n", (data >> 8) & 0x00ff);
944            mc68328->regs.pepuen = (data >> 8) & 0x00ff;
945            mc68328->regs.pedata |= mc68328->regs.pepuen;
946         }
947         break;
948
949      case 0x428:
950         if( mem_mask & 0x00ff )
951         {
952            verboselog(space.machine(), 2, "mc68328_w: PFDATA = %02x\n", data & 0x00ff);
953            mc68328->regs.pfdata = data & 0x00ff;
954            if(!mc68328->out_port_f.isnull())
955            {
956               mc68328->out_port_f( 0, data & 0x00ff );
957            }
958         }
959         else
960         {
961            verboselog(space.machine(), 2, "mc68328_w: PFDIR = %02x\n", (data >> 8) & 0x00ff);
962            mc68328->regs.pfdir = (data >> 8) & 0x00ff;
963         }
964         break;
965
966      case 0x42a:
967         if( mem_mask & 0x00ff )
968         {
969            verboselog(space.machine(), 2, "mc68328_w: PFSEL = %02x\n", data & 0x00ff);
970            mc68328->regs.pfsel = data & 0x00ff;
971         }
972         else
973         {
974            verboselog(space.machine(), 2, "mc68328_w: PFPUEN = %02x\n", (data >> 8) & 0x00ff);
975            mc68328->regs.pfpuen = (data >> 8) & 0x00ff;
976         }
977         break;
978
979      case 0x430:
980         if( mem_mask & 0x00ff )
981         {
982            verboselog(space.machine(), 2, "mc68328_w: PGDATA = %02x\n", data & 0x00ff);
983            mc68328->regs.pgdata = data & 0x00ff;
984            if(!mc68328->out_port_g.isnull())
985            {
986               mc68328->out_port_g( 0, data & 0x00ff );
987            }
988         }
989         else
990         {
991            verboselog(space.machine(), 2, "mc68328_w: PGDIR = %02x\n", (data >> 8) & 0x00ff);
992            mc68328->regs.pgdir = (data >> 8) & 0x00ff;
993         }
994         break;
995
996      case 0x432:
997         if( mem_mask & 0x00ff )
998         {
999            verboselog(space.machine(), 2, "mc68328_w: PGSEL = %02x\n", data & 0x00ff);
1000            mc68328->regs.pgsel = data & 0x00ff;
1001         }
1002         else
1003         {
1004            verboselog(space.machine(), 2, "mc68328_w: PGPUEN = %02x\n", (data >> 8) & 0x00ff);
1005            mc68328->regs.pgpuen = (data >> 8) & 0x00ff;
1006         }
1007         break;
1008
1009      case 0x438:
1010         if( mem_mask & 0x00ff )
1011         {
1012            verboselog(space.machine(), 2, "mc68328_w: PJDATA = %02x\n", data & 0x00ff);
1013            mc68328->regs.pjdata = data & 0x00ff;
1014            if(!mc68328->out_port_j.isnull())
1015            {
1016               mc68328->out_port_j( 0, data & 0x00ff );
1017            }
1018         }
1019         else
1020         {
1021            verboselog(space.machine(), 2, "mc68328_w: PJDIR = %02x\n", (data >> 8) & 0x00ff);
1022            mc68328->regs.pjdir = (data >> 8) & 0x00ff;
1023         }
1024         break;
1025
1026      case 0x43a:
1027         if( mem_mask & 0x00ff )
1028         {
1029            verboselog(space.machine(), 2, "mc68328_w: PJSEL = %02x\n", data & 0x00ff);
1030            mc68328->regs.pjsel = data & 0x00ff;
1031         }
1032         else
1033         {
1034            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff43a) = %02x\n", (data >> 8) & 0x00ff);
1035         }
1036         break;
1037
1038      case 0x440:
1039         if( mem_mask & 0x00ff )
1040         {
1041            verboselog(space.machine(), 2, "mc68328_w: PKDATA = %02x\n", data & 0x00ff);
1042            mc68328->regs.pkdata = data & 0x00ff;
1043            if(!mc68328->out_port_k.isnull())
1044            {
1045               mc68328->out_port_k( 0, data & 0x00ff );
1046            }
1047         }
1048         else
1049         {
1050            verboselog(space.machine(), 2, "mc68328_w: PKDIR = %02x\n", (data >> 8) & 0x00ff);
1051            mc68328->regs.pkdir = (data >> 8) & 0x00ff;
1052         }
1053         break;
1054
1055      case 0x442:
1056         if( mem_mask & 0x00ff )
1057         {
1058            verboselog(space.machine(), 2, "mc68328_w: PKSEL = %02x\n", data & 0x00ff);
1059            mc68328->regs.pksel = data & 0x00ff;
1060         }
1061         else
1062         {
1063            verboselog(space.machine(), 2, "mc68328_w: PKPUEN = %02x\n", (data >> 8) & 0x00ff);
1064            mc68328->regs.pgpuen = (data >> 8) & 0x00ff;
1065         }
1066         break;
1067
1068      case 0x448:
1069         if( mem_mask & 0x00ff )
1070         {
1071            verboselog(space.machine(), 2, "mc68328_w: PMDATA = %02x\n", data & 0x00ff);
1072            mc68328->regs.pmdata = data & 0x00ff;
1073            if(!mc68328->out_port_m.isnull())
1074            {
1075               mc68328->out_port_m( 0, data & 0x00ff );
1076            }
1077         }
1078         else
1079         {
1080            verboselog(space.machine(), 2, "mc68328_w: PMDIR = %02x\n", (data >> 8) & 0x00ff);
1081            mc68328->regs.pmdir = (data >> 8) & 0x00ff;
1082         }
1083         break;
1084
1085      case 0x44a:
1086         if( mem_mask & 0x00ff )
1087         {
1088            verboselog(space.machine(), 2, "mc68328_w: PMSEL = %02x\n", data & 0x00ff);
1089            mc68328->regs.pmsel = data & 0x00ff;
1090         }
1091         else
1092         {
1093            verboselog(space.machine(), 2, "mc68328_w: PMPUEN = %02x\n", (data >> 8) & 0x00ff);
1094            mc68328->regs.pmpuen = (data >> 8) & 0x00ff;
1095         }
1096         break;
1097
1098      case 0x500:
1099         verboselog(space.machine(), 2, "mc68328_w: PWMC = %04x\n", data);
1100
1101         mc68328->regs.pwmc = data;
1102
1103         if(mc68328->regs.pwmc & PWMC_PWMIRQ)
1104         {
1105            mc68328_set_interrupt_line(device, INT_PWM, 1);
1106         }
1107
1108         mc68328->regs.pwmc &= ~PWMC_LOAD;
1109
1110         if((mc68328->regs.pwmc & PWMC_PWMEN) != 0 && mc68328->regs.pwmw != 0 && mc68328->regs.pwmp != 0)
1111         {
1112            UINT32 frequency = 32768 * 506;
1113            UINT32 divisor = 4 << (mc68328->regs.pwmc & PWMC_CLKSEL); // ?? Datasheet says 2 <<, but then we're an octave higher than CoPilot.
1114            attotime period;
1115            frequency /= divisor;
1116            period = attotime::from_hz(frequency) * mc68328->regs.pwmw;
1117            mc68328->pwm->adjust(period);
1118            if(mc68328->regs.pwmc & PWMC_IRQEN)
1119            {
1120               mc68328_set_interrupt_line(device, INT_PWM, 1);
1121            }
1122            mc68328->regs.pwmc ^= PWMC_PIN;
1123         }
1124         else
1125         {
1126            mc68328->pwm->adjust(attotime::never);
1127         }
1128         break;
1129
1130      case 0x502:
1131         verboselog(space.machine(), 2, "mc68328_w: PWMP = %04x\n", data);
1132         mc68328->regs.pwmp = data;
1133         break;
1134
1135      case 0x504:
1136         verboselog(space.machine(), 2, "mc68328_w: PWMW = %04x\n", data);
1137         mc68328->regs.pwmw = data;
1138         break;
1139
1140      case 0x506:
1141         verboselog(space.machine(), 2, "mc68328_w: PWMCNT = %04x\n", data);
1142         mc68328->regs.pwmcnt = 0;
1143         break;
1144
1145      case 0x600:
1146         verboselog(space.machine(), 2, "mc68328_w: TCTL1 = %04x\n", data);
1147         temp16[0] = mc68328->regs.tctl[0];
1148         mc68328->regs.tctl[0] = data;
1149         if((temp16[0] & TCTL_TEN) == (mc68328->regs.tctl[0] & TCTL_TEN))
1150         {
1151            mc68328_maybe_start_timer(device, 0, 0);
1152         }
1153         else if((temp16[0] & TCTL_TEN) != TCTL_TEN_ENABLE && (mc68328->regs.tctl[0] & TCTL_TEN) == TCTL_TEN_ENABLE)
1154         {
1155            mc68328_maybe_start_timer(device, 0, 1);
1156         }
1157         break;
1158
1159      case 0x602:
1160         verboselog(space.machine(), 2, "mc68328_w: TPRER1 = %04x\n", data);
1161         mc68328->regs.tprer[0] = data;
1162         mc68328_maybe_start_timer(device, 0, 0);
1163         break;
1164
1165      case 0x604:
1166         verboselog(space.machine(), 2, "mc68328_w: TCMP1 = %04x\n", data);
1167         mc68328->regs.tcmp[0] = data;
1168         mc68328_maybe_start_timer(device, 0, 0);
1169         break;
1170
1171      case 0x606:
1172         verboselog(space.machine(), 2, "mc68328_w: TCR1 = %04x (Ignored)\n", data);
1173         break;
1174
1175      case 0x608:
1176         verboselog(space.machine(), 2, "mc68328_w: TCN1 = %04x (Ignored)\n", data);
1177         break;
1178
1179      case 0x60a:
1180         verboselog(space.machine(), 5, "mc68328_w: TSTAT1 = %04x\n", data);
1181         mc68328->regs.tstat[0] &= ~mc68328->regs.tclear[0];
1182         if(!(mc68328->regs.tstat[0] & TSTAT_COMP))
1183         {
1184            mc68328_set_interrupt_line(device, INT_TIMER1, 0);
1185         }
1186         break;
1187
1188      case 0x60c:
1189         verboselog(space.machine(), 2, "mc68328_w: TCTL2 = %04x\n", data);
1190         temp16[0] = mc68328->regs.tctl[1];
1191         mc68328->regs.tctl[1] = data;
1192         if((temp16[0] & TCTL_TEN) == (mc68328->regs.tctl[1] & TCTL_TEN))
1193         {
1194            mc68328_maybe_start_timer(device, 1, 0);
1195         }
1196         else if((temp16[0] & TCTL_TEN) != TCTL_TEN_ENABLE && (mc68328->regs.tctl[1] & TCTL_TEN) == TCTL_TEN_ENABLE)
1197         {
1198            mc68328_maybe_start_timer(device, 1, 1);
1199         }
1200         break;
1201
1202      case 0x60e:
1203         verboselog(space.machine(), 2, "mc68328_w: TPRER2 = %04x\n", data);
1204         mc68328->regs.tprer[1] = data;
1205         mc68328_maybe_start_timer(device, 1, 0);
1206         break;
1207
1208      case 0x610:
1209         verboselog(space.machine(), 2, "mc68328_w: TCMP2 = %04x\n", data);
1210         mc68328->regs.tcmp[1] = data;
1211         mc68328_maybe_start_timer(device, 1, 0);
1212         break;
1213
1214      case 0x612:
1215         verboselog(space.machine(), 2, "mc68328_w: TCR2 = %04x (Ignored)\n", data);
1216         break;
1217
1218      case 0x614:
1219         verboselog(space.machine(), 2, "mc68328_w: TCN2 = %04x (Ignored)\n", data);
1220         break;
1221
1222      case 0x616:
1223         verboselog(space.machine(), 2, "mc68328_w: TSTAT2 = %04x\n", data);
1224         mc68328->regs.tstat[1] &= ~mc68328->regs.tclear[1];
1225         if(!(mc68328->regs.tstat[1] & TSTAT_COMP))
1226         {
1227            mc68328_set_interrupt_line(device, INT_TIMER2, 0);
1228         }
1229         break;
1230
1231      case 0x618:
1232         verboselog(space.machine(), 2, "mc68328_w: WCTLR = %04x\n", data);
1233         mc68328->regs.wctlr = data;
1234         break;
1235
1236      case 0x61a:
1237         verboselog(space.machine(), 2, "mc68328_w: WCMPR = %04x\n", data);
1238         mc68328->regs.wcmpr = data;
1239         break;
1240
1241      case 0x61c:
1242         verboselog(space.machine(), 2, "mc68328_w: WCN = %04x (Ignored)\n", data);
1243         break;
1244
1245      case 0x700:
1246         verboselog(space.machine(), 2, "mc68328_w: SPISR = %04x\n", data);
1247         mc68328->regs.spisr = data;
1248         break;
1249
1250      case 0x800:
1251         verboselog(space.machine(), 2, "mc68328_w: SPIMDATA = %04x\n", data);
1252         if(!mc68328->out_spim.isnull())
1253         {
1254            mc68328->out_spim( 0, data, 0xffff );
1255         }
1256         else
1257         {
1258            mc68328->regs.spimdata = data;
1259         }
1260         break;
1261
1262      case 0x802:
1263         verboselog(space.machine(), 2, "mc68328_w: SPIMCONT = %04x\n", data);
1264         verboselog(space.machine(), 3, "           Count = %d\n", data & SPIM_CLOCK_COUNT);
1265         verboselog(space.machine(), 3, "           Polarity = %s\n", (data & SPIM_POL) ? "Inverted" : "Active-high");
1266         verboselog(space.machine(), 3, "           Phase = %s\n", (data & SPIM_PHA) ? "Opposite" : "Normal");
1267         verboselog(space.machine(), 3, "           IRQ Enable = %s\n", (data & SPIM_IRQEN) ? "Enable" : "Disable");
1268         verboselog(space.machine(), 3, "           IRQ Pending = %s\n", (data & SPIM_SPIMIRQ) ? "Yes" : "No");
1269         verboselog(space.machine(), 3, "           Exchange = %s\n", (data & SPIM_XCH) ? "Initiate" : "Idle");
1270         verboselog(space.machine(), 3, "           SPIM Enable = %s\n", (data & SPIM_SPMEN) ? "Enable" : "Disable");
1271         verboselog(space.machine(), 3, "           Data Rate = Divide By %d\n", 1 << ((((data & SPIM_RATE) >> 13) & 0x0007) + 2) );
1272         mc68328->regs.spimcont = data;
1273         // $$HACK$$ We should probably emulate the ADS7843 A/D device properly.
1274         if(data & SPIM_XCH)
1275         {
1276            mc68328->regs.spimcont &= ~SPIM_XCH;
1277            if(mc68328->iface->spim_xch_trigger)
1278            {
1279               (mc68328->iface->spim_xch_trigger)( device );
1280            }
1281            if(data & SPIM_IRQEN)
1282            {
1283               mc68328->regs.spimcont |= SPIM_SPIMIRQ;
1284               verboselog(space.machine(), 3, "Triggering SPIM Interrupt\n" );
1285               mc68328_set_interrupt_line(device, INT_SPIM, 1);
1286            }
1287         }
1288         if(!(data & SPIM_IRQEN))
1289         {
1290            mc68328_set_interrupt_line(device, INT_SPIM, 0);
1291         }
1292         break;
1293
1294      case 0x900:
1295         verboselog(space.machine(), 2, "mc68328_w: USTCNT = %04x\n", data);
1296         mc68328->regs.ustcnt = data;
1297         break;
1298
1299      case 0x902:
1300         verboselog(space.machine(), 2, "mc68328_w: UBAUD = %04x\n", data);
1301         mc68328->regs.ubaud = data;
1302         break;
1303
1304      case 0x904:
1305         verboselog(space.machine(), 2, "mc68328_w: URX = %04x\n", data);
1306         break;
1307
1308      case 0x906:
1309         verboselog(space.machine(), 2, "mc68328_w: UTX = %04x\n", data);
1310         break;
1311
1312      case 0x908:
1313         verboselog(space.machine(), 2, "mc68328_w: UMISC = %04x\n", data);
1314         mc68328->regs.umisc = data;
1315         break;
1316
1317      case 0xa00:
1318         verboselog(space.machine(), 2, "mc68328_w: LSSA(16) = %04x\n", data);
1319         mc68328->regs.lssa &= ~(mem_mask << 16);
1320         mc68328->regs.lssa |= (data & mem_mask) << 16;
1321         verboselog(space.machine(), 3, "              Address: %08x\n", mc68328->regs.lssa);
1322         break;
1323
1324      case 0xa02:
1325         verboselog(space.machine(), 2, "mc68328_w: LSSA(0) = %04x\n", data);
1326         mc68328->regs.lssa &= 0xffff0000 | (~mem_mask);
1327         mc68328->regs.lssa |= data & mem_mask;
1328         verboselog(space.machine(), 3, "              Address: %08x\n", mc68328->regs.lssa);
1329         break;
1330
1331      case 0xa04:
1332         if( mem_mask & 0x00ff )
1333         {
1334            verboselog(space.machine(), 2, "mc68328_w: LVPW = %02x\n", data & 0x00ff);
1335            mc68328->regs.lvpw = data & 0x00ff;
1336            verboselog(space.machine(), 3, "              Page Width: %d or %d\n", (mc68328->regs.lvpw + 1) * ((mc68328->regs.lpicf & 0x01) ? 8 : 16));
1337         }
1338         else
1339         {
1340            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa04) = %02x\n", (data >> 8) & 0x00ff);
1341         }
1342         break;
1343
1344      case 0xa08:
1345         verboselog(space.machine(), 2, "mc68328_w: LXMAX = %04x\n", data);
1346         mc68328->regs.lxmax = data;
1347         verboselog(space.machine(), 3, "              Width: %d\n", (data & 0x03ff) + 1);
1348         break;
1349
1350      case 0xa0a:
1351         verboselog(space.machine(), 2, "mc68328_w: LYMAX = %04x\n", data);
1352         mc68328->regs.lymax = data;
1353         verboselog(space.machine(), 3, "              Height: %d\n", (data & 0x03ff) + 1);
1354         break;
1355
1356      case 0xa18:
1357         verboselog(space.machine(), 2, "mc68328_w: LCXP = %04x\n", data);
1358         mc68328->regs.lcxp = data;
1359         verboselog(space.machine(), 3, "              X Position: %d\n", data & 0x03ff);
1360         switch(mc68328->regs.lcxp >> 14)
1361         {
1362            case 0:
1363               verboselog(space.machine(), 3, "              Cursor Control: Transparent\n");
1364               break;
1365
1366            case 1:
1367               verboselog(space.machine(), 3, "              Cursor Control: Black\n");
1368               break;
1369
1370            case 2:
1371               verboselog(space.machine(), 3, "              Cursor Control: Reverse\n");
1372               break;
1373
1374            case 3:
1375               verboselog(space.machine(), 3, "              Cursor Control: Invalid\n");
1376               break;
1377         }
1378         break;
1379
1380      case 0xa1a:
1381         verboselog(space.machine(), 2, "mc68328_w: LCYP = %04x\n", data);
1382         mc68328->regs.lcyp = data;
1383         verboselog(space.machine(), 3, "              Y Position: %d\n", data & 0x01ff);
1384         break;
1385
1386      case 0xa1c:
1387         verboselog(space.machine(), 2, "mc68328_w: LCWCH = %04x\n", data);
1388         mc68328->regs.lcwch = data;
1389         verboselog(space.machine(), 3, "              Width:  %d\n", (data >> 8) & 0x1f);
1390         verboselog(space.machine(), 3, "              Height: %d\n", data & 0x1f);
1391         break;
1392
1393      case 0xa1e:
1394         if( mem_mask & 0x00ff )
1395         {
1396            verboselog(space.machine(), 2, "mc68328_w: LBLKC = %02x\n", data & 0x00ff);
1397            mc68328->regs.lblkc = data & 0x00ff;
1398            verboselog(space.machine(), 3, "              Blink Enable:  %d\n", mc68328->regs.lblkc >> 7);
1399            verboselog(space.machine(), 3, "              Blink Divisor: %d\n", mc68328->regs.lblkc & 0x7f);
1400         }
1401         else
1402         {
1403            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa1e) = %02x\n", (data >> 8) & 0x00ff);
1404         }
1405         break;
1406
1407      case 0xa20:
1408         if( mem_mask & 0x00ff )
1409         {
1410            verboselog(space.machine(), 2, "mc68328_w: LPOLCF = %02x\n", data & 0x00ff);
1411            mc68328->regs.lpolcf = data & 0x00ff;
1412            verboselog(space.machine(), 3, "              LCD Shift Clock Polarity: %s\n", (mc68328->regs.lpicf & 0x08) ? "Active positive edge of LCLK" : "Active negative edge of LCLK");
1413            verboselog(space.machine(), 3, "              First-line marker polarity: %s\n", (mc68328->regs.lpicf & 0x04) ? "Active Low" : "Active High");
1414            verboselog(space.machine(), 3, "              Line-pulse polarity: %s\n", (mc68328->regs.lpicf & 0x02) ? "Active Low" : "Active High");
1415            verboselog(space.machine(), 3, "              Pixel polarity: %s\n", (mc68328->regs.lpicf & 0x01) ? "Active Low" : "Active High");
1416         }
1417         else
1418         {
1419            verboselog(space.machine(), 2, "mc68328_w: LPICF = %02x\n", (data >> 8) & 0x00ff);
1420            mc68328->regs.lpicf = (data >> 8) & 0x00ff;
1421            switch((mc68328->regs.lpicf >> 1) & 0x03)
1422            {
1423               case 0:
1424                  verboselog(space.machine(), 3, "              Bus Size: 1-bit\n");
1425                  break;
1426
1427               case 1:
1428                  verboselog(space.machine(), 3, "              Bus Size: 2-bit\n");
1429                  break;
1430
1431               case 2:
1432                  verboselog(space.machine(), 3, "              Bus Size: 4-bit\n");
1433                  break;
1434
1435               case 3:
1436                  verboselog(space.machine(), 3, "              Bus Size: unused\n");
1437                  break;
1438            }
1439            verboselog(space.machine(), 3, "              Gray scale enable: %d\n", mc68328->regs.lpicf & 0x01);
1440         }
1441         break;
1442
1443      case 0xa22:
1444         if( mem_mask & 0x00ff )
1445         {
1446            verboselog(space.machine(), 2, "mc68328_w: LACDRC = %02x\n", data & 0x00ff);
1447            mc68328->regs.lacdrc = data & 0x00ff;
1448         }
1449         else
1450         {
1451            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa22) = %02x\n", (data >> 8) & 0x00ff);
1452         }
1453         break;
1454
1455      case 0xa24:
1456         if( mem_mask & 0x00ff )
1457         {
1458            verboselog(space.machine(), 2, "mc68328_w: LPXCD = %02x\n", data & 0x00ff);
1459            mc68328->regs.lpxcd = data & 0x00ff;
1460            verboselog(space.machine(), 3, "              Clock Divisor: %d\n", mc68328->regs.lpxcd + 1);
1461         }
1462         else
1463         {
1464            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa24) = %02x\n", (data >> 8) & 0x00ff);
1465         }
1466         break;
1467
1468      case 0xa26:
1469         if( mem_mask & 0x00ff )
1470         {
1471            verboselog(space.machine(), 2, "mc68328_w: LCKCON = %02x\n", data & 0x00ff);
1472            mc68328->regs.lckcon = data & 0x00ff;
1473            verboselog(space.machine(), 3, "              LCDC Enable: %d\n", (mc68328->regs.lckcon >> 7) & 0x01);
1474            verboselog(space.machine(), 3, "              DMA Burst Length: %d\n", ((mc68328->regs.lckcon >> 6) & 0x01) ? 16 : 8);
1475            verboselog(space.machine(), 3, "              DMA Bursting Clock Control: %d\n", ((mc68328->regs.lckcon >> 4) & 0x03) + 1);
1476            verboselog(space.machine(), 3, "              Bus Width: %d\n", ((mc68328->regs.lckcon >> 1) & 0x01) ? 8 : 16);
1477            verboselog(space.machine(), 3, "              Pixel Clock Divider Source: %s\n", (mc68328->regs.lckcon & 0x01) ? "PIX" : "SYS");
1478         }
1479         else
1480         {
1481            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa26) = %02x\n", (data >> 8) & 0x00ff);
1482         }
1483         break;
1484
1485      case 0xa28:
1486         if( mem_mask & 0x00ff )
1487         {
1488            verboselog(space.machine(), 2, "mc68328_w: LLBAR = %02x\n", data & 0x00ff);
1489            mc68328->regs.llbar = data & 0x00ff;
1490            verboselog(space.machine(), 3, "              Address: %d\n", (mc68328->regs.llbar & 0x7f) * ((mc68328->regs.lpicf & 0x01) ? 8 : 16));
1491         }
1492         else
1493         {
1494            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa28) = %02x\n", (data >> 8) & 0x00ff);
1495         }
1496         break;
1497
1498      case 0xa2a:
1499         if( mem_mask & 0x00ff )
1500         {
1501            verboselog(space.machine(), 2, "mc68328_w: LOTCR = %02x\n", data & 0x00ff);
1502         }
1503         else
1504         {
1505            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa2a) = %02x\n", (data >> 8) & 0x00ff);
1506         }
1507         break;
1508
1509      case 0xa2c:
1510         if( mem_mask & 0x00ff )
1511         {
1512            verboselog(space.machine(), 2, "mc68328_w: LPOSR = %02x\n", data & 0x00ff);
1513            mc68328->regs.lposr = data & 0x00ff;
1514            verboselog(space.machine(), 3, "              Byte Offset: %d\n", (mc68328->regs.lposr >> 3) & 0x01);
1515            verboselog(space.machine(), 3, "              Pixel Offset: %d\n", mc68328->regs.lposr & 0x07);
1516         }
1517         else
1518         {
1519            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa2c) = %02x\n", (data >> 8) & 0x00ff);
1520         }
1521         break;
1522
1523      case 0xa30:
1524         if( mem_mask & 0x00ff )
1525         {
1526            verboselog(space.machine(), 2, "mc68328_w: LFRCM = %02x\n", data & 0x00ff);
1527            mc68328->regs.lfrcm = data & 0x00ff;
1528            verboselog(space.machine(), 3, "              X Modulation: %d\n", (mc68328->regs.lfrcm >> 4) & 0x0f);
1529            verboselog(space.machine(), 3, "              Y Modulation: %d\n", mc68328->regs.lfrcm & 0x0f);
1530         }
1531         else
1532         {
1533            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa30) = %02x\n", (data >> 8) & 0x00ff);
1534         }
1535         break;
1536
1537      case 0xa32:
1538         verboselog(space.machine(), 2, "mc68328_w: LGPMR = %04x\n", data);
1539         mc68328->regs.lgpmr = data;
1540         verboselog(space.machine(), 3, "              Palette 0: %d\n", (mc68328->regs.lgpmr >>  8) & 0x07);
1541         verboselog(space.machine(), 3, "              Palette 1: %d\n", (mc68328->regs.lgpmr >> 12) & 0x07);
1542         verboselog(space.machine(), 3, "              Palette 2: %d\n", (mc68328->regs.lgpmr >>  0) & 0x07);
1543         verboselog(space.machine(), 3, "              Palette 3: %d\n", (mc68328->regs.lgpmr >>  4) & 0x07);
1544         break;
1545
1546      case 0xb00:
1547         verboselog(space.machine(), 2, "mc68328_w: HMSR(0) = %04x\n", data);
1548         mc68328->regs.hmsr &= ~(mem_mask << 16);
1549         mc68328->regs.hmsr |= (data & mem_mask) << 16;
1550         mc68328->regs.hmsr &= 0x1f3f003f;
1551         break;
1552
1553      case 0xb02:
1554         verboselog(space.machine(), 2, "mc68328_w: HMSR(16) = %04x\n", data);
1555         mc68328->regs.hmsr &= 0xffff0000 | (~mem_mask);
1556         mc68328->regs.hmsr |= data & mem_mask;
1557         mc68328->regs.hmsr &= 0x1f3f003f;
1558         break;
1559
1560      case 0xb04:
1561         verboselog(space.machine(), 2, "mc68328_w: ALARM(0) = %04x\n", data);
1562         mc68328->regs.alarm &= ~(mem_mask << 16);
1563         mc68328->regs.alarm |= (data & mem_mask) << 16;
1564         mc68328->regs.alarm &= 0x1f3f003f;
1565         break;
1566
1567      case 0xb06:
1568         verboselog(space.machine(), 2, "mc68328_w: ALARM(16) = %04x\n", data);
1569         mc68328->regs.alarm &= 0xffff0000 | (~mem_mask);
1570         mc68328->regs.alarm |= data & mem_mask;
1571         mc68328->regs.alarm &= 0x1f3f003f;
1572         break;
1573
1574      case 0xb0c:
1575         verboselog(space.machine(), 2, "mc68328_w: RTCCTL = %04x\n", data);
1576         mc68328->regs.rtcctl = data & 0x00a0;
1577         break;
1578
1579      case 0xb0e:
1580         verboselog(space.machine(), 2, "mc68328_w: RTCISR = %04x\n", data);
1581         mc68328->regs.rtcisr &= ~data;
1582         if(mc68328->regs.rtcisr == 0)
1583         {
1584            mc68328_set_interrupt_line(device, INT_RTC, 0);
1585         }
1586         break;
1587
1588      case 0xb10:
1589         verboselog(space.machine(), 2, "mc68328_w: RTCIENR = %04x\n", data);
1590         mc68328->regs.rtcienr = data & 0x001f;
1591         break;
1592
1593      case 0xb12:
1594         verboselog(space.machine(), 2, "mc68328_w: STPWTCH = %04x\n", data);
1595         mc68328->regs.stpwtch = data & 0x003f;
1596         break;
1597
1598      default:
1599         verboselog(space.machine(), 0, "mc68328_w: Unknown address (0x%06x) = %04x (%04x)\n", 0xfff000 + address, data, mem_mask);
1600         break;
1601   }
1602}
1603
1604READ16_DEVICE_HANDLER( mc68328_r )
1605{
1606   mc68328_t* mc68328 = mc68328_get_safe_token( device );
1607   UINT16 temp16 = 0;
1608   UINT32 address = offset << 1;
1609
1610   switch(address)
1611   {
1612      case 0x000:
1613         if( mem_mask & 0x00ff )
1614         {
1615            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff001)\n", mem_mask);
1616         }
1617         else
1618         {
1619            verboselog(space.machine(), 2, "mc68328_r (%04x): SCR = %02x\n", mem_mask, mc68328->regs.scr);
1620            return mc68328->regs.scr << 8;
1621         }
1622         break;
1623
1624      case 0x100:
1625         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPBASEA = %04x\n", mem_mask, mc68328->regs.grpbasea);
1626         return mc68328->regs.grpbasea;
1627
1628      case 0x102:
1629         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPBASEB = %04x\n", mem_mask, mc68328->regs.grpbaseb);
1630         return mc68328->regs.grpbaseb;
1631
1632      case 0x104:
1633         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPBASEC = %04x\n", mem_mask, mc68328->regs.grpbasec);
1634         return mc68328->regs.grpbasec;
1635
1636      case 0x106:
1637         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPBASED = %04x\n", mem_mask, mc68328->regs.grpbased);
1638         return mc68328->regs.grpbased;
1639
1640      case 0x108:
1641         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPMASKA = %04x\n", mem_mask, mc68328->regs.grpmaska);
1642         return mc68328->regs.grpmaska;
1643
1644      case 0x10a:
1645         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPMASKB = %04x\n", mem_mask, mc68328->regs.grpmaskb);
1646         return mc68328->regs.grpmaskb;
1647
1648      case 0x10c:
1649         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPMASKC = %04x\n", mem_mask, mc68328->regs.grpmaskc);
1650         return mc68328->regs.grpmaskc;
1651
1652      case 0x10e:
1653         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPMASKD = %04x\n", mem_mask, mc68328->regs.grpmaskd);
1654         return mc68328->regs.grpmaskd;
1655
1656      case 0x110:
1657         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA0(0) = %04x\n", mem_mask, mc68328->regs.csa0 & 0x0000ffff);
1658         return mc68328->regs.csa0 & 0x0000ffff;
1659
1660      case 0x112:
1661         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA0(16) = %04x\n", mem_mask, mc68328->regs.csa0 >> 16);
1662         return mc68328->regs.csa0 >> 16;
1663
1664      case 0x114:
1665         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA1(0) = %04x\n", mem_mask, mc68328->regs.csa1 & 0x0000ffff);
1666         return mc68328->regs.csa1 & 0x0000ffff;
1667
1668      case 0x116:
1669         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA1(16) = %04x\n", mem_mask, mc68328->regs.csa1 >> 16);
1670         return mc68328->regs.csa1 >> 16;
1671
1672      case 0x118:
1673         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA2(0) = %04x\n", mem_mask, mc68328->regs.csa2 & 0x0000ffff);
1674         return mc68328->regs.csa2 & 0x0000ffff;
1675
1676      case 0x11a:
1677         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA2(16) = %04x\n", mem_mask, mc68328->regs.csa2 >> 16);
1678         return mc68328->regs.csa2 >> 16;
1679
1680      case 0x11c:
1681         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA3(0) = %04x\n", mem_mask, mc68328->regs.csa3 & 0x0000ffff);
1682         return mc68328->regs.csa3 & 0x0000ffff;
1683
1684      case 0x11e:
1685         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA3(16) = %04x\n", mem_mask, mc68328->regs.csa3 >> 16);
1686         return mc68328->regs.csa3 >> 16;
1687
1688      case 0x120:
1689         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB0(0) = %04x\n", mem_mask, mc68328->regs.csb0 & 0x0000ffff);
1690         return mc68328->regs.csb0 & 0x0000ffff;
1691
1692      case 0x122:
1693         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB0(16) = %04x\n", mem_mask, mc68328->regs.csb0 >> 16);
1694         return mc68328->regs.csb0 >> 16;
1695
1696      case 0x124:
1697         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB1(0) = %04x\n", mem_mask, mc68328->regs.csb1 & 0x0000ffff);
1698         return mc68328->regs.csb1 & 0x0000ffff;
1699
1700      case 0x126:
1701         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB1(16) = %04x\n", mem_mask, mc68328->regs.csb1 >> 16);
1702         return mc68328->regs.csb1 >> 16;
1703
1704      case 0x128:
1705         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB2(0) = %04x\n", mem_mask, mc68328->regs.csb2 & 0x0000ffff);
1706         return mc68328->regs.csb2 & 0x0000ffff;
1707
1708      case 0x12a:
1709         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB2(16) = %04x\n", mem_mask, mc68328->regs.csb2 >> 16);
1710         return mc68328->regs.csb2 >> 16;
1711
1712      case 0x12c:
1713         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB3(0) = %04x\n", mem_mask, mc68328->regs.csb3 & 0x0000ffff);
1714         return mc68328->regs.csb3 & 0x0000ffff;
1715
1716      case 0x12e:
1717         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB3(16) = %04x\n", mem_mask, mc68328->regs.csb3 >> 16);
1718         return mc68328->regs.csb3 >> 16;
1719
1720      case 0x130:
1721         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC0(0) = %04x\n", mem_mask, mc68328->regs.csc0 & 0x0000ffff);
1722         return mc68328->regs.csc0 & 0x0000ffff;
1723
1724      case 0x132:
1725         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC0(16) = %04x\n", mem_mask, mc68328->regs.csc0 >> 16);
1726         return mc68328->regs.csc0 >> 16;
1727
1728      case 0x134:
1729         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC1(0) = %04x\n", mem_mask, mc68328->regs.csc1 & 0x0000ffff);
1730         return mc68328->regs.csc1 & 0x0000ffff;
1731
1732      case 0x136:
1733         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC1(16) = %04x\n", mem_mask, mc68328->regs.csc1 >> 16);
1734         return mc68328->regs.csc1 >> 16;
1735
1736      case 0x138:
1737         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC2(0) = %04x\n", mem_mask, mc68328->regs.csc2 & 0x0000ffff);
1738         return mc68328->regs.csc2 & 0x0000ffff;
1739
1740      case 0x13a:
1741         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC2(16) = %04x\n", mem_mask, mc68328->regs.csc2 >> 16);
1742         return mc68328->regs.csc2 >> 16;
1743
1744      case 0x13c:
1745         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC3(0) = %04x\n", mem_mask, mc68328->regs.csc3 & 0x0000ffff);
1746         return mc68328->regs.csc3 & 0x0000ffff;
1747
1748      case 0x13e:
1749         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC3(16) = %04x\n", mem_mask, mc68328->regs.csc3 >> 16);
1750         return mc68328->regs.csc3 >> 16;
1751
1752      case 0x140:
1753         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD0(0) = %04x\n", mem_mask, mc68328->regs.csd0 & 0x0000ffff);
1754         return mc68328->regs.csd0 & 0x0000ffff;
1755
1756      case 0x142:
1757         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD0(16) = %04x\n", mem_mask, mc68328->regs.csd0 >> 16);
1758         return mc68328->regs.csd0 >> 16;
1759
1760      case 0x144:
1761         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD1(0) = %04x\n", mem_mask, mc68328->regs.csd1 & 0x0000ffff);
1762         return mc68328->regs.csd1 & 0x0000ffff;
1763
1764      case 0x146:
1765         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD1(16) = %04x\n", mem_mask, mc68328->regs.csd1 >> 16);
1766         return mc68328->regs.csd1 >> 16;
1767
1768      case 0x148:
1769         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD2(0) = %04x\n", mem_mask, mc68328->regs.csd2 & 0x0000ffff);
1770         return mc68328->regs.csd2 & 0x0000ffff;
1771
1772      case 0x14a:
1773         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD2(16) = %04x\n", mem_mask, mc68328->regs.csd2 >> 16);
1774         return mc68328->regs.csd2 >> 16;
1775
1776      case 0x14c:
1777         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD3(0) = %04x\n", mem_mask, mc68328->regs.csd3 & 0x0000ffff);
1778         return mc68328->regs.csd3 & 0x0000ffff;
1779
1780      case 0x14e:
1781         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD3(16) = %04x\n", mem_mask, mc68328->regs.csd3 >> 16);
1782         return mc68328->regs.csd3 >> 16;
1783
1784      case 0x200:
1785         verboselog(space.machine(), 2, "mc68328_r (%04x): PLLCR = %04x\n", mem_mask, mc68328->regs.pllcr);
1786         return mc68328->regs.pllcr;
1787
1788      case 0x202:
1789         verboselog(space.machine(), 2, "mc68328_r (%04x): PLLFSR = %04x\n", mem_mask, mc68328->regs.pllfsr);
1790         mc68328->regs.pllfsr ^= 0x8000;
1791         return mc68328->regs.pllfsr;
1792
1793      case 0x206:
1794         if( mem_mask & 0x00ff )
1795         {
1796            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff206)\n", mem_mask);
1797         }
1798         else
1799         {
1800            verboselog(space.machine(), 2, "mc68328_r (%04x): PCTLR = %02x\n", mem_mask, mc68328->regs.pctlr);
1801            return mc68328->regs.pctlr << 8;
1802         }
1803         break;
1804
1805      case 0x300:
1806         if( mem_mask & 0x00ff )
1807         {
1808            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff301)\n", mem_mask);
1809         }
1810         else
1811         {
1812            verboselog(space.machine(), 2, "mc68328_r (%04x): IVR = %02x\n", mem_mask, mc68328->regs.ivr);
1813            return mc68328->regs.ivr << 8;
1814         }
1815         break;
1816
1817      case 0x302:
1818         verboselog(space.machine(), 2, "mc68328_r (%04x): ICR = %04x\n", mem_mask, mc68328->regs.icr);
1819         return mc68328->regs.icr;
1820
1821      case 0x304:
1822         verboselog(space.machine(), 2, "mc68328_r (%04x): IMR(16) = %04x\n", mem_mask, mc68328->regs.imr >> 16);
1823         return mc68328->regs.imr >> 16;
1824
1825      case 0x306:
1826         verboselog(space.machine(), 2, "mc68328_r (%04x): IMR(0) = %04x\n", mem_mask, mc68328->regs.imr & 0x0000ffff);
1827         return mc68328->regs.imr & 0x0000ffff;
1828
1829      case 0x308:
1830         verboselog(space.machine(), 2, "mc68328_r (%04x): IWR(16) = %04x\n", mem_mask, mc68328->regs.iwr >> 16);
1831         return mc68328->regs.iwr >> 16;
1832
1833      case 0x30a:
1834         verboselog(space.machine(), 2, "mc68328_r (%04x): IWR(0) = %04x\n", mem_mask, mc68328->regs.iwr & 0x0000ffff);
1835         return mc68328->regs.iwr & 0x0000ffff;
1836
1837      case 0x30c:
1838         verboselog(space.machine(), 2, "mc68328_r (%04x): ISR(16) = %04x\n", mem_mask, mc68328->regs.isr >> 16);
1839         return mc68328->regs.isr >> 16;
1840
1841      case 0x30e:
1842         verboselog(space.machine(), 2, "mc68328_r (%04x): ISR(0) = %04x\n", mem_mask, mc68328->regs.isr & 0x0000ffff);
1843         return mc68328->regs.isr & 0x0000ffff;
1844
1845      case 0x310:
1846         verboselog(space.machine(), 2, "mc68328_r (%04x): IPR(16) = %04x\n", mem_mask, mc68328->regs.ipr >> 16);
1847         return mc68328->regs.ipr >> 16;
1848
1849      case 0x312:
1850         verboselog(space.machine(), 2, "mc68328_r (%04x): IPR(0) = %04x\n", mem_mask, mc68328->regs.ipr & 0x0000ffff);
1851         return mc68328->regs.ipr & 0x0000ffff;
1852
1853      case 0x400:
1854         if( mem_mask & 0x00ff )
1855         {
1856            verboselog(space.machine(), 2, "mc68328_r (%04x): PADATA = %02x\n", mem_mask, mc68328->regs.padata);
1857            if(!mc68328->in_port_a.isnull())
1858            {
1859               return mc68328->in_port_a( 0 );
1860            }
1861            else
1862            {
1863               return mc68328->regs.padata;
1864            }
1865         }
1866         else
1867         {
1868            verboselog(space.machine(), 2, "mc68328_r (%04x): PADIR = %02x\n", mem_mask, mc68328->regs.padir);
1869            return mc68328->regs.padir << 8;
1870         }
1871         break;
1872
1873      case 0x402:
1874         if( mem_mask & 0x00ff )
1875         {
1876            verboselog(space.machine(), 2, "mc68328_r (%04x): PASEL = %02x\n", mem_mask, mc68328->regs.pasel);
1877            return mc68328->regs.pasel;
1878         }
1879         else
1880         {
1881            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff402)\n", mem_mask);
1882         }
1883         break;
1884
1885      case 0x408:
1886         if( mem_mask & 0x00ff )
1887         {
1888            verboselog(space.machine(), 2, "mc68328_r (%04x): PBDATA = %02x\n", mem_mask, mc68328->regs.pbdata);
1889            if(!mc68328->in_port_b.isnull())
1890            {
1891               return mc68328->in_port_b( 0 );
1892            }
1893            else
1894            {
1895               return mc68328->regs.pbdata;
1896            }
1897         }
1898         else
1899         {
1900            verboselog(space.machine(), 2, "mc68328_r (%04x): PBDIR = %02x\n", mem_mask, mc68328->regs.pbdir);
1901            return mc68328->regs.pbdir << 8;
1902         }
1903         break;
1904
1905      case 0x40a:
1906         if( mem_mask & 0x00ff )
1907         {
1908            verboselog(space.machine(), 2, "mc68328_r (%04x): PBSEL = %02x\n", mem_mask, mc68328->regs.pbsel);
1909            return mc68328->regs.pbsel;
1910         }
1911         else
1912         {
1913            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff40a)\n", mem_mask);
1914         }
1915         break;
1916
1917      case 0x410:
1918         if( mem_mask & 0x00ff )
1919         {
1920            verboselog(space.machine(), 2, "mc68328_r (%04x): PCDATA = %02x\n", mem_mask, mc68328->regs.pcdata);
1921            if(!mc68328->in_port_c.isnull())
1922            {
1923               return mc68328->in_port_c( 0 );
1924            }
1925            else
1926            {
1927               return mc68328->regs.pcdata;
1928            }
1929         }
1930         else
1931         {
1932            verboselog(space.machine(), 2, "mc68328_r (%04x): PCDIR = %02x\n", mem_mask, mc68328->regs.pcdir);
1933            return mc68328->regs.pcdir << 8;
1934         }
1935         break;
1936
1937      case 0x412:
1938         if( mem_mask & 0x00ff )
1939         {
1940            verboselog(space.machine(), 2, "mc68328_r (%04x): PCSEL = %02x\n", mem_mask, mc68328->regs.pcsel);
1941            return mc68328->regs.pcsel;
1942         }
1943         else
1944         {
1945            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff412)\n", mem_mask);
1946         }
1947         break;
1948
1949      case 0x418:
1950         if( mem_mask & 0x00ff )
1951         {
1952            verboselog(space.machine(), 2, "mc68328_r (%04x): PDDATA = %02x\n", mem_mask, mc68328->regs.pddata);
1953            if(!mc68328->in_port_d.isnull())
1954            {
1955               return mc68328->in_port_d( 0 );
1956            }
1957            else
1958            {
1959               return mc68328->regs.pddata;
1960            }
1961         }
1962         else
1963         {
1964            verboselog(space.machine(), 2, "mc68328_r (%04x): PDDIR = %02x\n", mem_mask, mc68328->regs.pddir);
1965            return mc68328->regs.pddir << 8;
1966         }
1967         break;
1968
1969      case 0x41a:
1970         if( mem_mask & 0x00ff )
1971         {
1972            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff41b)\n", mem_mask);
1973         }
1974         else
1975         {
1976            verboselog(space.machine(), 2, "mc68328_r (%04x): PDPUEN = %02x\n", mem_mask, mc68328->regs.pdpuen);
1977            return mc68328->regs.pdpuen << 8;
1978         }
1979         break;
1980
1981      case 0x41c:
1982         if( mem_mask & 0x00ff )
1983         {
1984            verboselog(space.machine(), 2, "mc68328_r (%04x): PDIRQEN = %02x\n", mem_mask, mc68328->regs.pdirqen);
1985            return mc68328->regs.pdirqen;
1986         }
1987         else
1988         {
1989            verboselog(space.machine(), 2, "mc68328_r (%04x): PDPOL = %02x\n", mem_mask, mc68328->regs.pdpol);
1990            return mc68328->regs.pdpol << 8;
1991         }
1992         break;
1993
1994      case 0x41e:
1995         if( mem_mask & 0x00ff )
1996         {
1997            verboselog(space.machine(), 2, "mc68328_r (%04x): PDIRQEDGE = %02x\n", mem_mask, mc68328->regs.pdirqedge);
1998            return mc68328->regs.pdirqedge;
1999         }
2000         else
2001         {
2002            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff41e)\n", mem_mask);
2003         }
2004         break;
2005
2006      case 0x420:
2007         if( mem_mask & 0x00ff )
2008         {
2009            verboselog(space.machine(), 2, "mc68328_r (%04x): PEDATA = %02x\n", mem_mask, mc68328->regs.pedata);
2010            if(!mc68328->in_port_e.isnull())
2011            {
2012               return mc68328->in_port_e( 0 );
2013            }
2014            else
2015            {
2016               return mc68328->regs.pedata;
2017            }
2018         }
2019         else
2020         {
2021            verboselog(space.machine(), 2, "mc68328_r (%04x): PEDIR = %02x\n", mem_mask, mc68328->regs.pedir);
2022            return mc68328->regs.pedir << 8;
2023         }
2024         break;
2025
2026      case 0x422:
2027         if( mem_mask & 0x00ff )
2028         {
2029            verboselog(space.machine(), 2, "mc68328_r (%04x): PESEL = %02x\n", mem_mask, mc68328->regs.pesel);
2030            return mc68328->regs.pesel;
2031         }
2032         else
2033         {
2034            verboselog(space.machine(), 2, "mc68328_r (%04x): PEPUEN = %02x\n", mem_mask, mc68328->regs.pepuen);
2035            return mc68328->regs.pepuen << 8;
2036         }
2037         break;
2038
2039      case 0x428:
2040         if( mem_mask & 0x00ff )
2041         {
2042            verboselog(space.machine(), 2, "mc68328_r (%04x): PFDATA = %02x\n", mem_mask, mc68328->regs.pfdata);
2043            if(!mc68328->in_port_f.isnull())
2044            {
2045               return mc68328->in_port_f( 0 );
2046            }
2047            else
2048            {
2049               return mc68328->regs.pfdata;
2050            }
2051         }
2052         else
2053         {
2054            verboselog(space.machine(), 2, "mc68328_r (%04x): PFDIR = %02x\n", mem_mask, mc68328->regs.pfdir);
2055            return mc68328->regs.pfdir << 8;
2056         }
2057         break;
2058
2059      case 0x42a:
2060         if( mem_mask & 0x00ff )
2061         {
2062            verboselog(space.machine(), 2, "mc68328_r (%04x): PFSEL = %02x\n", mem_mask, mc68328->regs.pfsel);
2063            return mc68328->regs.pfsel;
2064         }
2065         else
2066         {
2067            verboselog(space.machine(), 2, "mc68328_r (%04x): PFPUEN = %02x\n", mem_mask, mc68328->regs.pfpuen);
2068            return mc68328->regs.pfpuen << 8;
2069         }
2070         break;
2071
2072      case 0x430:
2073         if( mem_mask & 0x00ff )
2074         {
2075            verboselog(space.machine(), 2, "mc68328_r (%04x): PGDATA = %02x\n", mem_mask, mc68328->regs.pgdata);
2076            if(!mc68328->in_port_g.isnull())
2077            {
2078               return mc68328->in_port_g( 0 );
2079            }
2080            else
2081            {
2082               return mc68328->regs.pgdata;
2083            }
2084         }
2085         else
2086         {
2087            verboselog(space.machine(), 2, "mc68328_r (%04x): PGDIR = %02x\n", mem_mask, mc68328->regs.pgdir);
2088            return mc68328->regs.pgdir << 8;
2089         }
2090         break;
2091
2092      case 0x432:
2093         if( mem_mask & 0x00ff )
2094         {
2095            verboselog(space.machine(), 2, "mc68328_r (%04x): PGSEL = %02x\n", mem_mask, mc68328->regs.pgsel);
2096            return mc68328->regs.pgsel;
2097         }
2098         else
2099         {
2100            verboselog(space.machine(), 2, "mc68328_r (%04x): PGPUEN = %02x\n", mem_mask, mc68328->regs.pgpuen);
2101            return mc68328->regs.pgpuen << 8;
2102         }
2103         break;
2104
2105      case 0x438:
2106         if( mem_mask & 0x00ff )
2107         {
2108            verboselog(space.machine(), 2, "mc68328_r (%04x): PJDATA = %02x\n", mem_mask, mc68328->regs.pjdata);
2109            if(!mc68328->in_port_j.isnull())
2110            {
2111               return mc68328->in_port_j( 0 );
2112            }
2113            else
2114            {
2115               return mc68328->regs.pjdata;
2116            }
2117         }
2118         else
2119         {
2120            verboselog(space.machine(), 2, "mc68328_r (%04x): PJDIR = %02x\n", mem_mask, mc68328->regs.pjdir);
2121            return mc68328->regs.pjdir << 8;
2122         }
2123         break;
2124
2125      case 0x43a:
2126         if( mem_mask & 0x00ff )
2127         {
2128            verboselog(space.machine(), 2, "mc68328_r (%04x): PJSEL = %02x\n", mem_mask, mc68328->regs.pjsel);
2129            return mc68328->regs.pjsel;
2130         }
2131         else
2132         {
2133            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff43a)\n", mem_mask);
2134         }
2135         break;
2136
2137      case 0x440:
2138         if( mem_mask & 0x00ff )
2139         {
2140            verboselog(space.machine(), 2, "mc68328_r (%04x): PKDATA = %02x\n", mem_mask, mc68328->regs.pkdata);
2141            if(!mc68328->in_port_k.isnull())
2142            {
2143               return mc68328->in_port_k( 0 );
2144            }
2145            else
2146            {
2147               return mc68328->regs.pkdata;
2148            }
2149         }
2150         else
2151         {
2152            verboselog(space.machine(), 2, "mc68328_r (%04x): PKDIR = %02x\n", mem_mask, mc68328->regs.pkdir);
2153            return mc68328->regs.pkdir << 8;
2154         }
2155         break;
2156
2157      case 0x442:
2158         if( mem_mask & 0x00ff )
2159         {
2160            verboselog(space.machine(), 2, "mc68328_r (%04x): PKSEL = %02x\n", mem_mask, mc68328->regs.pksel);
2161            return mc68328->regs.pksel;
2162         }
2163         else
2164         {
2165            verboselog(space.machine(), 2, "mc68328_r (%04x): PKPUEN = %02x\n", mem_mask, mc68328->regs.pkpuen);
2166            return mc68328->regs.pkpuen << 8;
2167         }
2168         break;
2169
2170      case 0x448:
2171         if( mem_mask & 0x00ff )
2172         {
2173            verboselog(space.machine(), 2, "mc68328_r (%04x): PMDATA = %02x\n", mem_mask, mc68328->regs.pmdata);
2174            if(!mc68328->in_port_m.isnull())
2175            {
2176               return mc68328->in_port_m( 0 );
2177            }
2178            else
2179            {
2180               return mc68328->regs.pmdata;
2181            }
2182         }
2183         else
2184         {
2185            verboselog(space.machine(), 2, "mc68328_r (%04x): PMDIR = %02x\n", mem_mask, mc68328->regs.pmdir);
2186            return mc68328->regs.pmdir << 8;
2187         }
2188         break;
2189
2190      case 0x44a:
2191         if( mem_mask & 0x00ff )
2192         {
2193            verboselog(space.machine(), 2, "mc68328_r (%04x): PMSEL = %02x\n", mem_mask, mc68328->regs.pmsel);
2194            return mc68328->regs.pmsel;
2195         }
2196         else
2197         {
2198            verboselog(space.machine(), 2, "mc68328_r (%04x): PMPUEN = %02x\n", mem_mask, mc68328->regs.pmpuen);
2199            return mc68328->regs.pmpuen << 8;
2200         }
2201         break;
2202
2203      case 0x500:
2204         verboselog(space.machine(), 2, "mc68328_r (%04x): PWMC = %04x\n", mem_mask, mc68328->regs.pwmc);
2205         temp16 = mc68328->regs.pwmc;
2206         if(mc68328->regs.pwmc & PWMC_PWMIRQ)
2207         {
2208            mc68328->regs.pwmc &= ~PWMC_PWMIRQ;
2209            mc68328_set_interrupt_line(device, INT_PWM, 0);
2210         }
2211         return temp16;
2212
2213      case 0x502:
2214         verboselog(space.machine(), 2, "mc68328_r (%04x): PWMP = %04x\n", mem_mask, mc68328->regs.pwmp);
2215         return mc68328->regs.pwmp;
2216
2217      case 0x504:
2218         verboselog(space.machine(), 2, "mc68328_r (%04x): PWMW = %04x\n", mem_mask, mc68328->regs.pwmw);
2219         return mc68328->regs.pwmw;
2220
2221      case 0x506:
2222         verboselog(space.machine(), 2, "mc68328_r (%04x): PWMCNT = %04x\n", mem_mask, mc68328->regs.pwmcnt);
2223         return mc68328->regs.pwmcnt;
2224
2225      case 0x600:
2226         verboselog(space.machine(), 2, "mc68328_r (%04x): TCTL1 = %04x\n", mem_mask, mc68328->regs.tctl[0]);
2227         return mc68328->regs.tctl[0];
2228
2229      case 0x602:
2230         verboselog(space.machine(), 2, "mc68328_r (%04x): TPRER1 = %04x\n", mem_mask, mc68328->regs.tprer[0]);
2231         return mc68328->regs.tprer[0];
2232
2233      case 0x604:
2234         verboselog(space.machine(), 2, "mc68328_r (%04x): TCMP1 = %04x\n", mem_mask, mc68328->regs.tcmp[0]);
2235         return mc68328->regs.tcmp[0];
2236
2237      case 0x606:
2238         verboselog(space.machine(), 2, "mc68328_r (%04x): TCR1 = %04x\n", mem_mask, mc68328->regs.tcr[0]);
2239         return mc68328->regs.tcr[0];
2240
2241      case 0x608:
2242         verboselog(space.machine(), 2, "mc68328_r (%04x): TCN1 = %04x\n", mem_mask, mc68328->regs.tcn[0]);
2243         return mc68328->regs.tcn[0];
2244
2245      case 0x60a:
2246         verboselog(space.machine(), 5, "mc68328_r (%04x): TSTAT1 = %04x\n", mem_mask, mc68328->regs.tstat[0]);
2247         mc68328->regs.tclear[0] |= mc68328->regs.tstat[0];
2248         return mc68328->regs.tstat[0];
2249
2250      case 0x60c:
2251         verboselog(space.machine(), 2, "mc68328_r (%04x): TCTL2 = %04x\n", mem_mask, mc68328->regs.tctl[1]);
2252         return mc68328->regs.tctl[1];
2253
2254      case 0x60e:
2255         verboselog(space.machine(), 2, "mc68328_r (%04x): TPREP2 = %04x\n", mem_mask, mc68328->regs.tprer[1]);
2256         return mc68328->regs.tprer[1];
2257
2258      case 0x610:
2259         verboselog(space.machine(), 2, "mc68328_r (%04x): TCMP2 = %04x\n", mem_mask, mc68328->regs.tcmp[1]);
2260         return mc68328->regs.tcmp[1];
2261
2262      case 0x612:
2263         verboselog(space.machine(), 2, "mc68328_r (%04x): TCR2 = %04x\n", mem_mask, mc68328->regs.tcr[1]);
2264         return mc68328->regs.tcr[1];
2265
2266      case 0x614:
2267         verboselog(space.machine(), 2, "mc68328_r (%04x): TCN2 = %04x\n", mem_mask, mc68328->regs.tcn[1]);
2268         return mc68328->regs.tcn[1];
2269
2270      case 0x616:
2271         verboselog(space.machine(), 2, "mc68328_r (%04x): TSTAT2 = %04x\n", mem_mask, mc68328->regs.tstat[1]);
2272         mc68328->regs.tclear[1] |= mc68328->regs.tstat[1];
2273         return mc68328->regs.tstat[1];
2274
2275      case 0x618:
2276         verboselog(space.machine(), 2, "mc68328_r (%04x): WCTLR = %04x\n", mem_mask, mc68328->regs.wctlr);
2277         return mc68328->regs.wctlr;
2278
2279      case 0x61a:
2280         verboselog(space.machine(), 2, "mc68328_r (%04x): WCMPR = %04x\n", mem_mask, mc68328->regs.wcmpr);
2281         return mc68328->regs.wcmpr;
2282
2283      case 0x61c:
2284         verboselog(space.machine(), 2, "mc68328_r (%04x): WCN = %04x\n", mem_mask, mc68328->regs.wcn);
2285         return mc68328->regs.wcn;
2286
2287      case 0x700:
2288         verboselog(space.machine(), 2, "mc68328_r (%04x): SPISR = %04x\n", mem_mask, mc68328->regs.spisr);
2289         return mc68328->regs.spisr;
2290
2291      case 0x800:
2292         verboselog(space.machine(), 2, "mc68328_r (%04x): SPIMDATA = %04x\n", mem_mask, mc68328->regs.spimdata);
2293         if(!mc68328->in_spim.isnull())
2294         {
2295            return mc68328->in_spim( 0, 0xffff );
2296         }
2297         return mc68328->regs.spimdata;
2298
2299      case 0x802:
2300         verboselog(space.machine(), 2, "mc68328_r (%04x): SPIMCONT = %04x\n", mem_mask, mc68328->regs.spimcont);
2301         if(mc68328->regs.spimcont & SPIM_XCH)
2302         {
2303            mc68328->regs.spimcont &= ~SPIM_XCH;
2304            mc68328->regs.spimcont |= SPIM_SPIMIRQ;
2305            return ((mc68328->regs.spimcont | SPIM_XCH) &~ SPIM_SPIMIRQ);
2306         }
2307         return mc68328->regs.spimcont;
2308
2309      case 0x900:
2310         verboselog(space.machine(), 2, "mc68328_r (%04x): USTCNT = %04x\n", mem_mask, mc68328->regs.ustcnt);
2311         return mc68328->regs.ustcnt;
2312
2313      case 0x902:
2314         verboselog(space.machine(), 2, "mc68328_r (%04x): UBAUD = %04x\n", mem_mask, mc68328->regs.ubaud);
2315         return mc68328->regs.ubaud;
2316
2317      case 0x904:
2318         verboselog(space.machine(), 5, "mc68328_r (%04x): URX = %04x\n", mem_mask, mc68328->regs.urx);
2319         return mc68328->regs.urx;
2320
2321      case 0x906:
2322         verboselog(space.machine(), 5, "mc68328_r (%04x): UTX = %04x\n", mem_mask, mc68328->regs.utx);
2323         return mc68328->regs.utx | UTX_FIFO_EMPTY | UTX_FIFO_HALF | UTX_TX_AVAIL;
2324
2325      case 0x908:
2326         verboselog(space.machine(), 2, "mc68328_r (%04x): UMISC = %04x\n", mem_mask, mc68328->regs.umisc);
2327         return mc68328->regs.umisc;
2328
2329      case 0xa00:
2330         verboselog(space.machine(), 2, "mc68328_r (%04x): LSSA(16) = %04x\n", mem_mask, mc68328->regs.lssa >> 16);
2331         return mc68328->regs.lssa >> 16;
2332
2333      case 0xa02:
2334         verboselog(space.machine(), 2, "mc68328_r (%04x): LSSA(0) = %04x\n", mem_mask, mc68328->regs.lssa & 0x0000ffff);
2335         return mc68328->regs.lssa & 0x0000ffff;
2336
2337      case 0xa04:
2338         if( mem_mask & 0x00ff )
2339         {
2340            verboselog(space.machine(), 2, "mc68328_r (%04x): LVPW = %02x\n", mem_mask, mc68328->regs.lvpw);
2341            return mc68328->regs.lvpw;
2342         }
2343         else
2344         {
2345            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa04)\n", mem_mask);
2346         }
2347         break;
2348
2349      case 0xa08:
2350         verboselog(space.machine(), 2, "mc68328_r (%04x): LXMAX = %04x\n", mem_mask, mc68328->regs.lxmax);
2351         return mc68328->regs.lxmax;
2352
2353      case 0xa0a:
2354         verboselog(space.machine(), 2, "mc68328_r (%04x): LYMAX = %04x\n", mem_mask, mc68328->regs.lymax);
2355         return mc68328->regs.lymax;
2356
2357      case 0xa18:
2358         verboselog(space.machine(), 2, "mc68328_r (%04x): LCXP = %04x\n", mem_mask, mc68328->regs.lcxp);
2359         return mc68328->regs.lcxp;
2360
2361      case 0xa1a:
2362         verboselog(space.machine(), 2, "mc68328_r (%04x): LCYP = %04x\n", mem_mask, mc68328->regs.lcyp);
2363         return mc68328->regs.lcyp;
2364
2365      case 0xa1c:
2366         verboselog(space.machine(), 2, "mc68328_r (%04x): LCWCH = %04x\n", mem_mask, mc68328->regs.lcwch);
2367         return mc68328->regs.lcwch;
2368
2369      case 0xa1e:
2370         if( mem_mask & 0x00ff )
2371         {
2372            verboselog(space.machine(), 2, "mc68328_r (%04x): LBLKC = %02x\n", mem_mask, mc68328->regs.lblkc);
2373            return mc68328->regs.lblkc;
2374         }
2375         else
2376         {
2377            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa1e)\n", mem_mask);
2378         }
2379         break;
2380
2381      case 0xa20:
2382         if( mem_mask & 0x00ff )
2383         {
2384            verboselog(space.machine(), 2, "mc68328_r (%04x): LPOLCF = %02x\n", mem_mask, mc68328->regs.lpolcf);
2385            return mc68328->regs.lpolcf;
2386         }
2387         else
2388         {
2389            verboselog(space.machine(), 2, "mc68328_r (%04x): LPICF = %02x\n", mem_mask, mc68328->regs.lpicf);
2390            return mc68328->regs.lpicf << 8;
2391         }
2392         break;
2393
2394      case 0xa22:
2395         if( mem_mask & 0x00ff )
2396         {
2397            verboselog(space.machine(), 2, "mc68328_r (%04x): LACDRC = %02x\n", mem_mask, mc68328->regs.lacdrc);
2398            return mc68328->regs.lacdrc;
2399         }
2400         else
2401         {
2402            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa22)\n", mem_mask);
2403         }
2404         break;
2405
2406      case 0xa24:
2407         if( mem_mask & 0x00ff )
2408         {
2409            verboselog(space.machine(), 2, "mc68328_r (%04x): LPXCD = %02x\n", mem_mask, mc68328->regs.lpxcd);
2410            return mc68328->regs.lpxcd;
2411         }
2412         else
2413         {
2414            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa24)\n", mem_mask);
2415         }
2416         break;
2417
2418      case 0xa26:
2419         if( mem_mask & 0x00ff )
2420         {
2421            verboselog(space.machine(), 2, "mc68328_r (%04x): LCKCON = %02x\n", mem_mask, mc68328->regs.lckcon);
2422            return mc68328->regs.lckcon;
2423         }
2424         else
2425         {
2426            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa26)\n", mem_mask);
2427         }
2428         break;
2429
2430      case 0xa28:
2431         if( mem_mask & 0x00ff )
2432         {
2433            verboselog(space.machine(), 2, "mc68328_r (%04x): LLBAR = %02x\n", mem_mask, mc68328->regs.llbar);
2434            return mc68328->regs.llbar;
2435         }
2436         else
2437         {
2438            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa28)\n", mem_mask);
2439         }
2440         break;
2441
2442      case 0xa2a:
2443         if( mem_mask & 0x00ff )
2444         {
2445            verboselog(space.machine(), 2, "mc68328_r (%04x): LOTCR = %02x\n", mem_mask, mc68328->regs.lotcr);
2446            return mc68328->regs.lotcr;
2447         }
2448         else
2449         {
2450            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa2a)\n", mem_mask);
2451         }
2452         break;
2453
2454      case 0xa2c:
2455         if( mem_mask & 0x00ff )
2456         {
2457            verboselog(space.machine(), 2, "mc68328_r (%04x): LPOSR = %02x\n", mem_mask, mc68328->regs.lposr);
2458            return mc68328->regs.lposr;
2459         }
2460         else
2461         {
2462            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa2c)\n", mem_mask);
2463         }
2464         break;
2465
2466      case 0xa30:
2467         if( mem_mask & 0x00ff )
2468         {
2469            verboselog(space.machine(), 2, "mc68328_r (%04x): LFRCM = %02x\n", mem_mask, mc68328->regs.lfrcm);
2470            return mc68328->regs.lfrcm;
2471         }
2472         else
2473         {
2474            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa30)\n", mem_mask);
2475         }
2476         break;
2477
2478      case 0xa32:
2479         verboselog(space.machine(), 2, "mc68328_r (%04x): LGPMR = %04x\n", mem_mask, mc68328->regs.lgpmr);
2480         return mc68328->regs.lgpmr;
2481
2482      case 0xb00:
2483         verboselog(space.machine(), 2, "mc68328_r (%04x): HMSR(0) = %04x\n", mem_mask, mc68328->regs.hmsr & 0x0000ffff);
2484         return mc68328->regs.hmsr & 0x0000ffff;
2485
2486      case 0xb02:
2487         verboselog(space.machine(), 2, "mc68328_r (%04x): HMSR(16) = %04x\n", mem_mask, mc68328->regs.hmsr >> 16);
2488         return mc68328->regs.hmsr >> 16;
2489
2490      case 0xb04:
2491         verboselog(space.machine(), 2, "mc68328_r (%04x): ALARM(0) = %04x\n", mem_mask, mc68328->regs.alarm & 0x0000ffff);
2492         return mc68328->regs.alarm & 0x0000ffff;
2493
2494      case 0xb06:
2495         verboselog(space.machine(), 2, "mc68328_r (%04x): ALARM(16) = %04x\n", mem_mask, mc68328->regs.alarm >> 16);
2496         return mc68328->regs.alarm >> 16;
2497
2498      case 0xb0c:
2499         verboselog(space.machine(), 2, "mc68328_r (%04x): RTCCTL = %04x\n", mem_mask, mc68328->regs.rtcctl);
2500         return mc68328->regs.rtcctl;
2501
2502      case 0xb0e:
2503         verboselog(space.machine(), 2, "mc68328_r (%04x): RTCISR = %04x\n", mem_mask, mc68328->regs.rtcisr);
2504         return mc68328->regs.rtcisr;
2505
2506      case 0xb10:
2507         verboselog(space.machine(), 2, "mc68328_r (%04x): RTCIENR = %04x\n", mem_mask, mc68328->regs.rtcienr);
2508         return mc68328->regs.rtcienr;
2509
2510      case 0xb12:
2511         verboselog(space.machine(), 2, "mc68328_r (%04x): STPWTCH = %04x\n", mem_mask, mc68328->regs.stpwtch);
2512         return mc68328->regs.stpwtch;
2513
2514      default:
2515         verboselog(space.machine(), 0, "mc68328_r (%04x): Unknown address (0x%06x)\n", mem_mask, 0xfff000 + address);
2516         break;
2517   }
2518   return 0;
2519}
2520
2521static DEVICE_RESET( mc68328 )
2522{
2523   mc68328_t* mc68328 = mc68328_get_safe_token( device );
2524
2525   mc68328->regs.scr = 0x0c;
2526   mc68328->regs.grpbasea = 0x0000;
2527   mc68328->regs.grpbaseb = 0x0000;
2528   mc68328->regs.grpbasec = 0x0000;
2529   mc68328->regs.grpbased = 0x0000;
2530   mc68328->regs.grpmaska = 0x0000;
2531   mc68328->regs.grpmaskb = 0x0000;
2532   mc68328->regs.grpmaskc = 0x0000;
2533   mc68328->regs.grpmaskd = 0x0000;
2534   mc68328->regs.csa0 = 0x00010006;
2535   mc68328->regs.csa1 = 0x00010006;
2536   mc68328->regs.csa2 = 0x00010006;
2537   mc68328->regs.csa3 = 0x00010006;
2538   mc68328->regs.csb0 = 0x00010006;
2539   mc68328->regs.csb1 = 0x00010006;
2540   mc68328->regs.csb2 = 0x00010006;
2541   mc68328->regs.csb3 = 0x00010006;
2542   mc68328->regs.csc0 = 0x00010006;
2543   mc68328->regs.csc1 = 0x00010006;
2544   mc68328->regs.csc2 = 0x00010006;
2545   mc68328->regs.csc3 = 0x00010006;
2546   mc68328->regs.csd0 = 0x00010006;
2547   mc68328->regs.csd1 = 0x00010006;
2548   mc68328->regs.csd2 = 0x00010006;
2549   mc68328->regs.csd3 = 0x00010006;
2550
2551   mc68328->regs.pllcr = 0x2400;
2552   mc68328->regs.pllfsr = 0x0123;
2553   mc68328->regs.pctlr = 0x1f;
2554
2555   mc68328->regs.ivr = 0x00;
2556   mc68328->regs.icr = 0x0000;
2557   mc68328->regs.imr = 0x00ffffff;
2558   mc68328->regs.iwr = 0x00ffffff;
2559   mc68328->regs.isr = 0x00000000;
2560   mc68328->regs.ipr = 0x00000000;
2561
2562   mc68328->regs.padir = 0x00;
2563   mc68328->regs.padata = 0x00;
2564   mc68328->regs.pasel = 0x00;
2565   mc68328->regs.pbdir = 0x00;
2566   mc68328->regs.pbdata = 0x00;
2567   mc68328->regs.pbsel = 0x00;
2568   mc68328->regs.pcdir = 0x00;
2569   mc68328->regs.pcdata = 0x00;
2570   mc68328->regs.pcsel = 0x00;
2571   mc68328->regs.pddir = 0x00;
2572   mc68328->regs.pddata = 0x00;
2573   mc68328->regs.pdpuen = 0xff;
2574   mc68328->regs.pdpol = 0x00;
2575   mc68328->regs.pdirqen = 0x00;
2576   mc68328->regs.pddataedge = 0x00;
2577   mc68328->regs.pdirqedge = 0x00;
2578   mc68328->regs.pedir = 0x00;
2579   mc68328->regs.pedata = 0x00;
2580   mc68328->regs.pepuen = 0x80;
2581   mc68328->regs.pesel = 0x80;
2582   mc68328->regs.pfdir = 0x00;
2583   mc68328->regs.pfdata = 0x00;
2584   mc68328->regs.pfpuen = 0xff;
2585   mc68328->regs.pfsel = 0xff;
2586   mc68328->regs.pgdir = 0x00;
2587   mc68328->regs.pgdata = 0x00;
2588   mc68328->regs.pgpuen = 0xff;
2589   mc68328->regs.pgsel = 0xff;
2590   mc68328->regs.pjdir = 0x00;
2591   mc68328->regs.pjdata = 0x00;
2592   mc68328->regs.pjsel = 0x00;
2593   mc68328->regs.pkdir = 0x00;
2594   mc68328->regs.pkdata = 0x00;
2595   mc68328->regs.pkpuen = 0xff;
2596   mc68328->regs.pksel = 0xff;
2597   mc68328->regs.pmdir = 0x00;
2598   mc68328->regs.pmdata = 0x00;
2599   mc68328->regs.pmpuen = 0xff;
2600   mc68328->regs.pmsel = 0xff;
2601
2602   mc68328->regs.pwmc = 0x0000;
2603   mc68328->regs.pwmp = 0x0000;
2604   mc68328->regs.pwmw = 0x0000;
2605   mc68328->regs.pwmcnt = 0x0000;
2606
2607   mc68328->regs.tctl[0] = mc68328->regs.tctl[1] = 0x0000;
2608   mc68328->regs.tprer[0] = mc68328->regs.tprer[1] = 0x0000;
2609   mc68328->regs.tcmp[0] = mc68328->regs.tcmp[1] = 0xffff;
2610   mc68328->regs.tcr[0] = mc68328->regs.tcr[1] = 0x0000;
2611   mc68328->regs.tcn[0] = mc68328->regs.tcn[1] = 0x0000;
2612   mc68328->regs.tstat[0] = mc68328->regs.tstat[1] = 0x0000;
2613   mc68328->regs.wctlr = 0x0000;
2614   mc68328->regs.wcmpr = 0xffff;
2615   mc68328->regs.wcn = 0x0000;
2616
2617   mc68328->regs.spisr = 0x0000;
2618
2619   mc68328->regs.spimdata = 0x0000;
2620   mc68328->regs.spimcont = 0x0000;
2621
2622   mc68328->regs.ustcnt = 0x0000;
2623   mc68328->regs.ubaud = 0x003f;
2624   mc68328->regs.urx = 0x0000;
2625   mc68328->regs.utx = 0x0000;
2626   mc68328->regs.umisc = 0x0000;
2627
2628   mc68328->regs.lssa = 0x00000000;
2629   mc68328->regs.lvpw = 0xff;
2630   mc68328->regs.lxmax = 0x03ff;
2631   mc68328->regs.lymax = 0x01ff;
2632   mc68328->regs.lcxp = 0x0000;
2633   mc68328->regs.lcyp = 0x0000;
2634   mc68328->regs.lcwch = 0x0101;
2635   mc68328->regs.lblkc = 0x7f;
2636   mc68328->regs.lpicf = 0x00;
2637   mc68328->regs.lpolcf = 0x00;
2638   mc68328->regs.lacdrc = 0x00;
2639   mc68328->regs.lpxcd = 0x00;
2640   mc68328->regs.lckcon = 0x40;
2641   mc68328->regs.llbar = 0x3e;
2642   mc68328->regs.lotcr = 0x3f;
2643   mc68328->regs.lposr = 0x00;
2644   mc68328->regs.lfrcm = 0xb9;
2645   mc68328->regs.lgpmr = 0x1073;
2646
2647   mc68328->regs.hmsr = 0x00000000;
2648   mc68328->regs.alarm = 0x00000000;
2649   mc68328->regs.rtcctl = 0x00;
2650   mc68328->regs.rtcisr = 0x00;
2651   mc68328->regs.rtcienr = 0x00;
2652   mc68328->regs.stpwtch = 0x00;
2653
2654   mc68328->rtc->adjust(attotime::from_hz(1), 0, attotime::from_hz(1));
2655}
2656
2657static void mc68328_register_state_save(device_t *device)
2658{
2659   mc68328_t* mc68328 = mc68328_get_safe_token( device );
2660
2661   state_save_register_global(device->machine(), mc68328->regs.scr);
2662   state_save_register_global(device->machine(), mc68328->regs.grpbasea);
2663   state_save_register_global(device->machine(), mc68328->regs.grpbaseb);
2664   state_save_register_global(device->machine(), mc68328->regs.grpbasec);
2665   state_save_register_global(device->machine(), mc68328->regs.grpbased);
2666   state_save_register_global(device->machine(), mc68328->regs.grpmaska);
2667   state_save_register_global(device->machine(), mc68328->regs.grpmaskb);
2668   state_save_register_global(device->machine(), mc68328->regs.grpmaskc);
2669   state_save_register_global(device->machine(), mc68328->regs.grpmaskd);
2670   state_save_register_global(device->machine(), mc68328->regs.csa0);
2671   state_save_register_global(device->machine(), mc68328->regs.csa1);
2672   state_save_register_global(device->machine(), mc68328->regs.csa2);
2673   state_save_register_global(device->machine(), mc68328->regs.csa3);
2674   state_save_register_global(device->machine(), mc68328->regs.csb0);
2675   state_save_register_global(device->machine(), mc68328->regs.csb1);
2676   state_save_register_global(device->machine(), mc68328->regs.csb2);
2677   state_save_register_global(device->machine(), mc68328->regs.csb3);
2678   state_save_register_global(device->machine(), mc68328->regs.csc0);
2679   state_save_register_global(device->machine(), mc68328->regs.csc1);
2680   state_save_register_global(device->machine(), mc68328->regs.csc2);
2681   state_save_register_global(device->machine(), mc68328->regs.csc3);
2682   state_save_register_global(device->machine(), mc68328->regs.csd0);
2683   state_save_register_global(device->machine(), mc68328->regs.csd1);
2684   state_save_register_global(device->machine(), mc68328->regs.csd2);
2685   state_save_register_global(device->machine(), mc68328->regs.csd3);
2686
2687   state_save_register_global(device->machine(), mc68328->regs.pllcr);
2688   state_save_register_global(device->machine(), mc68328->regs.pllfsr);
2689   state_save_register_global(device->machine(), mc68328->regs.pctlr);
2690
2691   state_save_register_global(device->machine(), mc68328->regs.ivr);
2692   state_save_register_global(device->machine(), mc68328->regs.icr);
2693   state_save_register_global(device->machine(), mc68328->regs.imr);
2694   state_save_register_global(device->machine(), mc68328->regs.iwr);
2695   state_save_register_global(device->machine(), mc68328->regs.isr);
2696   state_save_register_global(device->machine(), mc68328->regs.ipr);
2697
2698   state_save_register_global(device->machine(), mc68328->regs.padir);
2699   state_save_register_global(device->machine(), mc68328->regs.padata);
2700   state_save_register_global(device->machine(), mc68328->regs.pasel);
2701   state_save_register_global(device->machine(), mc68328->regs.pbdir);
2702   state_save_register_global(device->machine(), mc68328->regs.pbdata);
2703   state_save_register_global(device->machine(), mc68328->regs.pbsel);
2704   state_save_register_global(device->machine(), mc68328->regs.pcdir);
2705   state_save_register_global(device->machine(), mc68328->regs.pcdata);
2706   state_save_register_global(device->machine(), mc68328->regs.pcsel);
2707   state_save_register_global(device->machine(), mc68328->regs.pddir);
2708   state_save_register_global(device->machine(), mc68328->regs.pddata);
2709   state_save_register_global(device->machine(), mc68328->regs.pdpuen);
2710   state_save_register_global(device->machine(), mc68328->regs.pdpol);
2711   state_save_register_global(device->machine(), mc68328->regs.pdirqen);
2712   state_save_register_global(device->machine(), mc68328->regs.pddataedge);
2713   state_save_register_global(device->machine(), mc68328->regs.pdirqedge);
2714   state_save_register_global(device->machine(), mc68328->regs.pedir);
2715   state_save_register_global(device->machine(), mc68328->regs.pedata);
2716   state_save_register_global(device->machine(), mc68328->regs.pepuen);
2717   state_save_register_global(device->machine(), mc68328->regs.pesel);
2718   state_save_register_global(device->machine(), mc68328->regs.pfdir);
2719   state_save_register_global(device->machine(), mc68328->regs.pfdata);
2720   state_save_register_global(device->machine(), mc68328->regs.pfpuen);
2721   state_save_register_global(device->machine(), mc68328->regs.pfsel);
2722   state_save_register_global(device->machine(), mc68328->regs.pgdir);
2723   state_save_register_global(device->machine(), mc68328->regs.pgdata);
2724   state_save_register_global(device->machine(), mc68328->regs.pgpuen);
2725   state_save_register_global(device->machine(), mc68328->regs.pgsel);
2726   state_save_register_global(device->machine(), mc68328->regs.pjdir);
2727   state_save_register_global(device->machine(), mc68328->regs.pjdata);
2728   state_save_register_global(device->machine(), mc68328->regs.pjsel);
2729   state_save_register_global(device->machine(), mc68328->regs.pkdir);
2730   state_save_register_global(device->machine(), mc68328->regs.pkdata);
2731   state_save_register_global(device->machine(), mc68328->regs.pkpuen);
2732   state_save_register_global(device->machine(), mc68328->regs.pksel);
2733   state_save_register_global(device->machine(), mc68328->regs.pmdir);
2734   state_save_register_global(device->machine(), mc68328->regs.pmdata);
2735   state_save_register_global(device->machine(), mc68328->regs.pmpuen);
2736   state_save_register_global(device->machine(), mc68328->regs.pmsel);
2737
2738   state_save_register_global(device->machine(), mc68328->regs.pwmc);
2739   state_save_register_global(device->machine(), mc68328->regs.pwmp);
2740   state_save_register_global(device->machine(), mc68328->regs.pwmw);
2741   state_save_register_global(device->machine(), mc68328->regs.pwmcnt);
2742
2743   state_save_register_global(device->machine(), mc68328->regs.tctl[0]);
2744   state_save_register_global(device->machine(), mc68328->regs.tctl[1]);
2745   state_save_register_global(device->machine(), mc68328->regs.tprer[0]);
2746   state_save_register_global(device->machine(), mc68328->regs.tprer[1]);
2747   state_save_register_global(device->machine(), mc68328->regs.tcmp[0]);
2748   state_save_register_global(device->machine(), mc68328->regs.tcmp[1]);
2749   state_save_register_global(device->machine(), mc68328->regs.tcr[0]);
2750   state_save_register_global(device->machine(), mc68328->regs.tcr[1]);
2751   state_save_register_global(device->machine(), mc68328->regs.tcn[0]);
2752   state_save_register_global(device->machine(), mc68328->regs.tcn[1]);
2753   state_save_register_global(device->machine(), mc68328->regs.tstat[0]);
2754   state_save_register_global(device->machine(), mc68328->regs.tstat[1]);
2755   state_save_register_global(device->machine(), mc68328->regs.wctlr);
2756   state_save_register_global(device->machine(), mc68328->regs.wcmpr);
2757   state_save_register_global(device->machine(), mc68328->regs.wcn);
2758
2759   state_save_register_global(device->machine(), mc68328->regs.spisr);
2760
2761   state_save_register_global(device->machine(), mc68328->regs.spimdata);
2762   state_save_register_global(device->machine(), mc68328->regs.spimcont);
2763
2764   state_save_register_global(device->machine(), mc68328->regs.ustcnt);
2765   state_save_register_global(device->machine(), mc68328->regs.ubaud);
2766   state_save_register_global(device->machine(), mc68328->regs.urx);
2767   state_save_register_global(device->machine(), mc68328->regs.utx);
2768   state_save_register_global(device->machine(), mc68328->regs.umisc);
2769
2770   state_save_register_global(device->machine(), mc68328->regs.lssa);
2771   state_save_register_global(device->machine(), mc68328->regs.lvpw);
2772   state_save_register_global(device->machine(), mc68328->regs.lxmax);
2773   state_save_register_global(device->machine(), mc68328->regs.lymax);
2774   state_save_register_global(device->machine(), mc68328->regs.lcxp);
2775   state_save_register_global(device->machine(), mc68328->regs.lcyp);
2776   state_save_register_global(device->machine(), mc68328->regs.lcwch);
2777   state_save_register_global(device->machine(), mc68328->regs.lblkc);
2778   state_save_register_global(device->machine(), mc68328->regs.lpicf);
2779   state_save_register_global(device->machine(), mc68328->regs.lpolcf);
2780   state_save_register_global(device->machine(), mc68328->regs.lacdrc);
2781   state_save_register_global(device->machine(), mc68328->regs.lpxcd);
2782   state_save_register_global(device->machine(), mc68328->regs.lckcon);
2783   state_save_register_global(device->machine(), mc68328->regs.llbar);
2784   state_save_register_global(device->machine(), mc68328->regs.lotcr);
2785   state_save_register_global(device->machine(), mc68328->regs.lposr);
2786   state_save_register_global(device->machine(), mc68328->regs.lfrcm);
2787   state_save_register_global(device->machine(), mc68328->regs.lgpmr);
2788
2789   state_save_register_global(device->machine(), mc68328->regs.hmsr);
2790   state_save_register_global(device->machine(), mc68328->regs.alarm);
2791   state_save_register_global(device->machine(), mc68328->regs.rtcctl);
2792   state_save_register_global(device->machine(), mc68328->regs.rtcisr);
2793   state_save_register_global(device->machine(), mc68328->regs.rtcienr);
2794   state_save_register_global(device->machine(), mc68328->regs.stpwtch);
2795}
2796
2797static DEVICE_START( mc68328 )
2798{
2799   mc68328_t* mc68328 = mc68328_get_safe_token( device );
2800
2801   mc68328->iface = (const mc68328_interface*)device->static_config();
2802
2803   mc68328->out_port_a.resolve(mc68328->iface->out_port_a_func, *device);
2804   mc68328->out_port_b.resolve(mc68328->iface->out_port_b_func, *device);
2805   mc68328->out_port_c.resolve(mc68328->iface->out_port_c_func, *device);
2806   mc68328->out_port_d.resolve(mc68328->iface->out_port_d_func, *device);
2807   mc68328->out_port_e.resolve(mc68328->iface->out_port_e_func, *device);
2808   mc68328->out_port_f.resolve(mc68328->iface->out_port_f_func, *device);
2809   mc68328->out_port_g.resolve(mc68328->iface->out_port_g_func, *device);
2810   mc68328->out_port_j.resolve(mc68328->iface->out_port_j_func, *device);
2811   mc68328->out_port_k.resolve(mc68328->iface->out_port_k_func, *device);
2812   mc68328->out_port_m.resolve(mc68328->iface->out_port_m_func, *device);
2813
2814   mc68328->in_port_a.resolve(mc68328->iface->in_port_a_func, *device);
2815   mc68328->in_port_b.resolve(mc68328->iface->in_port_b_func, *device);
2816   mc68328->in_port_c.resolve(mc68328->iface->in_port_c_func, *device);
2817   mc68328->in_port_d.resolve(mc68328->iface->in_port_d_func, *device);
2818   mc68328->in_port_e.resolve(mc68328->iface->in_port_e_func, *device);
2819   mc68328->in_port_f.resolve(mc68328->iface->in_port_f_func, *device);
2820   mc68328->in_port_g.resolve(mc68328->iface->in_port_g_func, *device);
2821   mc68328->in_port_j.resolve(mc68328->iface->in_port_j_func, *device);
2822   mc68328->in_port_k.resolve(mc68328->iface->in_port_k_func, *device);
2823   mc68328->in_port_m.resolve(mc68328->iface->in_port_m_func, *device);
2824
2825   mc68328->out_pwm.resolve(mc68328->iface->out_pwm_func, *device);
2826
2827   mc68328->out_spim.resolve(mc68328->iface->out_spim_func, *device);
2828   mc68328->in_spim.resolve(mc68328->iface->in_spim_func, *device);
2829
2830   mc68328->gptimer[0] = device->machine().scheduler().timer_alloc(FUNC(mc68328_timer1_hit));
2831   mc68328->gptimer[1] = device->machine().scheduler().timer_alloc(FUNC(mc68328_timer2_hit));
2832   mc68328->rtc = device->machine().scheduler().timer_alloc(FUNC(mc68328_rtc_tick));
2833   mc68328->pwm = device->machine().scheduler().timer_alloc(FUNC(mc68328_pwm_transition));
2834
2835   mc68328_register_state_save(device);
2836}
2837
2838const device_type MC68328 = &device_creator<mc68328_device>;
2839
2840mc68328_device::mc68328_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
2841   : device_t(mconfig, MC68328, "Motorola MC68328 (DragonBall) Integrated Processor", tag, owner, clock)
2842{
2843   m_token = global_alloc_clear(mc68328_t);
2844}
2845
2846//-------------------------------------------------
2847//  device_config_complete - perform any
2848//  operations now that the configuration is
2849//  complete
2850//-------------------------------------------------
2851
2852void mc68328_device::device_config_complete()
2853{
2854}
2855
2856//-------------------------------------------------
2857//  device_start - device-specific startup
2858//-------------------------------------------------
2859
2860void mc68328_device::device_start()
2861{
2862   DEVICE_START_NAME( mc68328 )(this);
2863}
2864
2865//-------------------------------------------------
2866//  device_reset - device-specific reset
2867//-------------------------------------------------
2868
2869void mc68328_device::device_reset()
2870{
2871   DEVICE_RESET_NAME( mc68328 )(this);
2872}
Property changes on: trunk/src/emu/machine/mc68328.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/mc68328.h
r0r21685
1/**********************************************************************
2
3    Motorola 68328 ("DragonBall") System-on-a-Chip private data
4
5    By MooglyGuy
6    contact mooglyguy@gmail.com with licensing and usage questions.
7
8**********************************************************************/
9
10#ifndef __MC68328_PRIVATE_H_
11#define __MC68328_PRIVATE_H_
12
13struct mc68328_regs_t
14{
15   // $(FF)FFF000
16   UINT8   scr;        // System Control Register
17   UINT8   unused0[255];
18
19   // $(FF)FFF100
20   UINT16  grpbasea;   // Chip Select Group A Base Register
21   UINT16  grpbaseb;   // Chip Select Group B Base Register
22   UINT16  grpbasec;   // Chip Select Group C Base Register
23   UINT16  grpbased;   // Chip Select Group D Base Register
24   UINT16  grpmaska;   // Chip Select Group A Mask Register
25   UINT16  grpmaskb;   // Chip Select Group B Mask Register
26   UINT16  grpmaskc;   // Chip Select Group C Mask Register
27   UINT16  grpmaskd;   // Chip Select Group D Mask Register
28   UINT32  csa0;       // Group A Chip Select 0 Register
29   UINT32  csa1;       // Group A Chip Select 1 Register
30   UINT32  csa2;       // Group A Chip Select 2 Register
31   UINT32  csa3;       // Group A Chip Select 3 Register
32   UINT32  csb0;       // Group B Chip Select 0 Register
33   UINT32  csb1;       // Group B Chip Select 1 Register
34   UINT32  csb2;       // Group B Chip Select 2 Register
35   UINT32  csb3;       // Group B Chip Select 3 Register
36   UINT32  csc0;       // Group C Chip Select 0 Register
37   UINT32  csc1;       // Group C Chip Select 1 Register
38   UINT32  csc2;       // Group C Chip Select 2 Register
39   UINT32  csc3;       // Group C Chip Select 3 Register
40   UINT32  csd0;       // Group D Chip Select 0 Register
41   UINT32  csd1;       // Group D Chip Select 1 Register
42   UINT32  csd2;       // Group D Chip Select 2 Register
43   UINT32  csd3;       // Group D Chip Select 3 Register
44   UINT8   unused1[176];
45
46   // $(FF)FFF200
47   UINT16  pllcr;      // PLL Control Register
48   UINT16  pllfsr;     // PLL Frequency Select Register
49   UINT8   pad2[3];
50   UINT8   pctlr;      // Power Control Register
51   UINT8   unused3[248];
52
53   // $(FF)FFF300
54   UINT8   ivr;        // Interrupt Vector Register
55   UINT8   unused4[1];
56   UINT16  icr;        // Interrupt Control Register
57   UINT32  imr;        // Interrupt Mask Register
58   UINT32  iwr;        // Interrupt Wakeup Enable Register
59   UINT32  isr;        // Interrupt Status Register
60   UINT32  ipr;        // Interrupt Pending Register
61   UINT8   unused5[236];
62
63   // $(FF)FFF400
64   UINT8   padir;      // Port A Direction Register
65   UINT8   padata;     // Port A Data Register
66   UINT8   unused6[1];
67   UINT8   pasel;      // Port A Select Register
68   UINT8   unused7[4];
69
70   UINT8   pbdir;      // Port B Direction Register
71   UINT8   pbdata;     // Port B Data Register
72   UINT8   unused8[1];
73   UINT8   pbsel;      // Port B Select Register
74   UINT8   unused9[4];
75
76   UINT8   pcdir;      // Port C Direction Register
77   UINT8   pcdata;     // Port C Data Register
78   UINT8   unused10[1];
79   UINT8   pcsel;      // Port C Select Register
80   UINT8   unused11[4];
81
82   UINT8   pddir;      // Port D Direction Register
83   UINT8   pddata;     // Port D Data Register
84   UINT8   pdpuen;     // Port D Pullup Enable Register
85   UINT8   unused12[1];
86   UINT8   pdpol;      // Port D Polarity Register
87   UINT8   pdirqen;    // Port D IRQ Enable Register
88   UINT8   pddataedge; // Port D Data Edge Level
89   UINT8   pdirqedge;  // Port D IRQ Edge Register
90
91   UINT8   pedir;      // Port E Direction Register
92   UINT8   pedata;     // Port E Data Register
93   UINT8   pepuen;     // Port E Pullup Enable Register
94   UINT8   pesel;      // Port E Select Register
95   UINT8   unused14[4];
96
97   UINT8   pfdir;      // Port F Direction Register
98   UINT8   pfdata;     // Port F Data Register
99   UINT8   pfpuen;     // Port F Pullup Enable Register
100   UINT8   pfsel;      // Port F Select Register
101   UINT8   unused15[4];
102
103   UINT8   pgdir;      // Port G Direction Register
104   UINT8   pgdata;     // Port G Data Register
105   UINT8   pgpuen;     // Port G Pullup Enable Register
106   UINT8   pgsel;      // Port G Select Register
107   UINT8   unused16[4];
108
109   UINT8   pjdir;      // Port J Direction Register
110   UINT8   pjdata;     // Port J Data Register
111   UINT8   unused17[1];
112   UINT8   pjsel;      // Port J Select Register
113   UINT8   unused18[4];
114   UINT8   pkdir;      // Port K Direction Register
115   UINT8   pkdata;     // Port K Data Register
116   UINT8   pkpuen;     // Port K Pullup Enable Register
117   UINT8   pksel;      // Port K Select Register
118   UINT8   unused19[4];
119
120   UINT8   pmdir;      // Port M Direction Register
121   UINT8   pmdata;     // Port M Data Register
122   UINT8   pmpuen;     // Port M Pullup Enable Register
123   UINT8   pmsel;      // Port M Select Register
124   UINT8   unused20[180];
125
126   // $(FF)FFF500
127   UINT16  pwmc;       // PWM Control Register
128   UINT16  pwmp;       // PWM Period Register
129   UINT16  pwmw;       // PWM Width Register
130   UINT16  pwmcnt;     // PWN Counter
131   UINT8   unused21[248];
132
133   // $(FF)FFF600
134   UINT16  tctl[2];    // Timer Control Register
135   UINT16  tprer[2];   // Timer Prescaler Register
136   UINT16  tcmp[2];    // Timer Compare Register
137   UINT16  tcr[2];     // Timer Capture Register
138   UINT16  tcn[2];     // Timer Counter
139   UINT16  tstat[2];   // Timer Status
140   UINT16  wctlr;      // Watchdog Control Register
141   UINT16  wcmpr;      // Watchdog Compare Register
142   UINT16  wcn;        // Watchdog Counter
143   UINT8   tclear[2];  // Timer Clearable Status
144   UINT8   unused22[224];
145
146   // $(FF)FFF700
147   UINT16  spisr;      // SPIS Register
148   UINT8   unused23[254];
149
150   // $(FF)FFF800
151   UINT16  spimdata;   // SPIM Data Register
152   UINT16  spimcont;   // SPIM Control/Status Register
153   UINT8   unused24[252];
154
155   // $(FF)FFF900
156   UINT16  ustcnt;     // UART Status/Control Register
157   UINT16  ubaud;      // UART Baud Control Register
158   UINT16  urx;        // UART RX Register
159   UINT16  utx;        // UART TX Register
160   UINT16  umisc;      // UART Misc Register
161   UINT8   unused25[246];
162
163   // $(FF)FFFA00
164   UINT32  lssa;       // Screen Starting Address Register
165   UINT8   unused26[1];
166   UINT8   lvpw;       // Virtual Page Width Register
167   UINT8   unused27[2];
168   UINT16  lxmax;      // Screen Width Register
169   UINT16  lymax;      // Screen Height Register
170   UINT8   unused28[12];
171   UINT16  lcxp;       // Cursor X Position
172   UINT16  lcyp;       // Cursor Y Position
173   UINT16  lcwch;      // Cursor Width & Height Register
174   UINT8   unused29[1];
175   UINT8   lblkc;      // Blink Control Register
176   UINT8   lpicf;      // Panel Interface Config Register
177   UINT8   lpolcf;     // Polarity Config Register
178   UINT8   unused30[1];
179   UINT8   lacdrc;     // ACD (M) Rate Control Register
180   UINT8   unused31[1];
181   UINT8   lpxcd;      // Pixel Clock Divider Register
182   UINT8   unused32[1];
183   UINT8   lckcon;     // Clocking Control Register
184   UINT8   unused33[1];
185   UINT8   llbar;      // Last Buffer Address Register
186   UINT8   unused34[1];
187   UINT8   lotcr;      // Octet Terminal Count Register
188   UINT8   unused35[1];
189   UINT8   lposr;      // Panning Offset Register
190   UINT8   unused36[3];
191   UINT8   lfrcm;      // Frame Rate Control Modulation Register
192   UINT16  lgpmr;      // Gray Palette Mapping Register
193   UINT8   unused37[204];
194
195   // $(FF)FFFB00
196   UINT32  hmsr;       // RTC Hours Minutes Seconds Register
197   UINT32  alarm;      // RTC Alarm Register
198   UINT8   unused38[4];
199   UINT16  rtcctl;     // RTC Control Register
200   UINT16  rtcisr;     // RTC Interrupt Status Register
201   UINT16  rtcienr;    // RTC Interrupt Enable Register
202   UINT16  stpwtch;    // Stopwatch Minutes
203   UINT8   unused42[1260];
204};
205
206struct mc68328_t
207{
208   const mc68328_interface* iface;
209
210   mc68328_regs_t regs;
211
212   emu_timer *gptimer[2];
213   emu_timer *rtc;
214   emu_timer *pwm;
215
216   devcb_resolved_write8  out_port_a;    /* 8-bit output */
217   devcb_resolved_write8  out_port_b;    /* 8-bit output */
218   devcb_resolved_write8  out_port_c;    /* 8-bit output */
219   devcb_resolved_write8  out_port_d;    /* 8-bit output */
220   devcb_resolved_write8  out_port_e;    /* 8-bit output */
221   devcb_resolved_write8  out_port_f;    /* 8-bit output */
222   devcb_resolved_write8  out_port_g;    /* 8-bit output */
223   devcb_resolved_write8  out_port_j;    /* 8-bit output */
224   devcb_resolved_write8  out_port_k;    /* 8-bit output */
225   devcb_resolved_write8  out_port_m;    /* 8-bit output */
226
227   devcb_resolved_read8   in_port_a;     /* 8-bit input */
228   devcb_resolved_read8   in_port_b;     /* 8-bit input */
229   devcb_resolved_read8   in_port_c;     /* 8-bit input */
230   devcb_resolved_read8   in_port_d;     /* 8-bit input */
231   devcb_resolved_read8   in_port_e;     /* 8-bit input */
232   devcb_resolved_read8   in_port_f;     /* 8-bit input */
233   devcb_resolved_read8   in_port_g;     /* 8-bit input */
234   devcb_resolved_read8   in_port_j;     /* 8-bit input */
235   devcb_resolved_read8   in_port_k;     /* 8-bit input */
236   devcb_resolved_read8   in_port_m;     /* 8-bit input */
237
238   devcb_resolved_write8  out_pwm;       /* 1-bit output */
239
240   devcb_resolved_write16 out_spim;      /* 16-bit output */
241   devcb_resolved_read16  in_spim;       /* 16-bit input */
242};
243
244#define SCR_BETO                0x80
245#define SCR_WPV                 0x40
246#define SCR_PRV                 0x20
247#define SCR_BETEN               0x10
248#define SCR_SO                  0x08
249#define SCR_DMAP                0x04
250#define SCR_WDTH8               0x01
251
252#define ICR_POL6                0x0100
253#define ICR_POL3                0x0200
254#define ICR_POL2                0x0400
255#define ICR_POL1                0x0800
256#define ICR_ET6                 0x1000
257#define ICR_ET3                 0x2000
258#define ICR_ET2                 0x4000
259#define ICR_ET1                 0x8000
260
261#define INT_SPIM                0x000001
262#define INT_TIMER2              0x000002
263#define INT_UART                0x000004
264#define INT_WDT                 0x000008
265#define INT_RTC                 0x000010
266#define INT_RESERVED            0x000020
267#define INT_KB                  0x000040
268#define INT_PWM                 0x000080
269#define INT_INT0                0x000100
270#define INT_INT1                0x000200
271#define INT_INT2                0x000400
272#define INT_INT3                0x000800
273#define INT_INT4                0x001000
274#define INT_INT5                0x002000
275#define INT_INT6                0x004000
276#define INT_INT7                0x008000
277#define INT_KBDINTS             0x00ff00
278#define INT_IRQ1                0x010000
279#define INT_IRQ2                0x020000
280#define INT_IRQ3                0x040000
281#define INT_IRQ6                0x080000
282#define INT_PEN                 0x100000
283#define INT_SPIS                0x200000
284#define INT_TIMER1              0x400000
285#define INT_IRQ7                0x800000
286
287#define INT_M68K_LINE1          (INT_IRQ1)
288#define INT_M68K_LINE2          (INT_IRQ2)
289#define INT_M68K_LINE3          (INT_IRQ3)
290#define INT_M68K_LINE4          (INT_INT0 | INT_INT1 | INT_INT2 | INT_INT3 | INT_INT4 | INT_INT5 | INT_INT6 | INT_INT7 | \
291                           INT_PWM | INT_KB | INT_RTC | INT_WDT | INT_UART | INT_TIMER2 | INT_SPIM)
292#define INT_M68K_LINE5          (INT_PEN)
293#define INT_M68K_LINE6          (INT_IRQ6 | INT_TIMER1 | INT_SPIS)
294#define INT_M68K_LINE7          (INT_IRQ7)
295#define INT_M68K_LINE67         (INT_M68K_LINE6 | INT_M68K_LINE7)
296#define INT_M68K_LINE567        (INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7)
297#define INT_M68K_LINE4567       (INT_M68K_LINE4 | INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7)
298#define INT_M68K_LINE34567      (INT_M68K_LINE3 | INT_M68K_LINE4 | INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7)
299#define INT_M68K_LINE234567     (INT_M68K_LINE2 | INT_M68K_LINE3 | INT_M68K_LINE4 | INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7)
300
301#define INT_IRQ1_SHIFT          0x000001
302#define INT_IRQ2_SHIFT          0x000002
303#define INT_IRQ3_SHIFT          0x000004
304#define INT_IRQ6_SHIFT          0x000008
305#define INT_PEN_SHIFT           0x000010
306#define INT_SPIS_SHIFT          0x000020
307#define INT_TIMER1_SHIFT        0x000040
308#define INT_IRQ7_SHIFT          0x000080
309
310#define INT_ACTIVE              1
311#define INT_INACTIVE            0
312
313#define GRPBASE_BASE_ADDR       0xfff0
314#define GRPBASE_VALID           0x0001
315
316#define GRPMASK_BASE_MASK       0xfff0
317
318#define CSAB_COMPARE            0xff000000
319#define CSAB_BSW                0x00010000
320#define CSAB_MASK               0x0000ff00
321#define CSAB_RO                 0x00000008
322#define CSAB_WAIT               0x00000007
323
324#define CSCD_COMPARE            0xfff00000
325#define CSCD_BSW                0x00010000
326#define CSCD_MASK               0x0000fff0
327#define CSCD_RO                 0x00000008
328#define CSCD_WAIT               0x00000007
329
330#define PLLCR_PIXCLK_SEL        0x3800
331#define PLLCR_PIXCLK_SEL_DIV2       0x0000
332#define PLLCR_PIXCLK_SEL_DIV4       0x0800
333#define PLLCR_PIXCLK_SEL_DIV8       0x1000
334#define PLLCR_PIXCLK_SEL_DIV16      0x1800
335#define PLLCR_PIXCLK_SEL_DIV1_0     0x2000
336#define PLLCR_PIXCLK_SEL_DIV1_1     0x2800
337#define PLLCR_PIXCLK_SEL_DIV1_2     0x3000
338#define PLLCR_PIXCLK_SEL_DIV1_3     0x3800
339#define PLLCR_SYSCLK_SEL        0x0700
340#define PLLCR_SYSCLK_SEL_DIV2       0x0000
341#define PLLCR_SYSCLK_SEL_DIV4       0x0100
342#define PLLCR_SYSCLK_SEL_DIV8       0x0200
343#define PLLCR_SYSCLK_SEL_DIV16      0x0300
344#define PLLCR_SYSCLK_SEL_DIV1_0     0x0400
345#define PLLCR_SYSCLK_SEL_DIV1_1     0x0500
346#define PLLCR_SYSCLK_SEL_DIV1_2     0x0600
347#define PLLCR_SYSCLK_SEL_DIV1_3     0x0700
348#define PLLCR_CLKEN             0x0010
349#define PLLCR_DISPLL            0x0008
350
351#define PLLFSR_CLK32            0x8000
352#define PLLFSR_PROT             0x4000
353#define PLLFSR_QCNT             0x0f00
354#define PLLFSR_PCNT             0x00ff
355
356#define PCTLR_PC_EN             0x80
357#define PCTLR_STOP              0x40
358#define PCTLR_WIDTH             0x1f
359
360#define CXP_CC                  0xc000
361#define CXP_CC_XLU                  0x0000
362#define CXP_CC_BLACK                0x4000
363#define CXP_CC_INVERSE              0x8000
364#define CXP_CC_INVALID              0xc000
365#define CXP_MASK                0x03ff
366
367#define CYP_MASK                0x01ff
368
369#define CWCH_CW                 0x1f00
370#define CWCH_CH                 0x001f
371
372#define BLKC_BKEN               0x80
373#define BLKC_BD                 0x7f
374
375#define LPICF_PBSIZ             0x06
376#define LPICF_PBSIZ_1               0x00
377#define LPICF_PBSIZ_2               0x02
378#define LPICF_PBSIZ_4               0x04
379#define LPICF_PBSIZ_INVALID         0x06
380
381#define LPOLCF_LCKPOL           0x08
382#define LPOLCF_FLMPOL           0x04
383#define LPOLCF_LPPOL            0x02
384#define LPOLCF_PIXPOL           0x01
385
386#define LACDRC_MASK             0x0f
387
388#define LPXCD_MASK              0x3f
389
390#define LCKCON_LCDC_EN          0x80
391#define LCKCON_LCDON            0x80
392#define LCKCON_DMA16            0x40
393#define LCKCON_WS               0x30
394#define LCKCON_WS_1                 0x00
395#define LCKCON_WS_2                 0x10
396#define LCKCON_WS_3                 0x20
397#define LCKCON_WS_4                 0x30
398#define LCKCON_DWIDTH           0x02
399#define LCKCON_PCDS             0x01
400
401#define LBAR_MASK               0x7f
402
403#define LPOSR_BOS               0x08
404#define LPOSR_POS               0x07
405
406#define LFRCM_XMOD              0xf0
407#define LFRCM_YMOD              0x0f
408
409#define LGPMR_PAL1              0x7000
410#define LGPMR_PAL0              0x0700
411#define LGPMR_PAL3              0x0070
412#define LGPMR_PAL2              0x0007
413
414#define RTCHMSR_HOURS           0x1f000000
415#define RTCHMSR_MINUTES         0x003f0000
416#define RTCHMSR_SECONDS         0x0000003f
417
418#define RTCCTL_38_4             0x0020
419#define RTCCTL_ENABLE           0x0080
420
421#define RTCINT_STOPWATCH        0x0001
422#define RTCINT_MINUTE           0x0002
423#define RTCINT_ALARM            0x0004
424#define RTCINT_DAY              0x0008
425#define RTCINT_SECOND           0x0010
426
427#define RTCSTPWTCH_MASK         0x003f
428
429#define TCTL_TEN                0x0001
430#define TCTL_TEN_ENABLE             0x0001
431#define TCTL_CLKSOURCE          0x000e
432#define TCTL_CLKSOURCE_STOP         0x0000
433#define TCTL_CLKSOURCE_SYSCLK       0x0002
434#define TCTL_CLKSOURCE_SYSCLK16     0x0004
435#define TCTL_CLKSOURCE_TIN          0x0006
436#define TCTL_CLKSOURCE_32KHZ4       0x0008
437#define TCTL_CLKSOURCE_32KHZ5       0x000a
438#define TCTL_CLKSOURCE_32KHZ6       0x000c
439#define TCTL_CLKSOURCE_32KHZ7       0x000e
440#define TCTL_IRQEN              0x0010
441#define TCTL_IRQEN_ENABLE           0x0010
442#define TCTL_OM                 0x0020
443#define TCTL_OM_ACTIVELOW           0x0000
444#define TCTL_OM_TOGGLE              0x0020
445#define TCTL_CAPTURE            0x00c0
446#define TCTL_CAPTURE_NOINT          0x0000
447#define TCTL_CAPTURE_RISING         0x0040
448#define TCTL_CAPTURE_FALLING        0x0080
449#define TCTL_CAPTURE_BOTH           0x00c0
450#define TCTL_FRR                0x0100
451#define TCTL_FRR_RESTART            0x0000
452#define TCTL_FRR_FREERUN            0x0100
453
454#define TSTAT_COMP              0x0001
455#define TSTAT_CAPT              0x0002
456
457#define WCTLR_WDRST             0x0008
458#define WCTLR_LOCK              0x0004
459#define WCTLR_FI                0x0002
460#define WCTLR_WDEN              0x0001
461
462#define USTCNT_UART_EN          0x8000
463#define USTCNT_RX_EN            0x4000
464#define USTCNT_TX_EN            0x2000
465#define USTCNT_RX_CLK_CONT      0x1000
466#define USTCNT_PARITY_EN        0x0800
467#define USTCNT_ODD_EVEN         0x0400
468#define USTCNT_STOP_BITS        0x0200
469#define USTCNT_8_7              0x0100
470#define USTCNT_GPIO_DELTA_EN    0x0080
471#define USTCNT_CTS_DELTA_EN     0x0040
472#define USTCNT_RX_FULL_EN       0x0020
473#define USTCNT_RX_HALF_EN       0x0010
474#define USTCNT_RX_RDY_EN        0x0008
475#define USTCNT_TX_EMPTY_EN      0x0004
476#define USTCNT_TX_HALF_EN       0x0002
477#define USTCNT_TX_AVAIL_EN      0x0001
478
479#define UBAUD_GPIO_DELTA        0x8000
480#define UBAUD_GPIO              0x4000
481#define UBAUD_GPIO_DIR          0x2000
482#define UBAUD_GPIO_SRC          0x1000
483#define UBAUD_BAUD_SRC          0x0800
484#define UBAUD_DIVIDE            0x0700
485#define UBAUD_DIVIDE_1              0x0000
486#define UBAUD_DIVIDE_2              0x0100
487#define UBAUD_DIVIDE_4              0x0200
488#define UBAUD_DIVIDE_8              0x0300
489#define UBAUD_DIVIDE_16             0x0400
490#define UBAUD_DIVIDE_32             0x0500
491#define UBAUD_DIVIDE_64             0x0600
492#define UBAUD_DIVIDE_128            0x0700
493#define UBAUD_PRESCALER         0x00ff
494
495#define URX_FIFO_FULL           0x8000
496#define URX_FIFO_HALF           0x4000
497#define URX_DATA_READY          0x2000
498#define URX_OVRUN               0x0800
499#define URX_FRAME_ERROR         0x0400
500#define URX_BREAK               0x0200
501#define URX_PARITY_ERROR        0x0100
502
503#define UTX_FIFO_EMPTY          0x8000
504#define UTX_FIFO_HALF           0x4000
505#define UTX_TX_AVAIL            0x2000
506#define UTX_SEND_BREAK          0x1000
507#define UTX_IGNORE_CTS          0x0800
508#define UTX_CTS_STATUS          0x0200
509#define UTX_CTS_DELTA           0x0100
510
511#define UMISC_CLK_SRC           0x4000
512#define UMISC_FORCE_PERR        0x2000
513#define UMISC_LOOP              0x1000
514#define UMISC_RTS_CONT          0x0080
515#define UMISC_RTS               0x0040
516#define UMISC_IRDA_ENABLE       0x0020
517#define UMISC_IRDA_LOOP         0x0010
518
519#define SPIS_SPIS_IRQ           0x8000
520#define SPIS_IRQEN              0x4000
521#define SPIS_ENPOL              0x2000
522#define SPIS_DATA_RDY           0x1000
523#define SPIS_OVRWR              0x0800
524#define SPIS_PHA                0x0400
525#define SPIS_POL                0x0200
526#define SPIS_SPISEN             0x0100
527
528#define SPIM_CLOCK_COUNT        0x000f
529#define SPIM_POL                0x0010
530#define SPIM_POL_HIGH               0x0000
531#define SPIM_POL_LOW                0x0010
532#define SPIM_PHA                0x0020
533#define SPIM_PHA_NORMAL             0x0000
534#define SPIM_PHA_OPPOSITE           0x0020
535#define SPIM_IRQEN              0x0040
536#define SPIM_SPIMIRQ            0x0080
537#define SPIM_XCH                0x0100
538#define SPIM_XCH_IDLE               0x0000
539#define SPIM_XCH_INIT               0x0100
540#define SPIM_SPMEN              0x0200
541#define SPIM_SPMEN_DISABLE          0x0000
542#define SPIM_SPMEN_ENABLE           0x0200
543#define SPIM_RATE               0xe000
544#define SPIM_RATE_4                 0x0000
545#define SPIM_RATE_8                 0x2000
546#define SPIM_RATE_16                0x4000
547#define SPIM_RATE_32                0x6000
548#define SPIM_RATE_64                0x8000
549#define SPIM_RATE_128               0xa000
550#define SPIM_RATE_256               0xc000
551#define SPIM_RATE_512               0xe000
552
553#define PWMC_PWMIRQ             0x8000
554#define PWMC_IRQEN              0x4000
555#define PWMC_LOAD               0x0100
556#define PWMC_PIN                0x0080
557#define PWMC_POL                0x0040
558#define PWMC_PWMEN              0x0010
559#define PWMC_CLKSEL             0x0007
560
561INLINE mc68328_t* mc68328_get_safe_token( device_t *device )
562{
563   assert( device != NULL );
564   assert( device->type() == MC68328 );
565   return (mc68328_t*) downcast<mc68328_device *>(device)->token();
566}
567
568#endif // __MC68328_PRIVATE_H_
Property changes on: trunk/src/emu/machine/mc68328.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/74145.c
r0r21685
1/*****************************************************************************
2 *
3 * machine/74145.c
4 *
5 * BCD-to-Decimal decoder
6 *
7 *        __ __
8 *     0-|  v  |-VCC
9 *     1-|     |-A
10 *     2-|     |-B
11 *     3-|     |-C
12 *     4-|     |-D
13 *     5-|     |-9
14 *     6-|     |-8
15 *   GND-|_____|-7
16 *
17 *
18 * Truth table
19 *  _______________________________
20 * | Inputs  | Outputs             |
21 * | D C B A | 0 1 2 3 4 5 6 7 8 9 |
22 * |-------------------------------|
23 * | L L L L | L H H H H H H H H H |
24 * | L L L H | H L H H H H H H H H |
25 * | L L H L | H H L H H H H H H H |
26 * | L L H H | H H H L H H H H H H |
27 * | L H L L | H H H H L H H H H H |
28 * |-------------------------------|
29 * | L H L H | H H H H H L H H H H |
30 * | L H H L | H H H H H H L H H H |
31 * | L H H H | H H H H H H H L H H |
32 * | H L L L | H H H H H H H H L H |
33 * | H L L H | H H H H H H H H H L |
34 * |-------------------------------|
35 * | H L H L | H H H H H H H H H H |
36 * | H L H H | H H H H H H H H H H |
37 * | H H L L | H H H H H H H H H H |
38 * | H H L H | H H H H H H H H H H |
39 * | H H H L | H H H H H H H H H H |
40 * | H H H H | H H H H H H H H H H |
41 *  -------------------------------
42 *
43 ****************************************************************************/
44
45#include "emu.h"
46#include "74145.h"
47#include "coreutil.h"
48
49/*****************************************************************************
50    GLOBAL VARIABLES
51*****************************************************************************/
52
53const ttl74145_interface default_ttl74145 =
54{
55   DEVCB_NULL,
56   DEVCB_NULL,
57   DEVCB_NULL,
58   DEVCB_NULL,
59   DEVCB_NULL,
60   DEVCB_NULL,
61   DEVCB_NULL,
62   DEVCB_NULL,
63   DEVCB_NULL,
64   DEVCB_NULL
65};
66
67
68const device_type TTL74145 = &device_creator<ttl74145_device>;
69
70/***************************************************************************
71    DEVICE INTERFACE
72***************************************************************************/
73//-------------------------------------------------
74//  ttl74145_device - constructor
75//-------------------------------------------------
76
77ttl74145_device::ttl74145_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
78   : device_t(mconfig, TTL74145, "TTL74145", tag, owner, clock)
79   , m_number(0)
80{
81}
82
83
84//-------------------------------------------------
85//  device_start - device-specific startup
86//-------------------------------------------------
87
88void ttl74145_device::device_start()
89{
90   /* resolve callbacks */
91   m_output_line_0_func.resolve(m_output_line_0_cb, *this);
92   m_output_line_1_func.resolve(m_output_line_1_cb, *this);
93   m_output_line_2_func.resolve(m_output_line_2_cb, *this);
94   m_output_line_3_func.resolve(m_output_line_3_cb, *this);
95   m_output_line_4_func.resolve(m_output_line_4_cb, *this);
96   m_output_line_5_func.resolve(m_output_line_5_cb, *this);
97   m_output_line_6_func.resolve(m_output_line_6_cb, *this);
98   m_output_line_7_func.resolve(m_output_line_7_cb, *this);
99   m_output_line_8_func.resolve(m_output_line_8_cb, *this);
100   m_output_line_9_func.resolve(m_output_line_9_cb, *this);
101
102   // register for state saving
103   save_item(NAME(m_number));
104}
105
106//-------------------------------------------------
107//  device_config_complete - perform any
108//  operations now that the configuration is
109//  complete
110//-------------------------------------------------
111
112void ttl74145_device::device_config_complete()
113{
114   // inherit a copy of the static data
115   const ttl74145_interface *intf = reinterpret_cast<const ttl74145_interface *>(static_config());
116   if (intf != NULL)
117      *static_cast<ttl74145_interface *>(this) = *intf;
118
119   // or initialize to defaults if none provided
120   else
121   {
122      memset(&m_output_line_0_cb, 0, sizeof(m_output_line_0_cb));
123      memset(&m_output_line_1_cb, 0, sizeof(m_output_line_1_cb));
124      memset(&m_output_line_2_cb, 0, sizeof(m_output_line_2_cb));
125      memset(&m_output_line_3_cb, 0, sizeof(m_output_line_3_cb));
126      memset(&m_output_line_4_cb, 0, sizeof(m_output_line_4_cb));
127      memset(&m_output_line_5_cb, 0, sizeof(m_output_line_5_cb));
128      memset(&m_output_line_6_cb, 0, sizeof(m_output_line_6_cb));
129      memset(&m_output_line_7_cb, 0, sizeof(m_output_line_7_cb));
130      memset(&m_output_line_8_cb, 0, sizeof(m_output_line_8_cb));
131      memset(&m_output_line_9_cb, 0, sizeof(m_output_line_9_cb));
132   }
133}
134
135//-------------------------------------------------
136//  device_start - device-specific reset
137//-------------------------------------------------
138
139void ttl74145_device::device_reset()
140{
141   m_number = 0;
142}
143
144/***************************************************************************
145    IMPLEMENTATION
146***************************************************************************/
147
148void ttl74145_device::write(UINT8 data)
149{
150   /* decode number */
151   UINT16 new_number = bcd_2_dec(data & 0x0f);
152
153   /* call output callbacks if the number changed */
154   if (new_number != m_number)
155   {
156      m_output_line_0_func(new_number == 0);
157      m_output_line_1_func(new_number == 1);
158      m_output_line_2_func(new_number == 2);
159      m_output_line_3_func(new_number == 3);
160      m_output_line_4_func(new_number == 4);
161      m_output_line_5_func(new_number == 5);
162      m_output_line_6_func(new_number == 6);
163      m_output_line_7_func(new_number == 7);
164      m_output_line_8_func(new_number == 8);
165      m_output_line_9_func(new_number == 9);
166   }
167
168   /* update state */
169   m_number = new_number;
170}
171
172
173UINT16 ttl74145_device::read()
174{
175   return (1 << m_number) & 0x3ff;
176}
Property changes on: trunk/src/emu/machine/74145.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/74145.h
r0r21685
1/***************************************************************************
2
3    TTL74145
4
5    BCD-to-Decimal decoder
6
7***************************************************************************/
8
9#ifndef __TTL74145_H__
10#define __TTL74145_H__
11
12//**************************************************************************
13//  INTERFACE CONFIGURATION MACROS
14//**************************************************************************
15#define MCFG_TTL74145_ADD(_tag, _intf) \
16   MCFG_DEVICE_ADD(_tag, TTL74145, 0) \
17   MCFG_DEVICE_CONFIG(_intf)
18
19
20//**************************************************************************
21//  TYPE DEFINITIONS
22//**************************************************************************
23
24// ======================> ttl74145_interface
25
26struct ttl74145_interface
27{
28   devcb_write_line m_output_line_0_cb;
29   devcb_write_line m_output_line_1_cb;
30   devcb_write_line m_output_line_2_cb;
31   devcb_write_line m_output_line_3_cb;
32   devcb_write_line m_output_line_4_cb;
33   devcb_write_line m_output_line_5_cb;
34   devcb_write_line m_output_line_6_cb;
35   devcb_write_line m_output_line_7_cb;
36   devcb_write_line m_output_line_8_cb;
37   devcb_write_line m_output_line_9_cb;
38};
39
40// ======================> ttl74145_device
41
42class ttl74145_device :  public device_t,
43                  public ttl74145_interface
44{
45public:
46   // construction/destruction
47   ttl74145_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
48
49   UINT16 read();
50   void write(UINT8 data);
51protected:
52   // device-level overrides
53   virtual void device_start();
54   virtual void device_reset();
55   virtual void device_config_complete();
56
57private:
58   devcb_resolved_write_line   m_output_line_0_func;
59   devcb_resolved_write_line   m_output_line_1_func;
60   devcb_resolved_write_line   m_output_line_2_func;
61   devcb_resolved_write_line   m_output_line_3_func;
62   devcb_resolved_write_line   m_output_line_4_func;
63   devcb_resolved_write_line   m_output_line_5_func;
64   devcb_resolved_write_line   m_output_line_6_func;
65   devcb_resolved_write_line   m_output_line_7_func;
66   devcb_resolved_write_line   m_output_line_8_func;
67   devcb_resolved_write_line   m_output_line_9_func;
68
69   /* decoded number */
70   UINT16 m_number;
71};
72
73// device type definition
74extern const device_type TTL74145;
75
76//**************************************************************************
77//  DEFAULT INTERFACES
78//**************************************************************************
79
80extern const ttl74145_interface default_ttl74145;
81
82
83#endif /* TTL74145 */
Property changes on: trunk/src/emu/machine/74145.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/mc6854.c
r0r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2006
4
5  Motorola 6854 emulation.
6
7  The MC6854 chip is an Advanced Data-Link Controller (ADLC).
8  It provides a high-level network interface that can transimit frames with
9  arbitrary data and address length, and is compatible with the following
10  standards:
11  - ADCCP (Advanced Data Communication Control Procedure)
12  - HDLC  (High-Level Data-Link Control)
13  - SDLC  (Synchronous Data-Link Control)
14  It is designed to be interfaced with a M6800-family CPU.
15
16  It is used in the "Nano-network" extension of the Thomson computers to
17  link up to 32 computers at 500 Kbps.
18  Many networks involving one PC server and several MO5 or TO7/70 computers
19  were build in French schools in the 1980's to teach computer science.
20
21  TODO:
22  - CRC
23  - DMA mode
24  - loop mode
25  - status prioritization
26  - NRZI vs. NRZ coding
27  - FD output
28
29**********************************************************************/
30
31
32#include "emu.h"
33#include "mc6854.h"
34
35
36
37/******************* parameters ******************/
38
39
40
41#define VERBOSE 0
42
43
44#define MAX_FRAME_LENGTH 65536
45/* arbitrary value, you may need to enlarge it if you get truncated frames */
46
47#define FIFO_SIZE 3
48/* hardcoded size of the 6854 FIFO (this is a hardware limit) */
49
50#define FLAG 0x7e
51/* flag value, as defined by HDLC protocol: 01111110 */
52
53#define BIT_LENGTH attotime::from_hz( 500000 )
54
55
56
57/******************* internal chip data structure ******************/
58
59
60struct mc6854_t
61{
62   devcb_resolved_write_line   out_irq_func;
63   devcb_resolved_read_line    in_rxd_func;
64   devcb_resolved_write_line   out_txd_func;
65   devcb_resolved_write_line   out_rts_func;
66   devcb_resolved_write_line   out_dtr_func;
67
68   /* interface */
69   const mc6854_interface* iface;
70
71   /* registers */
72   UINT8 cr1, cr2, cr3, cr4; /* control registers */
73   UINT8 sr1, sr2;           /* status registers */
74
75   UINT8 cts, dcd;
76
77   /* transmit state */
78   UINT8  tstate;
79   UINT16 tfifo[FIFO_SIZE];  /* X x 8-bit FIFO + full & last marker bits */
80   UINT8  tones;             /* counter for zero-insertion */
81   emu_timer *ttimer;       /* when to ask for more data */
82
83   /* receive state */
84   UINT8  rstate;
85   UINT32 rreg;              /* shift register */
86   UINT8  rones;             /* count '1 bits */
87   UINT8  rsize;             /* bits in the shift register */
88   UINT16 rfifo[FIFO_SIZE];  /* X x 8-bit FIFO + full & addr marker bits */
89
90   /* frame-based interface*/
91   UINT8  frame[MAX_FRAME_LENGTH];
92   UINT32 flen, fpos;
93
94};
95
96/* meaning of tstate / rtate:
97   0 = idle / waiting for frame flag
98   1 = flag sync
99   2 = 8-bit address field(s)
100   3-4 = 8-bit control field(s)
101   5 = 8-bit logical control field(s)
102   6 = variable-length data field(s)
103*/
104
105
106
107/******************* utility function and macros ********************/
108
109
110
111#define LOG(x)  do { if (VERBOSE) logerror x; } while (0)
112
113
114
115/* control register 1 */
116
117#define AC ( mc6854->cr1 & 1 )
118#define FCTDRA ( mc6854->cr2 & 8 )
119/* extra register select bits */
120
121#define RRESET ( mc6854->cr1 & 0x40 )
122#define TRESET ( mc6854->cr1 & 0x80 )
123/* transmit / reset condition */
124
125#define RIE ( mc6854->cr1 & 2 )
126#define TIE ( mc6854->cr1 & 4 )
127/* interrupt enable */
128
129#define DISCONTINUE ( mc6854->cr1 & 0x20 )
130/* discontinue received frame */
131
132
133
134/* control register 2 */
135
136#define PSE ( mc6854->cr2 & 1 )
137/* prioritize status bits (TODO) */
138
139#define TWOBYTES ( mc6854->cr2 & 2 )
140/* two-bytes mode */
141
142#define FMIDLE ( mc6854->cr2 & 4 )
143/* flag time fill (vs. mark idle) */
144
145#define TLAST ( mc6854->cr2 & 0x10 )
146/* transmit last byte of frame */
147
148#define RTS ( mc6854->cr2 & 0x80 )
149/* request-to-send */
150
151
152
153/* control register 3 */
154
155#define LCF ( mc6854->cr3 & 1 )
156/* logical control field select */
157
158#define CEX ( mc6854->cr3 & 2 )
159/* control field is 16 bits instead of 8 */
160
161#define AEX ( mc6854->cr3 & 4 )
162/* extended address mode (vs normal 8-bit address mode) */
163
164#define IDL0 ( mc6854->cr3 & 8 )
165/* idle condition begins with a '0' instead of a '1" */
166
167#define FDSE ( mc6854->cr3 & 0x10 )
168/* enable the flag detect status in SR1 */
169
170#define LOOP ( mc6854->cr3 & 0x20 )
171/* loop mode */
172
173#define TST ( mc6854->cr3 & 0x40 )
174/* test mode (or go active on poll) */
175
176#define DTR ( mc6854->cr3 & 0x80 )
177/* data-transmit-ready (or loop on-line control) */
178
179
180
181/* control register 4 */
182
183#define TWOINTER ( mc6854->cr4 & 1 )
184/* both an openning and a closing inter-frame are sent */
185
186static const int word_length[4] = { 5, 6, 7, 8 };
187#define TWL word_length[ ( mc6854->cr4 >> 1 ) & 3 ]
188#define RWL word_length[ ( mc6854->cr4 >> 3 ) & 3 ]
189/* transmit / receive word length */
190
191#define ABT ( mc6854->cr4 & 0x20 )
192/* aborts */
193
194#define ABTEX ( mc6854->cr4 & 0x40 )
195/* abort generates 16 '1' bits instead of 8 */
196
197#define NRZ ( mc6854->cr4 & 0x80 )
198/* zero complement / non-zero complement data format */
199
200
201
202/* status register 1 */
203#define RDA  0x01  /* receiver data available */
204#define S2RQ 0x02  /* status register #2 read request */
205#define FD   0x04  /* flag detect */
206#define CTS  0x10  /* clear-to-send */
207#define TU   0x20  /* transmitter underrun */
208#define TDRA 0x40  /* transmitter data register available */
209#define IRQ  0x80  /* interrupt request */
210
211
212/* status register 2 */
213#define AP    0x01  /* address present */
214#define FV    0x02  /* frame valid */
215#define RIDLE 0x04  /* receiver idle */
216#define RABT  0x08  /* receiver abort */
217#define ERR   0x10  /* invalid frame error */
218#define DCD   0x20  /* data carrier detect (ignored) */
219#define OVRN  0x40  /* receiver overrun */
220#define RDA2  0x80  /* copy of RDA */
221
222
223
224INLINE mc6854_t* get_safe_token( device_t *device )
225{
226   assert( device != NULL );
227   assert( device->type() == MC6854 );
228   return (mc6854_t*) downcast<mc6854_device *>(device)->token();
229}
230
231
232/*********************** transmit ***********************/
233
234
235
236/* MC6854 fills bit queue */
237static void mc6854_send_bits( device_t *device, UINT32 data, int len, int zi )
238{
239   mc6854_t* mc6854 = get_safe_token( device );
240   attotime expire;
241   int i;
242   if ( zi )
243   {
244      /* zero-insertion mode */
245      UINT32 d = 0;
246      int l = 0;
247      for ( i = 0; i < len; i++, data >>= 1, l++ )
248      {
249         if ( data & 1 )
250         {
251            d |= 1 << l;
252            mc6854->tones++;
253            if ( mc6854->tones == 5 )
254            {
255               /* insert a '0' after 5 consecutive '1" */
256               mc6854->tones = 0;
257               l++;
258            }
259         }
260         else
261            mc6854->tones = 0;
262      }
263      data = d;
264      len = l;
265   }
266   else
267      mc6854->tones = 0;
268
269   /* send bits */
270   if ( !mc6854->out_txd_func.isnull() )
271   {
272      for ( i = 0; i < len; i++, data >>= 1 )
273         mc6854->out_txd_func( data & 1 );
274   }
275
276   /* schedule when to ask the MC6854 for more bits */
277   expire = mc6854->ttimer ->remaining( );
278   if ( expire== attotime::never )
279      expire = attotime::zero;
280   mc6854->ttimer->reset( expire + (BIT_LENGTH * len));
281}
282
283
284
285/* CPU push -> tfifo[0] -> ... -> tfifo[FIFO_SIZE-1] -> pop */
286static void mc6854_tfifo_push( device_t *device, UINT8 data )
287{
288   mc6854_t* mc6854 = get_safe_token( device );
289   int i;
290
291   if ( TRESET )
292      return;
293
294   /* push towards the rightmost free entry */
295   for ( i = FIFO_SIZE - 1; i >= 0; i-- )
296   {
297      if ( ! ( mc6854->tfifo[ i ] & 0x100 ) )
298         break;
299   }
300
301   if ( i >= 0 )
302      mc6854->tfifo[ i ] = data | 0x100;
303   else
304      logerror( "%f mc6854_tfifo_push: FIFO overrun\n", device->machine().time().as_double() );
305
306   /* start frame, if needed */
307   if ( ! mc6854->tstate )
308   {
309      LOG(( "%f mc6854_tfifo_push: start frame\n", device->machine().time().as_double() ));
310      mc6854->tstate = 2;
311      mc6854_send_bits( device, FLAG, 8, 0 );
312   }
313}
314
315
316
317/* CPU asks for normal frame termination */
318static void mc6854_tfifo_terminate( device_t *device )
319{
320   mc6854_t* mc6854 = get_safe_token( device );
321
322   /* mark most recently pushed byte as the last one of the frame */
323   int i;
324   for ( i = 0; i < FIFO_SIZE; i++ )
325   {
326      if ( mc6854->tfifo[ i ] & 0x100 )
327      {
328         mc6854->tfifo[ i ] |= 0x200;
329         break;
330      }
331   }
332}
333
334
335
336/* call-back to refill the bit-stream from the FIFO */
337static TIMER_CALLBACK(mc6854_tfifo_cb)
338{
339   device_t* device = (device_t*) ptr;
340   mc6854_t* mc6854 = get_safe_token( device );
341   int i, data = mc6854->tfifo[ FIFO_SIZE - 1 ];
342
343   if ( ! mc6854->tstate )
344      return;
345
346   /* shift FIFO to the right */
347   for ( i = FIFO_SIZE - 1; i > 0; i-- )
348      mc6854->tfifo[ i ] = mc6854->tfifo[ i - 1 ];
349   mc6854->tfifo[ 0 ] = 0;
350
351   if ( data & 0x100 )
352   {
353      /* got data */
354
355      int blen = 8;
356
357      switch ( mc6854->tstate )
358      {
359      case 2: /* 8-bit address field */
360         if ( ( data & 1 ) || ( ! AEX ) )
361            mc6854->tstate = 3;
362         LOG(( "%f mc6854_tfifo_cb: address field $%02X\n", machine.time().as_double(), data & 0xff ));
363         break;
364
365      case 3: /* 8-bit control field */
366         if ( CEX )
367            mc6854->tstate = 4;
368         else if ( LCF )
369            mc6854->tstate = 5;
370         else
371            mc6854->tstate = 6;
372         LOG(( "%f mc6854_tfifo_cb: control field $%02X\n", machine.time().as_double(), data & 0xff ));
373         break;
374
375      case 4: /* 8-bit extended control field (optional) */
376         if ( LCF )
377            mc6854->tstate = 5;
378         else
379            mc6854->tstate = 6;
380         LOG(( "%f mc6854_tfifo_cb: control field $%02X\n", machine.time().as_double(), data & 0xff ));
381         break;
382
383      case 5: /* 8-bit logical control (optional) */
384         if ( ! ( data & 0x80 ) )
385            mc6854->tstate = 6;
386         LOG(( "%f mc6854_tfifo_cb: logical control field $%02X\n", machine.time().as_double(), data & 0xff ));
387         break;
388
389      case 6: /* variable-length data */
390         blen = TWL;
391         LOG(( "%f mc6854_tfifo_cb: data field $%02X, %i bits\n", machine.time().as_double(), data & 0xff, blen ));
392         break;
393
394      default:
395         LOG(( "%f mc6854_tfifo_cb: state=%i\n", machine.time().as_double(), mc6854->tstate));
396      }
397
398      if ( mc6854->flen < MAX_FRAME_LENGTH )
399         mc6854->frame[ mc6854->flen++ ] = data;
400      else
401         logerror( "mc6854_tfifo_cb: truncated frame, max=%i\n", MAX_FRAME_LENGTH );
402
403      mc6854_send_bits( device, data, blen, 1 );
404   }
405   else
406   {
407      /* data underrun => abort */
408      logerror( "%f mc6854_tfifo_cb: FIFO underrun\n", machine.time().as_double() );
409      mc6854->sr1 |= TU;
410      mc6854->tstate = 0;
411      mc6854_send_bits( device, 0xffff, ABTEX ? 16 : 8, 0 );
412      mc6854->flen = 0;
413   }
414
415   /* close frame, if needed */
416   if ( data & 0x200 )
417   {
418      int len = mc6854->flen;
419
420      LOG(( "%f mc6854_tfifo_cb: end frame\n", machine.time().as_double() ));
421      mc6854_send_bits( device, 0xdeadbeef, 16, 1 );  /* send check-sum: TODO */
422      mc6854_send_bits( device, FLAG, 8, 0 );         /* send closing flag */
423
424      if ( mc6854->tfifo[ FIFO_SIZE - 1 ] & 0x100 )
425      {
426         /* re-open frame asap */
427         LOG(( "%f mc6854_tfifo_cb: start frame\n", machine.time().as_double() ));
428         if ( TWOINTER )
429            mc6854_send_bits( device, FLAG, 8, 0 );
430      }
431      else
432         mc6854->tstate = 0;
433
434      mc6854->flen = 0;
435      if ( mc6854->iface->out_frame )
436         mc6854->iface->out_frame( device, mc6854->frame, len );
437   }
438}
439
440
441
442static void mc6854_tfifo_clear( device_t *device )
443{
444   mc6854_t* mc6854 = get_safe_token( device );
445   memset( mc6854->tfifo, 0, sizeof( mc6854->tfifo ) );
446   mc6854->tstate = 0;
447   mc6854->flen = 0;
448   mc6854->ttimer->reset(  );
449}
450
451
452
453/*********************** receive ***********************/
454
455
456
457/* MC6854 pushes a field in the FIFO */
458static void mc6854_rfifo_push( device_t *device, UINT8 d )
459{
460   mc6854_t* mc6854 = get_safe_token( device );
461   int i, blen = 8;
462   unsigned data = d;
463
464   switch ( mc6854->rstate )
465   {
466   case 0:
467   case 1:
468   case 2: /* 8-bit address field */
469      if ( ( data & 1 ) || ( ! AEX ) )
470         mc6854->rstate = 3;
471      else
472         mc6854->rstate = 2;
473      LOG(( "%f mc6854_rfifo_push: address field $%02X\n", device->machine().time().as_double(), data ));
474      data |= 0x400; /* address marker */
475      break;
476
477   case 3: /* 8-bit control field */
478      if ( CEX )
479         mc6854->rstate = 4;
480      else if ( LCF )
481         mc6854->rstate = 5;
482      else
483         mc6854->rstate = 6;
484      LOG(( "%f mc6854_rfifo_push: control field $%02X\n", device->machine().time().as_double(), data ));
485      break;
486
487   case 4: /* 8-bit extended control field (optional) */
488      if ( LCF )
489         mc6854->rstate = 5;
490      else
491         mc6854->rstate = 6;
492      LOG(( "%f mc6854_rfifo_push: control field $%02X\n", device->machine().time().as_double(), data ));
493      break;
494
495   case 5: /* 8-bit logical control (optional) */
496      if ( ! ( data & 0x80 ) )
497         mc6854->rstate = 6;
498      LOG(( "%f mc6854_rfifo_push: logical control field $%02X\n", device->machine().time().as_double(), data ));
499      break;
500
501   case 6: /* variable-length data */
502      blen = RWL;
503      data >>= 8 - blen;
504      LOG(( "%f mc6854_rfifo_push: data field $%02X, %i bits\n", device->machine().time().as_double(), data, blen ));
505      break;
506   }
507
508   /* no further FIFO fill until FV is cleared! */
509   if ( mc6854->sr2 & FV )
510   {
511      LOG(( "%f mc6854_rfifo_push: field not pushed\n", device->machine().time().as_double() ));
512      return;
513   }
514
515   data |= 0x100; /* entry full marker */
516
517   /* push towards the rightmost free entry */
518   for ( i = FIFO_SIZE - 1; i >= 0; i-- )
519   {
520      if ( ! ( mc6854->rfifo[ i ] & 0x100 ) )
521         break;
522   }
523
524   if ( i >= 0 )
525      mc6854->rfifo[ i ] = data | 0x100;
526   else
527   {
528      /* FIFO full */
529      mc6854->sr2 |= OVRN;
530      mc6854->rfifo[ 0 ] = data;
531      logerror( "%f mc6854_rfifo_push: FIFO overrun\n", device->machine().time().as_double() );
532   }
533
534   mc6854->rsize -= blen;
535}
536
537
538
539static void mc6854_rfifo_terminate( device_t *device )
540{
541   mc6854_t* mc6854 = get_safe_token( device );
542   /* mark most recently pushed byte as the last one of the frame */
543   int i;
544   for ( i = 0; i < FIFO_SIZE; i++ )
545   {
546      if ( mc6854->rfifo[ i ] & 0x100 )
547      {
548         mc6854->tfifo[ i ] |= 0x200;
549         break;
550      }
551
552   }
553
554   mc6854->flen = 0;
555   mc6854->rstate = 1;
556}
557
558
559
560/* CPU pops the FIFO */
561static UINT8 mc6854_rfifo_pop( device_t *device )
562{
563   mc6854_t* mc6854 = get_safe_token( device );
564   int i, data = mc6854->rfifo[ FIFO_SIZE - 1 ];
565
566   /* shift FIFO to the right */
567   for ( i = FIFO_SIZE - 1; i > 0; i -- )
568      mc6854->rfifo[ i ] = mc6854->rfifo[ i - 1 ];
569   mc6854->rfifo[ 0 ] = 0;
570
571   if ( mc6854->rfifo[ FIFO_SIZE - 1 ] & 0x200 )
572   {
573      /* last byte in frame */
574      mc6854->sr2 |= FV; /* TODO: check CRC & set ERR instead of FV if error*/
575   }
576
577   /* auto-refill in frame mode */
578   if ( mc6854->flen > 0 )
579   {
580      mc6854_rfifo_push( device, mc6854->frame[ mc6854->fpos++ ] );
581      if ( mc6854->fpos == mc6854->flen )
582         mc6854_rfifo_terminate( device );
583   }
584
585   return data;
586}
587
588
589/* MC6854 makes fields from bits */
590WRITE_LINE_DEVICE_HANDLER( mc6854_set_rx )
591{
592   mc6854_t* mc6854 = get_safe_token( device );
593   int fieldlen = ( mc6854->rstate < 6 ) ? 8 : RWL;
594
595   if ( RRESET || (mc6854->sr2 & DCD) )
596      return;
597
598   if ( state )
599   {
600      mc6854->rones++;
601      mc6854->rreg = (mc6854->rreg >> 1) | 0x80000000;
602      if ( mc6854->rones >= 8 )
603      {
604         /* abort */
605         mc6854->rstate = 0;
606         mc6854->rsize = 0;
607         if ( mc6854->rstate > 1 )
608         {
609            /* only in-frame abort */
610            mc6854->sr2 |= RABT;
611            LOG(( "%f mc6854_receive_bit: abort\n", device->machine().time().as_double() ));
612         }
613      }
614      else
615      {
616         mc6854->rsize++;
617         if ( mc6854->rstate && mc6854->rsize >= fieldlen + 24 )
618            mc6854_rfifo_push( device, mc6854->rreg );
619      }
620   }
621   else if ( mc6854->rones == 5 )
622   {
623      /* discards '0' inserted after 5 '1' */
624      mc6854->rones = 0;
625      return;
626   }
627   else if ( mc6854->rones == 6 )
628   {
629      /* flag */
630      if ( FDSE )
631         mc6854->sr1 |= FD;
632
633      if ( mc6854->rstate > 1 )
634      {
635         /* end of frame */
636         mc6854->rreg >>= 1;
637         mc6854->rsize++;
638         if ( mc6854->rsize >= fieldlen + 24 ) /* last field */
639            mc6854_rfifo_push( device, mc6854->rreg );
640         mc6854_rfifo_terminate( device );
641         LOG(( "%f mc6854_receive_bit: end of frame\n", device->machine().time().as_double() ));
642      }
643      mc6854->rones = 0;
644      mc6854->rstate = 1;
645      mc6854->rsize = 0;
646   } else
647   {
648      mc6854->rones = 0;
649      mc6854->rreg >>= 1;
650      mc6854->rsize++;
651      if ( mc6854->rstate && mc6854->rsize >= fieldlen + 24 )
652         mc6854_rfifo_push( device, mc6854->rreg );
653   }
654}
655
656
657
658static void mc6854_rfifo_clear( device_t *device )
659{
660   mc6854_t* mc6854 = get_safe_token( device );
661   memset( mc6854->rfifo, 0, sizeof( mc6854->rfifo ) );
662   mc6854->rstate = 0;
663   mc6854->rreg = 0;
664   mc6854->rsize = 0;
665   mc6854->rones = 0;
666   mc6854->flen = 0;
667}
668
669
670
671int mc6854_send_frame( device_t *device, UINT8* data, int len )
672{
673   mc6854_t* mc6854 = get_safe_token( device );
674   if ( mc6854->rstate > 1 || mc6854->tstate > 1 || RTS )
675      return -1; /* busy */
676
677   if ( len > MAX_FRAME_LENGTH )
678   {
679      logerror( "mc6854_send_frame: truncated frame, size=%i, max=%i\n", len, MAX_FRAME_LENGTH );
680      len = MAX_FRAME_LENGTH;
681   }
682   else if ( len < 2 )
683   {
684      logerror( "mc6854_send_frame: frame too short, size=%i, min=2\n", len );
685      len = 2;
686   }
687   memcpy( mc6854->frame, data, len );
688   if ( FDSE )
689      mc6854->sr1 |= FD;
690   mc6854->flen = len;
691   mc6854->fpos = 0;
692   mc6854_rfifo_push( device, mc6854->frame[ mc6854->fpos++ ] );
693   mc6854_rfifo_push( device, mc6854->frame[ mc6854->fpos++ ] );
694   if ( mc6854->fpos == mc6854->flen )
695      mc6854_rfifo_terminate( device );
696   return 0;
697}
698
699
700
701/************************** CPU interface ****************************/
702
703
704
705WRITE_LINE_DEVICE_HANDLER( mc6854_set_cts )
706{
707   mc6854_t* mc6854 = get_safe_token( device );
708   if ( ! mc6854->cts && state )
709      mc6854->sr1 |= CTS;
710   mc6854->cts = state;
711
712   if ( mc6854->cts )
713      mc6854->sr1 |= CTS;
714   else
715      mc6854->sr1 &= ~CTS;
716}
717
718
719
720WRITE_LINE_DEVICE_HANDLER( mc6854_set_dcd )
721{
722   mc6854_t* mc6854 = get_safe_token( device );
723   if ( ! mc6854->dcd && state )
724   {
725      mc6854->sr2 |= DCD;
726      /* partial reset */
727      mc6854->rstate = 0;
728      mc6854->rreg = 0;
729      mc6854->rsize = 0;
730      mc6854->rones = 0;
731   }
732   mc6854->dcd = state;
733}
734
735
736
737static void mc6854_update_sr2( mc6854_t* mc6854 )
738{
739   /* update RDA */
740   mc6854->sr2 |= RDA2;
741   if ( ! (mc6854->rfifo[ FIFO_SIZE - 1 ] & 0x100) )
742      mc6854->sr2 &= ~RDA2;
743   else if ( TWOBYTES && ! (mc6854->tfifo[ FIFO_SIZE - 2 ] & 0x100) )
744      mc6854->sr2 &= ~RDA2;
745
746   /* update AP */
747   if ( mc6854->rfifo[ FIFO_SIZE - 1 ] & 0x400 )
748      mc6854->sr2 |= AP;
749   else
750      mc6854->sr2 &= ~AP;
751}
752
753
754
755static void mc6854_update_sr1( mc6854_t* mc6854 )
756{
757   mc6854_update_sr2( mc6854 );
758
759   /* update S2RQ */
760   if ( mc6854->sr2 & 0x7f )
761      mc6854->sr1 |= S2RQ;
762   else
763      mc6854->sr1 &= ~S2RQ;
764
765   /* update TRDA (always prioritized by CTS) */
766   if ( TRESET || ( mc6854->sr1 & CTS ) )
767      mc6854->sr1 &= ~TDRA;
768   else
769   {
770      mc6854->sr1 |= TDRA;
771      if ( mc6854->tfifo[ 0 ] & 0x100 )
772         mc6854->sr1 &= ~TDRA;
773      else if ( TWOBYTES && (mc6854->tfifo[ 1 ] & 0x100) )
774         mc6854->sr1 &= ~TDRA;
775   }
776
777   /* update RDA */
778   if ( mc6854->sr2 & RDA2 )
779      mc6854->sr1 |= RDA;
780   else
781      mc6854->sr1 &= ~RDA;
782
783   /* update IRQ */
784   mc6854->sr1 &= ~IRQ;
785   if ( RIE && (mc6854->sr1 & (TU | TDRA) ) )
786      mc6854->sr1 |= IRQ;
787   if ( TIE )
788   {
789      if ( mc6854->sr1 & (S2RQ | RDA | CTS) )
790         mc6854->sr1 |= IRQ;
791      if ( mc6854->sr2 & (ERR | FV | DCD | OVRN | RABT | RIDLE | AP) )
792         mc6854->sr1 |= IRQ;
793   }
794
795   mc6854->out_irq_func((mc6854->sr1 & IRQ) ? ASSERT_LINE : CLEAR_LINE);
796}
797
798
799
800READ8_DEVICE_HANDLER ( mc6854_r )
801{
802   mc6854_t* mc6854 = get_safe_token( device );
803   switch ( offset )
804   {
805   case 0: /* status register 1 */
806      mc6854_update_sr1( mc6854 );
807      LOG(( "%f $%04x mc6854_r: get SR1=$%02X (rda=%i,s2rq=%i,fd=%i,cts=%i,tu=%i,tdra=%i,irq=%i)\n",
808            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->sr1,
809            ( mc6854->sr1 & RDA) ? 1 : 0, ( mc6854->sr1 & S2RQ) ? 1 : 0,
810            ( mc6854->sr1 & FD ) ? 1 : 0, ( mc6854->sr1 & CTS ) ? 1 : 0,
811            ( mc6854->sr1 & TU ) ? 1 : 0, ( mc6854->sr1 & TDRA) ? 1 : 0,
812            ( mc6854->sr1 & IRQ) ? 1 : 0 ));
813      return mc6854->sr1;
814
815   case 1: /* status register 2 */
816      mc6854_update_sr2( mc6854 );
817      LOG(( "%f $%04x mc6854_r: get SR2=$%02X (ap=%i,fv=%i,ridle=%i,rabt=%i,err=%i,dcd=%i,ovrn=%i,rda2=%i)\n",
818            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->sr2,
819            ( mc6854->sr2 & AP   ) ? 1 : 0, ( mc6854->sr2 & FV  ) ? 1 : 0,
820            ( mc6854->sr2 & RIDLE) ? 1 : 0, ( mc6854->sr2 & RABT) ? 1 : 0,
821            ( mc6854->sr2 & ERR  ) ? 1 : 0, ( mc6854->sr2 & DCD ) ? 1 : 0,
822            ( mc6854->sr2 & OVRN ) ? 1 : 0, ( mc6854->sr2 & RDA2) ? 1 : 0 ));
823      return mc6854->sr2;
824
825   case 2: /* receiver data register */
826   case 3:
827   {
828      UINT8 data = mc6854_rfifo_pop( device );
829      LOG(( "%f $%04x mc6854_r: get data $%02X\n",
830            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data ));
831      return data;
832   }
833
834   default:
835      logerror( "$%04x mc6854 invalid read offset %i\n", space.machine().firstcpu->pcbase( ), offset );
836   }
837   return 0;
838}
839
840
841
842WRITE8_DEVICE_HANDLER ( mc6854_w )
843{
844   mc6854_t* mc6854 = get_safe_token( device );
845   switch ( offset )
846   {
847   case 0: /* control register 1 */
848      mc6854->cr1 = data;
849      LOG(( "%f $%04x mc6854_w: set CR1=$%02X (ac=%i,irq=%c%c,%sreset=%c%c)\n",
850            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr1,
851            AC ? 1 : 0,
852            RIE ? 'r' : '-', TIE ? 't' : '-',
853            DISCONTINUE ? "discontinue," : "",
854            RRESET ? 'r' : '-', TRESET ? 't' : '-'
855            ));
856      if ( mc6854->cr1 & 0xc )
857         logerror( "$%04x mc6854 DMA not handled (CR1=$%02X)\n",
858               space.machine().firstcpu->pcbase( ), mc6854->cr1 );
859      if ( DISCONTINUE )
860      {
861         /* abort receive FIFO but keeps shift register & synchro */
862         mc6854->rstate = 0;
863         memset( mc6854->rfifo, 0, sizeof( mc6854->rfifo ) );
864      }
865      if ( RRESET )
866      {
867         /* abort FIFO & synchro */
868         mc6854_rfifo_clear( device );
869         mc6854->sr1 &= ~FD;
870         mc6854->sr2 &= ~(AP | FV | RIDLE | RABT | ERR | OVRN | DCD);
871         if ( mc6854->dcd ) mc6854->sr2 |= DCD;
872      }
873      if ( TRESET )
874      {
875         mc6854_tfifo_clear( device );
876         mc6854->sr1 &= ~(TU | TDRA | CTS);
877         if ( mc6854->cts ) mc6854->sr1 |= CTS;
878      }
879      break;
880
881   case 1:
882      if ( AC )
883      {
884         /* control register 3 */
885         mc6854->cr3 = data;
886         LOG(( "%f $%04x mc6854_w: set CR3=$%02X (lcf=%i,aex=%i,idl=%i,fdse=%i,loop=%i,tst=%i,dtr=%i)\n",
887               space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr3,
888               LCF ? (CEX ? 16 : 8) : 0,  AEX ? 1 : 0,
889               IDL0 ? 0 : 1, FDSE ? 1 : 0, LOOP ? 1 : 0,
890               TST ? 1 : 0, DTR ? 1 : 0
891               ));
892         if ( LOOP )
893            logerror( "$%04x mc6854 loop mode not handled (CR3=$%02X)\n", space.machine().firstcpu->pcbase( ), mc6854->cr3 );
894         if ( TST )
895            logerror( "$%04x mc6854 test mode not handled (CR3=$%02X)\n", space.machine().firstcpu->pcbase( ), mc6854->cr3 );
896
897         mc6854->out_dtr_func( DTR ? 1 : 0 );
898
899      }
900      else
901      {
902         /* control register 2 */
903         mc6854->cr2 = data;
904         LOG(( "%f $%04x mc6854_w: set CR2=$%02X (pse=%i,bytes=%i,fmidle=%i,%s,tlast=%i,clr=%c%c,rts=%i)\n",
905               space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr2,
906               PSE ? 1 : 0,  TWOBYTES ? 2 : 1,  FMIDLE ? 1 : 0,
907               FCTDRA ? "fc" : "tdra", TLAST ? 1 : 0,
908               data & 0x20 ? 'r' : '-',  data & 0x40 ? 't' : '-',
909               RTS ? 1 : 0 ));
910         if ( PSE )
911            logerror( "$%04x mc6854 status prioritization not handled (CR2=$%02X)\n", space.machine().firstcpu->pcbase( ), mc6854->cr2 );
912         if ( TLAST )
913            mc6854_tfifo_terminate( device );
914         if ( data & 0x20 )
915         {
916            /* clear receiver status */
917            mc6854->sr1 &= ~FD;
918            mc6854->sr2 &= ~(AP | FV | RIDLE | RABT | ERR | OVRN | DCD);
919            if ( mc6854->dcd )
920               mc6854->sr2 |= DCD;
921         }
922         if ( data & 0x40 )
923         {
924            /* clear transmitter status */
925            mc6854->sr1 &= ~(TU | TDRA | CTS);
926            if ( mc6854->cts )
927               mc6854->sr1 |= CTS;
928         }
929
930         mc6854->out_rts_func( RTS ? 1 : 0 );
931      }
932      break;
933
934   case 2: /* transmitter data: continue data */
935      LOG(( "%f $%04xmc6854_w: push data=$%02X\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data ));
936      mc6854_tfifo_push( device, data );
937      break;
938
939   case 3:
940      if ( AC )
941      {
942         /* control register 4 */
943         mc6854->cr4 = data;
944         LOG(( "%f $%04x mc6854_w: set CR4=$%02X (interframe=%i,tlen=%i,rlen=%i,%s%s)\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr4,
945               TWOINTER ? 2 : 1,
946               TWL, RWL,
947               ABT ? ( ABTEX ? "abort-ext," : "abort,") : "",
948               NRZ ? "nrz" : "nrzi" ));
949         if ( ABT )
950         {
951            mc6854->tstate = 0;
952            mc6854_send_bits( device, 0xffff, ABTEX ? 16 : 8, 0 );
953            mc6854->flen = 0;
954         }
955      }
956      else
957      {
958         /* transmitter data: last data */
959         LOG(( "%f $%04x mc6854_w: push last-data=$%02X\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data ));
960         mc6854_tfifo_push( device, data );
961         mc6854_tfifo_terminate( device );
962      }
963      break;
964
965   default:
966      logerror( "$%04x mc6854 invalid write offset %i (data=$%02X)\n", space.machine().firstcpu->pcbase( ), offset, data );
967   }
968}
969
970WRITE_LINE_DEVICE_HANDLER( mc6854_rxc_w )
971{
972   // TODO
973}
974
975WRITE_LINE_DEVICE_HANDLER( mc6854_txc_w )
976{
977   // TODO
978}
979
980/************************ reset *****************************/
981
982static DEVICE_RESET( mc6854 )
983{
984   mc6854_t* mc6854 = get_safe_token( device );
985   LOG (( "mc6854 reset\n" ));
986   mc6854->cr1 = 0xc0; /* reset condition */
987   mc6854->cr2 = 0;
988   mc6854->cr3 = 0;
989   mc6854->cr4 = 0;
990   mc6854->sr1 = 0;
991   mc6854->sr2 = 0;
992   mc6854->cts = 0;
993   mc6854->dcd = 0;
994   mc6854_tfifo_clear( device );
995   mc6854_rfifo_clear( device );
996}
997
998
999
1000/************************ start *****************************/
1001
1002static DEVICE_START( mc6854 )
1003{
1004   mc6854_t* mc6854 = get_safe_token( device );
1005
1006   mc6854->iface = (const mc6854_interface*)device->static_config();
1007   mc6854->out_irq_func.resolve(mc6854->iface->out_irq_func, *device);
1008   mc6854->in_rxd_func.resolve(mc6854->iface->in_rxd_func, *device);
1009   mc6854->out_txd_func.resolve(mc6854->iface->out_txd_func, *device);
1010   mc6854->out_rts_func.resolve(mc6854->iface->out_rts_func, *device);
1011   mc6854->out_dtr_func.resolve(mc6854->iface->out_dtr_func, *device);
1012
1013   mc6854->ttimer = device->machine().scheduler().timer_alloc(FUNC(mc6854_tfifo_cb), (void*) device );
1014
1015   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr1 );
1016   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr2 );
1017   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr3 );
1018   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr4 );
1019   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->sr1 );
1020   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->sr2 );
1021   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cts );
1022   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->dcd );
1023   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->tstate );
1024   state_save_register_item_array( device->machine(), "mc6854", device->tag(), 0, mc6854->tfifo );
1025   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->tones );
1026   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rstate );
1027   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rreg );
1028   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rones );
1029   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rsize );
1030   state_save_register_item_array( device->machine(), "mc6854", device->tag(), 0, mc6854->rfifo );
1031   state_save_register_item_array( device->machine(), "mc6854", device->tag(), 0, mc6854->frame );
1032   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->flen );
1033   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->fpos );
1034}
1035
1036
1037
1038const device_type MC6854 = &device_creator<mc6854_device>;
1039
1040mc6854_device::mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1041   : device_t(mconfig, MC6854, "Motorola MC6854 ADLC", tag, owner, clock)
1042{
1043   m_token = global_alloc_clear(mc6854_t);
1044}
1045
1046//-------------------------------------------------
1047//  device_config_complete - perform any
1048//  operations now that the configuration is
1049//  complete
1050//-------------------------------------------------
1051
1052void mc6854_device::device_config_complete()
1053{
1054}
1055
1056//-------------------------------------------------
1057//  device_start - device-specific startup
1058//-------------------------------------------------
1059
1060void mc6854_device::device_start()
1061{
1062   DEVICE_START_NAME( mc6854 )(this);
1063}
1064
1065//-------------------------------------------------
1066//  device_reset - device-specific reset
1067//-------------------------------------------------
1068
1069void mc6854_device::device_reset()
1070{
1071   DEVICE_RESET_NAME( mc6854 )(this);
1072}
Property changes on: trunk/src/emu/machine/mc6854.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/mc6854.h
r0r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2006
4
5  Motorola 6854 emulation (network interface).
6
7**********************************************************************/
8
9#ifndef MC6854_H
10#define MC6854_H
11
12class mc6854_device : public device_t
13{
14public:
15   mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
16   ~mc6854_device() { global_free(m_token); }
17
18   // access to legacy token
19   void *token() const { assert(m_token != NULL); return m_token; }
20protected:
21   // device-level overrides
22   virtual void device_config_complete();
23   virtual void device_start();
24   virtual void device_reset();
25private:
26   // internal state
27   void *m_token;
28};
29
30extern const device_type MC6854;
31
32
33/* we provide two interfaces:
34   - a bit-based interface:   out_tx, set_rx
35   - a frame-based interface: out_frame, send_frame
36
37   The bit-based interface is low-level and slow.
38   Use it to simulate the actual bits sent into the wires, e.g., to connect
39   the emulator to another bit-based emulated network device, or an actual
40   device.
41
42   The frame-based interface is higher-level and faster.
43   It passes bytes directly from one end to the other without bothering with
44   the actual bit-encoding, synchronization, and CRC.
45   Once completed, a frame is sent through out_frame. Aborted frames are not
46   transmitted at all. No start flag, stop flag, or crc bits are trasmitted.
47   send_frame makes a frame available to the CPU through the 6854 (it may
48   fail and return -1 if the 6854 is not ready to accept the frame; even
49   if the frame is accepted and 0 is returned, the CPU may abort it). Ony
50   full frames are accepted.
51*/
52
53
54/* ---------- configuration ------------ */
55
56struct mc6854_interface
57{
58   devcb_write_line  out_irq_func; /* interrupt request */
59
60   /* low-level, bit-based interface */
61   devcb_read_line   in_rxd_func; /* receive bit */
62   devcb_write_line  out_txd_func; /* transmit bit */
63
64   /* high-level, frame-based interface */
65   void ( * out_frame ) ( device_t *device, UINT8* data, int length );
66
67   /* control lines */
68   devcb_write_line  out_rts_func; /* 1 = transmitting, 0 = idle */
69   devcb_write_line  out_dtr_func; /* 1 = data transmit ready, 0 = busy */
70};
71
72
73#define MCFG_MC6854_ADD(_tag, _intrf) \
74   MCFG_DEVICE_ADD(_tag, MC6854, 0)          \
75   MCFG_DEVICE_CONFIG(_intrf)
76
77#define MCFG_MC6854_REMOVE(_tag)        \
78   MCFG_DEVICE_REMOVE(_tag)
79
80
81/* ---------- functions ------------ */
82/* interface to CPU via address/data bus*/
83extern DECLARE_READ8_DEVICE_HANDLER  ( mc6854_r );
84extern DECLARE_WRITE8_DEVICE_HANDLER ( mc6854_w );
85
86/* low-level, bit-based interface */
87WRITE_LINE_DEVICE_HANDLER( mc6854_set_rx );
88
89/* high-level, frame-based interface */
90extern int mc6854_send_frame( device_t *device, UINT8* data, int length ); /* ret -1 if busy */
91
92/* control lines */
93WRITE_LINE_DEVICE_HANDLER( mc6854_set_cts ); /* 1 = clear-to-send, 0 = busy */
94WRITE_LINE_DEVICE_HANDLER( mc6854_set_dcd ); /* 1 = carrier, 0 = no carrier */
95
96/* clock */
97WRITE_LINE_DEVICE_HANDLER( mc6854_rxc_w );
98WRITE_LINE_DEVICE_HANDLER( mc6854_txc_w );
99
100#endif
Property changes on: trunk/src/emu/machine/mc6854.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/mm58274c.c
r0r21685
1/***************************************************************************
2
3    mm58274c.c
4
5    mm58274c emulation
6
7    Reference:
8    * National Semiconductor MM58274C Microprocessor Compatible Real Time Clock
9        <http://www.national.com/ds/MM/MM58274C.pdf>
10
11    Todo:
12    * Clock initialization will only work with the BwG: we need to provide
13      a way to customize it.
14    * Save the config to NVRAM?
15    * Support interrupt pin output
16
17    Raphael Nabet, 2002
18
19***************************************************************************/
20
21#include "emu.h"
22#include "mm58274c.h"
23
24struct mm58274c_t
25{
26   const mm58274c_interface *intf;
27
28   int status;     /* status register (*read* from address 0 = control register) */
29   int control;    /* control register (*write* to address 0) */
30
31   int clk_set;    /* clock setting register */
32   int int_ctl;    /* interrupt control register */
33
34
35   int wday;       /* day of the week (1-7 (1=day1 as set in init)) */
36   int years1;     /* years (BCD: 0-99) */
37   int years2;
38   int months1;    /* months (BCD: 1-12) */
39   int months2;
40   int days1;      /* days (BCD: 1-31) */
41   int days2;
42   int hours1;     /* hours (BCD : 0-23) */
43   int hours2;
44   int minutes1;   /* minutes (BCD : 0-59) */
45   int minutes2;
46   int seconds1;   /* seconds (BCD : 0-59) */
47   int seconds2;
48   int tenths;     /* tenths of second (BCD : 0-9) */
49
50   emu_timer *increment_rtc;
51   emu_timer *interrupt_timer;
52};
53
54enum
55{
56   st_dcf = 0x8,       /* data-changed flag */
57   st_if = 0x1,        /* interrupt flag */
58
59   ctl_test = 0x8,     /* test mode (0=normal, 1=test) (not emulated) */
60   ctl_clkstop = 0x4,  /* clock start/stop (0=run, 1=stop) */
61   ctl_intsel = 0x2,   /* interrupt select (0=clock setting register, 1=interrupt register) */
62   ctl_intstop = 0x1,  /* interrupt start stop (0=interrupt run, 1=interrupt stop) */
63
64   clk_set_leap = 0xc,     /* leap year counter (0 indicates a leap year) */
65   clk_set_leap_inc = 0x4, /* leap year increment */
66   clk_set_pm = 0x2,       /* am/pm indicator (0 = am, 1 = pm, 0 in 24-hour mode) */
67   clk_set_24 = 0x1,       /* 12/24-hour select bit (1= 24-hour mode) */
68
69   int_ctl_rpt = 0x8,      /* 1 for repeated interrupt */
70   int_ctl_dly = 0x7       /* 0 no interrupt, 1 = .1 second, 2=.5, 3=1, 4=5, 5=10, 6=30, 7=60 */
71};
72
73
74INLINE mm58274c_t *get_safe_token(device_t *device)
75{
76   assert(device != NULL);
77   assert(device->type() == MM58274C);
78
79   return (mm58274c_t *)downcast<mm58274c_device *>(device)->token();
80}
81
82static attotime interrupt_period_table(int val)
83{
84   switch(val)
85   {
86      case 0: return attotime::from_msec(0);
87      case 1: return attotime::from_msec(100);
88      case 2: return attotime::from_msec(500);
89      case 3: return attotime::from_seconds(1);
90      case 4: return attotime::from_seconds(5);
91      case 5: return attotime::from_seconds(10);
92      case 6: return attotime::from_seconds(30);
93      case 7: return attotime::from_seconds(60);
94      default: fatalerror("out of range\n");
95   }
96};
97
98READ8_DEVICE_HANDLER( mm58274c_r )
99{
100   mm58274c_t *mm58274c = get_safe_token(device);
101   int reply;
102
103   offset &= 0xf;
104
105   switch (offset)
106   {
107   case 0x0:   /* Control Register */
108      reply = mm58274c->status;
109      mm58274c->status = 0;
110      break;
111
112   case 0x1:   /* Tenths of Seconds */
113      reply = mm58274c->tenths;
114      break;
115
116   case 0x2:   /* Units Seconds */
117      reply = mm58274c->seconds2;
118      break;
119
120   case 0x3:   /* Tens Seconds */
121      reply = mm58274c->seconds1;
122      break;
123
124   case 0x04:  /* Units Minutes */
125      reply = mm58274c->minutes2;
126      break;
127
128   case 0x5:   /* Tens Minutes */
129      reply = mm58274c->minutes1;
130      break;
131
132   case 0x6:   /* Units Hours */
133      reply = mm58274c->hours2;
134      break;
135
136   case 0x7:   /* Tens Hours */
137      reply = mm58274c->hours1;
138      break;
139
140   case 0x8:   /* Units Days */
141      reply = mm58274c->days2;
142      break;
143
144   case 0x9:   /* Tens Days */
145      reply = mm58274c->days1;
146      break;
147
148   case 0xA:   /* Units Months */
149      reply = mm58274c->months2;
150      break;
151
152   case 0xB:   /* Tens Months */
153      reply = mm58274c->months1;
154      break;
155
156   case 0xC:   /* Units Years */
157      reply = mm58274c->years2;
158      break;
159
160   case 0xD:   /* Tens Years */
161      reply = mm58274c->years1;
162      break;
163
164   case 0xE:   /* Day of Week */
165      reply = mm58274c->wday;
166      break;
167
168   case 0xF:   /* Clock Setting & Interrupt Registers */
169      if (mm58274c->control & ctl_intsel)
170         /* interrupt register */
171         reply = mm58274c->int_ctl;
172      else
173      {   /* clock setting register */
174         if (mm58274c->clk_set & clk_set_24)
175            /* 24-hour mode */
176            reply = mm58274c->clk_set & ~clk_set_pm;
177         else
178            /* 12-hour mode */
179            reply = mm58274c->clk_set;
180      }
181      break;
182
183   default:
184      reply = 0;
185      break;
186   }
187
188   return reply;
189}
190
191
192WRITE8_DEVICE_HANDLER (mm58274c_w)
193{
194   mm58274c_t *mm58274c = get_safe_token(device);
195
196   offset &= 0xf;
197   data &= 0xf;
198
199   switch (offset)
200   {
201   case 0x0:   /* Control Register (test mode and interrupt not emulated) */
202      if ((! (mm58274c->control & ctl_intstop)) && (data & ctl_intstop))
203         /* interrupt stop */
204         mm58274c->interrupt_timer->enable(0);
205      else if ((mm58274c->control & ctl_intstop) && (! (data & ctl_intstop)))
206      {
207         /* interrupt run */
208         attotime period = interrupt_period_table(mm58274c->int_ctl & int_ctl_dly);
209
210         mm58274c->interrupt_timer->adjust(period, 0, mm58274c->int_ctl & int_ctl_rpt ? period : attotime::zero);
211      }
212      if (data & ctl_clkstop)
213         /* stopping the clock clears the tenth counter */
214         mm58274c->tenths = 0;
215      mm58274c->control = data;
216      break;
217
218   case 0x1:   /* Tenths of Seconds: cannot be written */
219      break;
220
221   case 0x2:   /* Units Seconds */
222      mm58274c->seconds2 = data;
223      break;
224
225   case 0x3:   /* Tens Seconds */
226      mm58274c->seconds1 = data;
227      break;
228
229   case 0x4:   /* Units Minutes */
230      mm58274c->minutes2 = data;
231      break;
232
233   case 0x5:   /* Tens Minutes */
234      mm58274c->minutes1 = data;
235      break;
236
237   case 0x6:   /* Units Hours */
238      mm58274c->hours2 = data;
239      break;
240
241   case 0x7:   /* Tens Hours */
242      mm58274c->hours1 = data;
243      break;
244
245   case 0x8:   /* Units Days */
246      mm58274c->days2 = data;
247      break;
248
249   case 0x9:   /* Tens Days */
250      mm58274c->days1 = data;
251      break;
252
253   case 0xA:   /* Units Months */
254      mm58274c->months2 = data;
255      break;
256
257   case 0xB:   /* Tens Months */
258      mm58274c->months1 = data;
259      break;
260
261   case 0xC:   /* Units Years */
262      mm58274c->years2 = data;
263      break;
264
265   case 0xD:   /* Tens Years */
266      mm58274c->years1 = data;
267      break;
268
269   case 0xE:   /* Day of Week */
270      mm58274c->wday = data;
271      break;
272
273   case 0xF:   /* Clock Setting & Interrupt Registers */
274      if (mm58274c->control & ctl_intsel)
275      {
276         /* interrupt register (not emulated) */
277         mm58274c->int_ctl = data;
278         if (! (mm58274c->control & ctl_intstop))
279         {
280            /* interrupt run */
281            attotime period = interrupt_period_table(mm58274c->int_ctl & int_ctl_dly);
282
283            mm58274c->interrupt_timer->adjust(period, 0, mm58274c->int_ctl & int_ctl_rpt ? period : attotime::zero);
284         }
285      }
286      else
287      {
288         /* clock setting register */
289         mm58274c->clk_set = data;
290         #if 0
291            if (mm58274c->clk_set & clk_set_24)
292               /* 24-hour mode */
293               mm58274c->clk_set &= ~clk_set_pm;
294         #endif
295      }
296      break;
297   }
298}
299
300
301/*
302    Set RTC interrupt flag
303*/
304static TIMER_CALLBACK(rtc_interrupt_callback)
305{
306   device_t *device = (device_t *)ptr;
307   mm58274c_t *mm58274c = get_safe_token(device);
308   mm58274c->status |= st_if;
309}
310
311
312/*
313    Increment RTC clock (timed interrupt every 1/10s)
314*/
315
316static TIMER_CALLBACK(increment_rtc)
317{
318   device_t *device = (device_t *)ptr;
319   mm58274c_t *mm58274c = get_safe_token(device);
320   if (! (mm58274c->control & ctl_clkstop))
321   {
322      mm58274c->status |= st_dcf;
323
324      if ((++mm58274c->tenths) == 10)
325      {
326         mm58274c->tenths = 0;
327
328         if ((++mm58274c->seconds2) == 10)
329         {
330            mm58274c->seconds2 = 0;
331
332            if ((++mm58274c->seconds1) == 6)
333            {
334               mm58274c->seconds1 = 0;
335
336               if ((++mm58274c->minutes2) == 10)
337               {
338                  mm58274c->minutes2 = 0;
339
340                  if ((++mm58274c->minutes1) == 6)
341                  {
342                     mm58274c->minutes1 = 0;
343
344                     if ((++mm58274c->hours2) == 10)
345                     {
346                        mm58274c->hours2 = 0;
347
348                        mm58274c->hours1++;
349                     }
350
351                     /* handle wrap-around */
352                     if ((! (mm58274c->clk_set & clk_set_24))
353                           && ((mm58274c->hours1*10 + mm58274c->hours2) == 12))
354                     {
355                        mm58274c->clk_set ^= clk_set_pm;
356                     }
357                     if ((! (mm58274c->clk_set & clk_set_24))
358                           && ((mm58274c->hours1*10 + mm58274c->hours2) == 13))
359                     {
360                        mm58274c->hours1 = 0;
361                        mm58274c->hours2 = 1;
362                     }
363
364                     if ((mm58274c->clk_set & clk_set_24)
365                        && ((mm58274c->hours1*10 + mm58274c->hours2) == 24))
366                     {
367                        mm58274c->hours1 = mm58274c->hours2 = 0;
368                     }
369
370                     /* increment day if needed */
371                     if ((mm58274c->clk_set & clk_set_24)
372                        ? ((mm58274c->hours1*10 + mm58274c->hours2) == 0)
373                        : (((mm58274c->hours1*10 + mm58274c->hours2) == 12)
374                           && (! (mm58274c->clk_set & clk_set_pm))))
375                     {
376                        int days_in_month;
377
378                        if ((++mm58274c->days2) == 10)
379                        {
380                           mm58274c->days2 = 0;
381
382                           mm58274c->days1++;
383                        }
384
385                        if ((++mm58274c->wday) == 8)
386                           mm58274c->wday = 1;
387
388                        {
389                           static const int days_in_month_array[] =
390                           {
391                              31,28,31, 30,31,30,
392                              31,31,30, 31,30,31
393                           };
394
395                           if (((mm58274c->months1*10 + mm58274c->months2) != 2) || (mm58274c->clk_set & clk_set_leap))
396                              days_in_month = days_in_month_array[mm58274c->months1*10 + mm58274c->months2 - 1];
397                           else
398                              days_in_month = 29;
399                        }
400
401
402                        if ((mm58274c->days1*10 + mm58274c->days2) == days_in_month+1)
403                        {
404                           mm58274c->days1 = 0;
405                           mm58274c->days2 = 1;
406
407                           if ((++mm58274c->months2) == 10)
408                           {
409                              mm58274c->months2 = 0;
410
411                              mm58274c->months1++;
412                           }
413
414                           if ((mm58274c->months1*10 + mm58274c->months2) == 13)
415                           {
416                              mm58274c->months1 = 0;
417                              mm58274c->months2 = 1;
418
419                              mm58274c->clk_set = (mm58274c->clk_set & ~clk_set_leap)
420                                             | ((mm58274c->clk_set + clk_set_leap_inc) & clk_set_leap);
421
422                              if ((++mm58274c->years2) == 10)
423                              {
424                                 mm58274c->years2 = 0;
425
426                                 if ((++mm58274c->years1) == 10)
427                                    mm58274c->years1 = 0;
428                              }
429                           }
430                        }
431                     }
432                  }
433               }
434            }
435         }
436      }
437   }
438}
439
440/* Device Interface */
441
442static DEVICE_START( mm58274c )
443{
444   mm58274c_t *mm58274c = get_safe_token(device);
445
446   // validate arguments
447   assert(device != NULL);
448   assert(device->tag() != NULL);
449   assert(device->static_config() != NULL);
450
451   mm58274c->intf = (const mm58274c_interface*)device->static_config();
452   // register for state saving
453   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->status);
454   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->control);
455   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->clk_set);
456   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->int_ctl);
457   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->wday);
458   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->years1);
459   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->years2);
460   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->months1);
461   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->months2);
462   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->days1);
463   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->days2);
464   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->hours1);
465   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->hours2);
466   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->minutes1);
467   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->minutes2);
468   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->seconds1);
469   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->seconds2);
470   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->tenths);
471
472   mm58274c->increment_rtc = device->machine().scheduler().timer_alloc(FUNC(increment_rtc), ((void*)device));
473   mm58274c->increment_rtc->adjust(attotime::zero, 0, attotime::from_msec(100));
474   mm58274c->interrupt_timer = device->machine().scheduler().timer_alloc(FUNC(rtc_interrupt_callback), ((void*)device));
475}
476
477
478static DEVICE_RESET( mm58274c )
479{
480   mm58274c_t *mm58274c = get_safe_token(device);
481   system_time systime;
482
483   /* get the current date/time from the core */
484   device->machine().current_datetime(systime);
485
486   mm58274c->clk_set = systime.local_time.year & 3 << 2;
487   if (mm58274c->intf->mode24)
488      mm58274c->clk_set |= clk_set_24;
489
490   /* The clock count starts on 1st January 1900 */
491   mm58274c->wday = 1 + ((systime.local_time.weekday - mm58274c->intf->day1)%7);
492   mm58274c->years1 = (systime.local_time.year / 10) % 10;
493   mm58274c->years2 = systime.local_time.year % 10;
494   mm58274c->months1 = (systime.local_time.month + 1) / 10;
495   mm58274c->months2 = (systime.local_time.month + 1) % 10;
496   mm58274c->days1 = systime.local_time.mday / 10;
497   mm58274c->days2 = systime.local_time.mday % 10;
498   if (!mm58274c->intf->mode24)
499   {
500      /* 12-hour mode */
501      if (systime.local_time.hour > 12)
502      {
503         systime.local_time.hour -= 12;
504         mm58274c->clk_set |= clk_set_pm;
505      }
506      if (systime.local_time.hour == 0)
507         systime.local_time.hour = 12;
508   }
509   mm58274c->hours1 = systime.local_time.hour / 10;
510   mm58274c->hours2 = systime.local_time.hour % 10;
511   mm58274c->minutes1 = systime.local_time.minute / 10;
512   mm58274c->minutes2 = systime.local_time.minute % 10;
513   mm58274c->seconds1 = systime.local_time.second / 10;
514   mm58274c->seconds2 = systime.local_time.second % 10;
515   mm58274c->tenths = 0;
516}
517
518const device_type MM58274C = &device_creator<mm58274c_device>;
519
520mm58274c_device::mm58274c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
521   : device_t(mconfig, MM58274C, "National Semiconductor MM58274C", tag, owner, clock)
522{
523   m_token = global_alloc_clear(mm58274c_t);
524}
525
526//-------------------------------------------------
527//  device_config_complete - perform any
528//  operations now that the configuration is
529//  complete
530//-------------------------------------------------
531
532void mm58274c_device::device_config_complete()
533{
534}
535
536//-------------------------------------------------
537//  device_start - device-specific startup
538//-------------------------------------------------
539
540void mm58274c_device::device_start()
541{
542   DEVICE_START_NAME( mm58274c )(this);
543}
544
545//-------------------------------------------------
546//  device_reset - device-specific reset
547//-------------------------------------------------
548
549void mm58274c_device::device_reset()
550{
551   DEVICE_RESET_NAME( mm58274c )(this);
552}
Property changes on: trunk/src/emu/machine/mm58274c.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/mc6846.c
r0r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2006
4
5  Motorola 6846 emulation.
6
7  The MC6846 chip provides ROM (2048 bytes), I/O (8-bit directional data port +
8  2 control lines) and a programmable timer.
9  It may be interfaced with a M6809 cpu.
10  It is used in some Thomson computers.
11
12  Not yet implemented:
13  - external clock (CTC)
14  - latching of port on CP1
15  - gate input (CTG)
16  - timer comparison modes (frequency and pulse width)
17  - CP2 acknowledge modes
18
19**********************************************************************/
20
21#include "emu.h"
22#include "mc6846.h"
23
24#define VERBOSE 0
25
26
27
28/******************* internal chip data structure ******************/
29
30
31struct mc6846_t
32{
33   const mc6846_interface* iface;
34
35   /* registers */
36   UINT8    csr;      /* 0,4: combination status register */
37   UINT8    pcr;      /* 1:   peripheral control register */
38   UINT8    ddr;      /* 2:   data direction register */
39   UINT8    pdr;      /* 3:   peripheral data register (last cpu write) */
40   UINT8    tcr;      /* 5:   timer control register */
41
42   /* lines */
43   UINT8 cp1;         /* 1-bit input */
44   UINT8 cp2;         /* 1-bit input/output: last external write */
45   UINT8 cp2_cpu;     /* last cpu write */
46   UINT8 cto;         /* 1-bit timer output (unmasked) */
47
48   /* internal state */
49   UINT8  time_MSB; /* MSB buffer register */
50   UINT8  csr0_to_be_cleared;
51   UINT8  csr1_to_be_cleared;
52   UINT8  csr2_to_be_cleared;
53   UINT16 latch;   /* timer latch */
54   UINT16 preset;  /* preset value */
55   UINT8  timer_started;
56
57   /* timers */
58   emu_timer *interval; /* interval programmable timer */
59   emu_timer *one_shot; /* 1-us x factor one-shot timer */
60
61   /* CPU write to the outside through chip */
62   devcb_resolved_write8 out_port;  /* 8-bit output */
63   devcb_resolved_write8 out_cp1;   /* 1-bit output */
64   devcb_resolved_write8 out_cp2;   /* 1-bit output */
65
66   /* CPU read from the outside through chip */
67   devcb_resolved_read8 in_port; /* 8-bit input */
68
69   /* asynchronous timer output to outside world */
70   devcb_resolved_write8 out_cto; /* 1-bit output */
71
72   /* timer interrupt */
73   devcb_resolved_write_line irq;
74
75   int old_cif;
76   int old_cto;
77};
78
79
80
81/******************* utility function and macros ********************/
82
83#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
84
85#define PORT                                \
86   ((mc6846->pdr & mc6846->ddr) |                  \
87      ((!mc6846->in_port.isnull() ? mc6846->in_port( 0 ) : 0) & \
88      ~mc6846->ddr))
89
90#define CTO                             \
91   ((MODE == 0x30 || (mc6846->tcr & 0x80)) ? mc6846->cto : 0)
92
93#define MODE (mc6846->tcr & 0x38)
94
95#define FACTOR ((mc6846->tcr & 4) ? 8 : 1)
96
97
98
99INLINE mc6846_t* get_safe_token( device_t *device )
100{
101   assert( device != NULL );
102   assert( device->type() == MC6846 );
103   return (mc6846_t*) downcast<mc6846_device *>(device)->token();
104}
105
106
107INLINE UINT16 mc6846_counter( device_t *device )
108{
109   mc6846_t* mc6846 = get_safe_token( device );
110   if ( mc6846->timer_started )
111   {
112      attotime delay = mc6846->interval ->remaining( );
113      return delay.as_ticks(1000000) / FACTOR;
114   }
115   else
116      return mc6846->preset;
117}
118
119
120
121INLINE void mc6846_update_irq( device_t *device )
122{
123   mc6846_t* mc6846 = get_safe_token( device );
124   int cif = 0;
125   /* composite interrupt flag */
126   if ( ( (mc6846->csr & 1) && (mc6846->tcr & 0x40) ) ||
127         ( (mc6846->csr & 2) && (mc6846->pcr & 1) ) ||
128         ( (mc6846->csr & 4) && (mc6846->pcr & 8) && ! (mc6846->pcr & 0x20) ) )
129      cif = 1;
130   if ( mc6846->old_cif != cif )
131   {
132      LOG (( "%f: mc6846 interrupt %i (time=%i cp1=%i cp2=%i)\n",
133            device->machine().time().as_double(), cif,
134            mc6846->csr & 1, (mc6846->csr >> 1 ) & 1, (mc6846->csr >> 2 ) & 1 ));
135      mc6846->old_cif = cif;
136   }
137   if ( cif )
138   {
139      mc6846->csr |= 0x80;
140      if ( !mc6846->irq.isnull() )
141         mc6846->irq( 1 );
142   }
143   else
144   {
145      mc6846->csr &= ~0x80;
146      if ( !mc6846->irq.isnull() )
147         mc6846->irq( 0 );
148   }
149}
150
151
152
153INLINE void mc6846_update_cto ( device_t *device )
154{
155   mc6846_t* mc6846 = get_safe_token( device );
156   int cto = CTO;
157   if ( cto != mc6846->old_cto )
158   {
159      LOG (( "%f: mc6846 CTO set to %i\n", device->machine().time().as_double(), cto ));
160      mc6846->old_cto = cto;
161   }
162   if ( !mc6846->out_cto.isnull() )
163      mc6846->out_cto( 0, cto );
164}
165
166
167
168INLINE void mc6846_timer_launch ( device_t *device )
169{
170   mc6846_t* mc6846 = get_safe_token( device );
171   int delay = FACTOR * (mc6846->preset+1);
172   LOG (( "%f: mc6846 timer launch called, mode=%i, preset=%i (x%i)\n", device->machine().time().as_double(), MODE, mc6846->preset, FACTOR ));
173
174   if ( ! (mc6846->tcr & 2) )
175   {
176      logerror( "mc6846 external clock CTC not implemented\n" );
177   }
178
179   switch( MODE )
180   {
181   case 0x00:
182   case 0x10: /* continuous */
183      mc6846->cto = 0;
184      break;
185
186   case 0x20: /* single-shot */
187      mc6846->cto = 0;
188      mc6846->one_shot->reset( attotime::from_usec(FACTOR) );
189      break;
190
191   case 0x30:  /* cascaded single-shot */
192      break;
193
194   default:
195      logerror( "mc6846 timer mode %i not implemented\n", MODE );
196      mc6846->interval->reset(  );
197      mc6846->timer_started = 0;
198      return;
199   }
200
201   mc6846->interval->reset( attotime::from_usec(delay) );
202   mc6846->timer_started = 1;
203
204   mc6846->csr &= ~1;
205   mc6846_update_cto( device );
206   mc6846_update_irq( device );
207}
208
209
210
211/******************* timer callbacks *********************************/
212
213static TIMER_CALLBACK( mc6846_timer_expire )
214{
215   device_t* device = (device_t*) ptr;
216   mc6846_t* mc6846 = get_safe_token( device );
217   int delay = FACTOR * (mc6846->latch+1);
218
219   LOG (( "%f: mc6846 timer expire called, mode=%i, latch=%i (x%i)\n", device->machine().time().as_double(), MODE, mc6846->latch, FACTOR ));
220
221   /* latch => counter */
222   mc6846->preset = mc6846->latch;
223
224   if ( ! (mc6846->tcr & 2) )
225      logerror( "mc6846 external clock CTC not implemented\n" );
226
227   switch ( MODE )
228   {
229   case 0x00:
230   case 0x10: /* continuous */
231      mc6846->cto = 1 ^ mc6846->cto;
232      break;
233
234   case 0x20: /* single-shot */
235      mc6846->cto = 0;
236      break;
237
238   case 0x30:  /* cascaded single-shot */
239      mc6846->cto = ( mc6846->tcr & 0x80 ) ? 1 : 0;
240      break;
241
242   default:
243      logerror( "mc6846 timer mode %i not implemented\n", MODE );
244      mc6846->interval->reset(  );
245      mc6846->timer_started = 0;
246      return;
247   }
248
249   mc6846->interval->reset( attotime::from_usec(delay) );
250
251   mc6846->csr |= 1;
252   mc6846_update_cto( device );
253   mc6846_update_irq( device );
254}
255
256
257
258static TIMER_CALLBACK( mc6846_timer_one_shot )
259{
260   device_t* device = (device_t*) ptr;
261   mc6846_t* mc6846 = get_safe_token( device );
262   LOG (( "%f: mc6846 timer one shot called\n", device->machine().time().as_double() ));
263
264   /* 1 micro second after one-shot launch, we put cto to high */
265   mc6846->cto = 1;
266   mc6846_update_cto( device );
267}
268
269
270
271/************************** CPU interface ****************************/
272
273
274READ8_DEVICE_HANDLER ( mc6846_r )
275{
276   mc6846_t* mc6846 = get_safe_token( device );
277   switch ( offset )
278   {
279   case 0:
280   case 4:
281      LOG (( "$%04x %f: mc6846 CSR read $%02X intr=%i (timer=%i, cp1=%i, cp2=%i)\n",
282            space.machine().firstcpu->pcbase( ), space.machine().time().as_double(),
283            mc6846->csr, (mc6846->csr >> 7) & 1,
284            mc6846->csr & 1, (mc6846->csr >> 1) & 1, (mc6846->csr >> 2) & 1 ));
285      mc6846->csr0_to_be_cleared = mc6846->csr & 1;
286      mc6846->csr1_to_be_cleared = mc6846->csr & 2;
287      mc6846->csr2_to_be_cleared = mc6846->csr & 4;
288      return mc6846->csr;
289
290   case 1:
291      LOG (( "$%04x %f: mc6846 PCR read $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846->pcr ));
292      return mc6846->pcr;
293
294   case 2:
295      LOG (( "$%04x %f: mc6846 DDR read $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846->ddr ));
296      return mc6846->ddr;
297
298   case 3:
299      LOG (( "$%04x %f: mc6846 PORT read $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), PORT ));
300      if ( ! (mc6846->pcr & 0x80) )
301      {
302         if ( mc6846->csr1_to_be_cleared )
303            mc6846->csr &= ~2;
304         if ( mc6846->csr2_to_be_cleared )
305            mc6846->csr &= ~4;
306         mc6846_update_irq( device );
307         mc6846->csr1_to_be_cleared = 0;
308         mc6846->csr2_to_be_cleared = 0;
309      }
310      return PORT;
311
312   case 5:
313      LOG (( "$%04x %f: mc6846 TCR read $%02X\n",space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846->tcr ));
314      return mc6846->tcr;
315
316   case 6:
317      LOG (( "$%04x %f: mc6846 COUNTER hi read $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846_counter( device ) >> 8 ));
318      if ( mc6846->csr0_to_be_cleared )
319      {
320         mc6846->csr &= ~1;
321         mc6846_update_irq( device );
322      }
323      mc6846->csr0_to_be_cleared = 0;
324      return mc6846_counter( device ) >> 8;
325
326   case 7:
327      LOG (( "$%04x %f: mc6846 COUNTER low read $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846_counter( device ) & 0xff ));
328      if ( mc6846->csr0_to_be_cleared )
329      {
330         mc6846->csr &= ~1;
331         mc6846_update_irq( device );
332      }
333      mc6846->csr0_to_be_cleared = 0;
334      return mc6846_counter( device ) & 0xff;
335
336   default:
337      logerror( "$%04x mc6846 invalid read offset %i\n", space.machine().firstcpu->pcbase( ), offset );
338   }
339   return 0;
340}
341
342
343
344WRITE8_DEVICE_HANDLER ( mc6846_w )
345{
346   mc6846_t* mc6846 = get_safe_token( device );
347   switch ( offset )
348   {
349   case 0:
350   case 4:
351      /* CSR is read-only */
352      break;
353
354   case 1:
355   {
356      static const char *const cp2[8] =
357      {
358         "in,neg-edge", "in,neg-edge,intr", "in,pos-edge", "in,pos-edge,intr",
359         "out,intr-ack", "out,i/o-ack", "out,0", "out,1"
360      };
361      static const char *const cp1[8] =
362      {
363         "neg-edge", "neg-edge,intr", "pos-edge", "pos-edge,intr",
364         "latched,neg-edge", "latched,neg-edge,intr",
365         "latcged,pos-edge", "latcged,pos-edge,intr"
366      };
367      LOG (( "$%04x %f: mc6846 PCR write $%02X reset=%i cp2=%s cp1=%s\n",
368            space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), data,
369            (data >> 7) & 1, cp2[ (data >> 3) & 7 ], cp1[ data & 7 ] ));
370
371   }
372   mc6846->pcr = data;
373   if ( data & 0x80 )
374   {      /* data reset */
375      mc6846->pdr = 0;
376      mc6846->ddr = 0;
377      mc6846->csr &= ~6;
378      mc6846_update_irq( device );
379   }
380   if ( data & 4 )
381      logerror( "$%04x mc6846 CP1 latching not implemented\n", space.machine().firstcpu->pcbase( ) );
382   if (data & 0x20)
383   {
384      if (data & 0x10)
385      {
386         mc6846->cp2_cpu = (data >> 3) & 1;
387         if ( !mc6846->out_cp2.isnull() )
388            mc6846->out_cp2( 0, mc6846->cp2_cpu );
389      }
390      else
391         logerror( "$%04x mc6846 acknowledge not implemented\n", space.machine().firstcpu->pcbase( ) );
392   }
393   break;
394
395   case 2:
396      LOG (( "$%04x %f: mc6846 DDR write $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), data ));
397      if ( ! (mc6846->pcr & 0x80) )
398      {
399         mc6846->ddr = data;
400         if ( !mc6846->out_port.isnull() )
401            mc6846->out_port( 0, mc6846->pdr & mc6846->ddr );
402      }
403      break;
404
405   case 3:
406      LOG (( "$%04x %f: mc6846 PORT write $%02X (mask=$%02X)\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), data,mc6846->ddr ));
407      if ( ! (mc6846->pcr & 0x80) )
408      {
409         mc6846->pdr = data;
410         if ( !mc6846->out_port.isnull() )
411            mc6846->out_port( 0, mc6846->pdr & mc6846->ddr );
412         if ( mc6846->csr1_to_be_cleared && (mc6846->csr & 2) )
413         {
414            mc6846->csr &= ~2;
415            LOG (( "$%04x %f: mc6846 CP1 intr reset\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double() ));
416         }
417         if ( mc6846->csr2_to_be_cleared && (mc6846->csr & 4) )
418         {
419            mc6846->csr &= ~4;
420            LOG (( "$%04x %f: mc6846 CP2 intr reset\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double() ));
421         }
422         mc6846->csr1_to_be_cleared = 0;
423         mc6846->csr2_to_be_cleared = 0;
424         mc6846_update_irq( device );
425      }
426      break;
427
428   case 5:
429   {
430      static const char *const mode[8] =
431         {
432            "continuous", "cascaded", "continuous", "one-shot",
433            "freq-cmp", "freq-cmp", "pulse-cmp", "pulse-cmp"
434         };
435      LOG (( "$%04x %f: mc6846 TCR write $%02X reset=%i clock=%s scale=%i mode=%s out=%s\n",
436            space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), data,
437            (data >> 7) & 1, (data & 0x40) ? "extern" : "sys",
438            (data & 0x40) ? 1 : 8, mode[ (data >> 1) & 7 ],
439            (data & 1) ? "enabled" : "0" ));
440
441      mc6846->tcr = data;
442      if ( mc6846->tcr & 1 )
443      {
444         /* timer preset = initialization without launch */
445         mc6846->preset = mc6846->latch;
446         mc6846->csr &= ~1;
447         if ( MODE != 0x30 )
448            mc6846->cto = 0;
449         mc6846_update_cto( device );
450         mc6846->interval->reset(  );
451         mc6846->one_shot->reset(  );
452         mc6846->timer_started = 0;
453      }
454      else
455      {
456         /* timer launch */
457         if ( ! mc6846->timer_started )
458            mc6846_timer_launch( device );
459      }
460      mc6846_update_irq( device );
461   }
462   break;
463
464   case 6:
465      mc6846->time_MSB = data;
466      break;
467
468   case 7:
469      mc6846->latch = ( ((UINT16) mc6846->time_MSB) << 8 ) + data;
470      LOG (( "$%04x %f: mc6846 COUNT write %i\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846->latch  ));
471      if (!(mc6846->tcr & 0x38))
472      {
473         /* timer initialization */
474         mc6846->preset = mc6846->latch;
475         mc6846->csr &= ~1;
476         mc6846_update_irq( device );
477         mc6846->cto = 0;
478         mc6846_update_cto( device );
479         /* launch only if started */
480         if (!(mc6846->tcr & 1))
481            mc6846_timer_launch( device );
482      }
483      break;
484
485   default:
486      logerror( "$%04x mc6846 invalid write offset %i\n", space.machine().firstcpu->pcbase( ), offset );
487   }
488}
489
490
491
492/******************** outside world interface ************************/
493
494
495
496void mc6846_set_input_cp1 ( device_t *device, int data )
497{
498   mc6846_t* mc6846 = get_safe_token( device );
499   data = (data != 0 );
500   if ( data == mc6846->cp1 )
501      return;
502   mc6846->cp1 = data;
503   LOG (( "%f: mc6846 input CP1 set to %i\n",  device->machine().time().as_double(), data ));
504   if (( data &&  (mc6846->pcr & 2)) || (!data && !(mc6846->pcr & 2)))
505   {
506      mc6846->csr |= 2;
507      mc6846_update_irq( device );
508   }
509}
510
511void mc6846_set_input_cp2 ( device_t *device, int data )
512{
513   mc6846_t* mc6846 = get_safe_token( device );
514   data = (data != 0 );
515   if ( data == mc6846->cp2 )
516      return;
517   mc6846->cp2 = data;
518   LOG (( "%f: mc6846 input CP2 set to %i\n", device->machine().time().as_double(), data ));
519   if (mc6846->pcr & 0x20)
520   {
521      if (( data &&  (mc6846->pcr & 0x10)) || (!data && !(mc6846->pcr & 0x10)))
522      {
523         mc6846->csr |= 4;
524         mc6846_update_irq( device );
525      }
526   }
527}
528
529
530
531/************************ accessors **********************************/
532
533
534
535UINT8 mc6846_get_output_port ( device_t *device )
536{
537   mc6846_t* mc6846 = get_safe_token( device );
538   return PORT;
539}
540
541
542
543UINT8 mc6846_get_output_cto ( device_t *device )
544{
545   mc6846_t* mc6846 = get_safe_token( device );
546   return CTO;
547}
548
549
550
551UINT8 mc6846_get_output_cp2 ( device_t *device )
552{
553   mc6846_t* mc6846 = get_safe_token( device );
554   return mc6846->cp2_cpu;
555}
556
557
558
559UINT16 mc6846_get_preset ( device_t *device )
560{
561   mc6846_t* mc6846 = get_safe_token( device );
562   return mc6846->preset;
563}
564
565
566
567/************************ reset *****************************/
568
569
570static DEVICE_RESET( mc6846 )
571{
572   mc6846_t* mc6846 = get_safe_token( device );
573   LOG (( "mc6846_reset\n" ));
574   mc6846->cto   = 0;
575   mc6846->csr   = 0;
576   mc6846->pcr   = 0x80;
577   mc6846->ddr   = 0;
578   mc6846->pdr   = 0;
579   mc6846->tcr   = 1;
580   mc6846->cp1   = 0;
581   mc6846->cp2   = 0;
582   mc6846->cp2_cpu  = 0;
583   mc6846->latch    = 0xffff;
584   mc6846->preset   = 0xffff;
585   mc6846->time_MSB = 0;
586   mc6846->csr0_to_be_cleared = 0;
587   mc6846->csr1_to_be_cleared = 0;
588   mc6846->csr2_to_be_cleared = 0;
589   mc6846->timer_started = 0;
590   mc6846->interval->reset(  );
591   mc6846->one_shot->reset(  );
592}
593
594
595/************************ start *****************************/
596
597static DEVICE_START( mc6846 )
598{
599   mc6846_t* mc6846 = get_safe_token( device );
600
601   mc6846->iface = (const mc6846_interface*)device->static_config();
602   mc6846->interval = device->machine().scheduler().timer_alloc(FUNC(mc6846_timer_expire), (void*) device );
603   mc6846->one_shot = device->machine().scheduler().timer_alloc(FUNC(mc6846_timer_one_shot), (void*) device );
604
605   mc6846->out_port.resolve(mc6846->iface->out_port_func, *device);  /* 8-bit output */
606   mc6846->out_cp1.resolve(mc6846->iface->out_cp1_func, *device);   /* 1-bit output */
607   mc6846->out_cp2.resolve(mc6846->iface->out_cp2_func, *device);   /* 1-bit output */
608
609   /* CPU read from the outside through chip */
610   mc6846->in_port.resolve(mc6846->iface->in_port_func, *device); /* 8-bit input */
611
612   /* asynchronous timer output to outside world */
613   mc6846->out_cto.resolve(mc6846->iface->out_cto_func, *device); /* 1-bit output */
614
615   /* timer interrupt */
616   mc6846->irq.resolve(mc6846->iface->irq_func, *device);
617
618   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->csr );
619   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->pcr );
620   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->ddr );
621   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->pdr );
622   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->tcr );
623   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->cp1 );
624   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->cp2 );
625   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->cp2_cpu );
626   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->cto );
627   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->time_MSB );
628   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->csr0_to_be_cleared );
629   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->csr1_to_be_cleared );
630   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->csr2_to_be_cleared );
631   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->latch );
632   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->preset );
633   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->timer_started );
634}
635
636
637const device_type MC6846 = &device_creator<mc6846_device>;
638
639mc6846_device::mc6846_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
640   : device_t(mconfig, MC6846, "Motorola MC6846 programmable timer", tag, owner, clock)
641{
642   m_token = global_alloc_clear(mc6846_t);
643}
644
645//-------------------------------------------------
646//  device_config_complete - perform any
647//  operations now that the configuration is
648//  complete
649//-------------------------------------------------
650
651void mc6846_device::device_config_complete()
652{
653}
654
655//-------------------------------------------------
656//  device_start - device-specific startup
657//-------------------------------------------------
658
659void mc6846_device::device_start()
660{
661   DEVICE_START_NAME( mc6846 )(this);
662}
663
664//-------------------------------------------------
665//  device_reset - device-specific reset
666//-------------------------------------------------
667
668void mc6846_device::device_reset()
669{
670   DEVICE_RESET_NAME( mc6846 )(this);
671}
Property changes on: trunk/src/emu/machine/mc6846.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/mm58274c.h
r0r21685
1#ifndef MM58274C_H
2#define MM58274C_H
3
4/***************************************************************************
5    MACROS
6***************************************************************************/
7
8class mm58274c_device : public device_t
9{
10public:
11   mm58274c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
12   ~mm58274c_device() { global_free(m_token); }
13
14   // access to legacy token
15   void *token() const { assert(m_token != NULL); return m_token; }
16protected:
17   // device-level overrides
18   virtual void device_config_complete();
19   virtual void device_start();
20   virtual void device_reset();
21private:
22   // internal state
23   void *m_token;
24};
25
26extern const device_type MM58274C;
27
28
29/***************************************************************************
30    FUNCTION PROTOTYPES
31***************************************************************************/
32/* interface */
33/*
34    Initializes the clock chip.
35    day1 must be set to a value from 0 (sunday), 1 (monday) ...
36    to 6 (saturday) and is needed to correctly retrieve the day-of-week
37    from the host system clock.
38*/
39struct mm58274c_interface
40{
41   int mode24;     /* 24/12 mode */
42   int day1;       /* first day of week */
43};
44
45DECLARE_READ8_DEVICE_HANDLER ( mm58274c_r );
46DECLARE_WRITE8_DEVICE_HANDLER( mm58274c_w );
47
48/***************************************************************************
49    DEVICE CONFIGURATION MACROS
50***************************************************************************/
51
52#define MCFG_MM58274C_ADD(_tag, _intrf) \
53   MCFG_DEVICE_ADD(_tag, MM58274C, 0) \
54   MCFG_DEVICE_CONFIG(_intrf)
55
56#endif /* MM58274C_H */
Property changes on: trunk/src/emu/machine/mm58274c.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/mc6846.h
r0r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2006
4
5  Motorola 6846 timer emulation.
6
7**********************************************************************/
8
9#ifndef MC6846_H
10#define MC6846_H
11
12class mc6846_device : public device_t
13{
14public:
15   mc6846_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
16   ~mc6846_device() { global_free(m_token); }
17
18   // access to legacy token
19   void *token() const { assert(m_token != NULL); return m_token; }
20protected:
21   // device-level overrides
22   virtual void device_config_complete();
23   virtual void device_start();
24   virtual void device_reset();
25private:
26   // internal state
27   void *m_token;
28};
29
30extern const device_type MC6846;
31
32
33/* ---------- configuration ------------ */
34
35struct mc6846_interface
36{
37   /* CPU write to the outside through chip */
38   devcb_write8 out_port_func;  /* 8-bit output */
39   devcb_write8 out_cp1_func;   /* 1-bit output */
40   devcb_write8 out_cp2_func;   /* 1-bit output */
41
42   /* CPU read from the outside through chip */
43   devcb_read8 in_port_func; /* 8-bit input */
44
45   /* asynchronous timer output to outside world */
46   devcb_write8 out_cto_func; /* 1-bit output */
47
48   /* timer interrupt */
49   devcb_write_line irq_func;
50};
51
52
53#define MCFG_MC6846_ADD(_tag, _intrf) \
54   MCFG_DEVICE_ADD(_tag, MC6846, 0)          \
55   MCFG_DEVICE_CONFIG(_intrf)
56
57#define MCFG_MC6846_MODIFY(_tag, _intrf) \
58   MCFG_DEVICE_MODIFY(_tag)          \
59   MCFG_DEVICE_CONFIG(_intrf)
60
61#define MCFG_MC6846_REMOVE(_tag)        \
62   MCFG_DEVICE_REMOVE(_tag)
63
64
65/* ---------- functions ------------ */
66/* interface to CPU via address/data bus*/
67extern DECLARE_READ8_DEVICE_HANDLER  ( mc6846_r );
68extern DECLARE_WRITE8_DEVICE_HANDLER ( mc6846_w );
69
70/* asynchronous write from outside world into interrupt-generating pins */
71extern void mc6846_set_input_cp1 ( device_t *device, int data );
72extern void mc6846_set_input_cp2 ( device_t *device, int data );
73
74/* polling from outside world */
75extern UINT8  mc6846_get_output_port ( device_t *device );
76extern UINT8  mc6846_get_output_cto  ( device_t *device );
77extern UINT8  mc6846_get_output_cp2  ( device_t *device );
78
79/* partial access to internal state */
80extern UINT16 mc6846_get_preset ( device_t *device ); /* timer interval - 1 in us */
81
82#endif
Property changes on: trunk/src/emu/machine/mc6846.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/mos6530.c
r0r21685
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 "mos6530.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
41struct mos6530_port
42{
43   devcb_resolved_read8        in_port_func;
44   devcb_resolved_write8       out_port_func;
45
46   UINT8               in;
47   UINT8               out;
48   UINT8               ddr;
49};
50
51
52struct mos6530_state
53{
54   devcb_resolved_write_line   out_irq_func;
55
56   mos6530_port    port[2];
57
58   UINT8           irqstate;
59   UINT8           irqenable;
60
61   UINT8           timershift;
62   UINT8           timerstate;
63   emu_timer *     timer;
64
65   UINT32          clock;
66};
67
68
69
70/***************************************************************************
71    INLINE FUNCTIONS
72***************************************************************************/
73
74/*-------------------------------------------------
75    get_safe_token - convert a device's token
76    into a mos6530_state
77-------------------------------------------------*/
78
79INLINE mos6530_state *get_safe_token(device_t *device)
80{
81   assert(device != NULL);
82   assert(device->type() == MOS6530);
83   return (mos6530_state *)downcast<mos6530_device *>(device)->token();
84}
85
86
87/*-------------------------------------------------
88    update_irqstate - update the IRQ state
89    based on interrupt enables
90-------------------------------------------------*/
91
92INLINE void update_irqstate(device_t *device)
93{
94   mos6530_state *miot = get_safe_token(device);
95   UINT8 out = miot->port[1].out;
96
97   if ( miot->irqenable )
98      out = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( out & 0x7F );
99
100   if (!miot->port[1].out_port_func.isnull())
101      miot->port[1].out_port_func(0, out);
102   else
103      logerror("6530MIOT chip %s: Port B is being written to but has no handler.\n", device->tag());
104}
105
106
107/*-------------------------------------------------
108    get_timer - return the current timer value
109-------------------------------------------------*/
110
111INLINE UINT8 get_timer(mos6530_state *miot)
112{
113   /* if idle, return 0 */
114   if (miot->timerstate == TIMER_IDLE)
115      return 0;
116
117   /* if counting, return the number of ticks remaining */
118   else if (miot->timerstate == TIMER_COUNTING)
119      return miot->timer->remaining().as_ticks(miot->clock) >> miot->timershift;
120
121   /* if finishing, return the number of ticks without the shift */
122   else
123      return miot->timer->remaining().as_ticks(miot->clock);
124}
125
126
127/***************************************************************************
128    INTERNAL FUNCTIONS
129***************************************************************************/
130
131/*-------------------------------------------------
132    timer_end_callback - callback to process the
133    timer
134-------------------------------------------------*/
135
136static TIMER_CALLBACK( timer_end_callback )
137{
138   device_t *device = (device_t *)ptr;
139   mos6530_state *miot = get_safe_token(device);
140
141   assert(miot->timerstate != TIMER_IDLE);
142
143   /* if we finished counting, switch to the finishing state */
144   if (miot->timerstate == TIMER_COUNTING)
145   {
146      miot->timerstate = TIMER_FINISHING;
147      miot->timer->adjust(attotime::from_ticks(256, miot->clock));
148
149      /* signal timer IRQ as well */
150      miot->irqstate |= TIMER_FLAG;
151      update_irqstate(device);
152   }
153
154   /* if we finished finishing, switch to the idle state */
155   else if (miot->timerstate == TIMER_FINISHING)
156   {
157      miot->timerstate = TIMER_IDLE;
158      miot->timer->adjust(attotime::never);
159   }
160}
161
162
163
164/***************************************************************************
165    I/O ACCESS
166***************************************************************************/
167
168/*-------------------------------------------------
169    mos6530_w - master I/O write access
170-------------------------------------------------*/
171
172WRITE8_DEVICE_HANDLER( mos6530_w )
173{
174   mos6530_state *miot = get_safe_token(device);
175
176   /* if A2 == 1, we are writing to the timer */
177   if (offset & 0x04)
178   {
179      static const UINT8 timershift[4] = { 0, 3, 6, 10 };
180      attotime curtime = space.machine().time();
181      INT64 target;
182
183      /* A0-A1 contain the timer divisor */
184      miot->timershift = timershift[offset & 3];
185
186      /* A3 contains the timer IRQ enable */
187      if (offset & 8)
188         miot->irqenable |= TIMER_FLAG;
189      else
190         miot->irqenable &= ~TIMER_FLAG;
191
192      /* writes here clear the timer flag */
193      if (miot->timerstate != TIMER_FINISHING || get_timer(miot) != 0xff)
194         miot->irqstate &= ~TIMER_FLAG;
195      update_irqstate(device);
196
197      /* update the timer */
198      miot->timerstate = TIMER_COUNTING;
199      target = curtime.as_ticks(miot->clock) + 1 + (data << miot->timershift);
200      miot->timer->adjust(attotime::from_ticks(target, miot->clock) - curtime);
201   }
202
203   /* if A2 == 0, we are writing to the I/O section */
204   else
205   {
206      /* A1 selects the port */
207      mos6530_port *port = &miot->port[(offset >> 1) & 1];
208
209      /* if A0 == 1, we are writing to the port's DDR */
210      if (offset & 1)
211         port->ddr = data;
212
213      /* if A0 == 0, we are writing to the port's output */
214      else
215      {
216         UINT8 olddata = port->out;
217         port->out = data;
218
219         if ( ( offset & 2 ) && miot->irqenable )
220         {
221            olddata = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( olddata & 0x7F );
222            data = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( data & 0x7F );
223         }
224
225         if (!port->out_port_func.isnull())
226            port->out_port_func(0, data);
227         else
228            logerror("6530MIOT chip %s: Port %c is being written to but has no handler.  PC: %08X - %02X\n", device->tag(), 'A' + (offset & 1), space.machine().firstcpu->pc(), data);
229      }
230   }
231}
232
233
234/*-------------------------------------------------
235    mos6530_r - master I/O read access
236-------------------------------------------------*/
237
238READ8_DEVICE_HANDLER( mos6530_r )
239{
240   mos6530_state *miot = get_safe_token(device);
241   UINT8 val = 0;
242
243   /* if A2 == 1 and A0 == 1, we are reading interrupt flags */
244   if ((offset & 0x05) == 0x05)
245   {
246      val = miot->irqstate;
247   }
248
249   /* if A2 == 1 and A0 == 0, we are reading the timer */
250   else if ((offset & 0x05) == 0x04)
251   {
252      val = get_timer(miot);
253
254      /* A3 contains the timer IRQ enable */
255      if (offset & 8)
256         miot->irqenable |= TIMER_FLAG;
257      else
258         miot->irqenable &= ~TIMER_FLAG;
259
260      /* implicitly clears the timer flag */
261      if (miot->timerstate != TIMER_FINISHING || val != 0xff)
262         miot->irqstate &= ~TIMER_FLAG;
263      update_irqstate(device);
264   }
265
266   /* if A2 == 0 and A0 == anything, we are reading from ports */
267   else
268   {
269      /* A1 selects the port */
270      mos6530_port *port = &miot->port[(offset >> 1) & 1];
271
272      /* if A0 == 1, we are reading the port's DDR */
273      if (offset & 1)
274         val = port->ddr;
275
276      /* if A0 == 0, we are reading the port as an input */
277      else
278      {
279         UINT8   out = port->out;
280
281         if ( ( offset & 2 ) && miot->irqenable )
282            out = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( out & 0x7F );
283
284         /* call the input callback if it exists */
285         if (!port->in_port_func.isnull())
286         {
287            port->in = port->in_port_func(0);
288         }
289         else
290            logerror("6530MIOT chip %s: Port %c is being read but has no handler.  PC: %08X\n", device->tag(), 'A' + (offset & 1), space.machine().firstcpu->pc());
291
292         /* apply the DDR to the result */
293         val = (out & port->ddr) | (port->in & ~port->ddr);
294      }
295   }
296   return val;
297}
298
299
300/*-------------------------------------------------
301    mos6530_porta_in_set - set port A input
302    value
303-------------------------------------------------*/
304
305void mos6530_porta_in_set(device_t *device, UINT8 data, UINT8 mask)
306{
307   mos6530_state *miot = get_safe_token(device);
308   miot->port[0].in = (miot->port[0].in & ~mask) | (data & mask);
309}
310
311
312/*-------------------------------------------------
313    mos6530_portb_in_set - set port B input
314    value
315-------------------------------------------------*/
316
317void mos6530_portb_in_set(device_t *device, UINT8 data, UINT8 mask)
318{
319   mos6530_state *miot = get_safe_token(device);
320   miot->port[1].in = (miot->port[1].in & ~mask) | (data & mask);
321}
322
323
324/*-------------------------------------------------
325    mos6530_porta_in_get - return port A input
326    value
327-------------------------------------------------*/
328
329UINT8 mos6530_porta_in_get(device_t *device)
330{
331   mos6530_state *miot = get_safe_token(device);
332   return miot->port[0].in;
333}
334
335
336/*-------------------------------------------------
337    mos6530_portb_in_get - return port B input
338    value
339-------------------------------------------------*/
340
341UINT8 mos6530_portb_in_get(device_t *device)
342{
343   mos6530_state *miot = get_safe_token(device);
344   return miot->port[1].in;
345}
346
347
348/*-------------------------------------------------
349    mos6530_porta_in_get - return port A output
350    value
351-------------------------------------------------*/
352
353UINT8 mos6530_porta_out_get(device_t *device)
354{
355   mos6530_state *miot = get_safe_token(device);
356   return miot->port[0].out;
357}
358
359
360/*-------------------------------------------------
361    mos6530_portb_in_get - return port B output
362    value
363-------------------------------------------------*/
364
365UINT8 mos6530_portb_out_get(device_t *device)
366{
367   mos6530_state *miot = get_safe_token(device);
368   return miot->port[1].out;
369}
370
371
372/***************************************************************************
373    DEVICE INTERFACE
374***************************************************************************/
375
376static DEVICE_START( mos6530 )
377{
378   mos6530_state *miot = get_safe_token(device);
379   const mos6530_interface *intf = (const mos6530_interface*)device->static_config();
380
381   /* validate arguments */
382   assert(device != NULL);
383   assert(device->tag() != NULL);
384
385   /* set static values */
386   miot->clock = device->clock();
387
388   /* resolve callbacks */
389   miot->port[0].in_port_func.resolve(intf->in_pa_func, *device);
390   miot->port[1].in_port_func.resolve(intf->in_pb_func, *device);
391   miot->port[0].out_port_func.resolve(intf->out_pa_func, *device);
392   miot->port[1].out_port_func.resolve(intf->out_pb_func, *device);
393
394   /* allocate timers */
395   miot->timer = device->machine().scheduler().timer_alloc(FUNC(timer_end_callback), (void *)device);
396
397   /* register for save states */
398   device->save_item(NAME(miot->port[0].in));
399   device->save_item(NAME(miot->port[0].out));
400   device->save_item(NAME(miot->port[0].ddr));
401   device->save_item(NAME(miot->port[1].in));
402   device->save_item(NAME(miot->port[1].out));
403   device->save_item(NAME(miot->port[1].ddr));
404
405   device->save_item(NAME(miot->irqstate));
406   device->save_item(NAME(miot->irqenable));
407
408   device->save_item(NAME(miot->timershift));
409   device->save_item(NAME(miot->timerstate));
410}
411
412
413static DEVICE_RESET( mos6530 )
414{
415   mos6530_state *miot = get_safe_token(device);
416
417   /* reset I/O states */
418   miot->port[0].out = 0;
419   miot->port[0].ddr = 0;
420   miot->port[1].out = 0;
421   miot->port[1].ddr = 0;
422
423   /* reset IRQ states */
424   miot->irqenable = 0;
425   miot->irqstate = TIMER_FLAG;
426   update_irqstate(device);
427
428   /* reset timer states */
429   miot->timershift = 0;
430   miot->timerstate = TIMER_IDLE;
431   miot->timer->adjust(attotime::never);
432}
433
434
435const device_type MOS6530 = &device_creator<mos6530_device>;
436
437mos6530_device::mos6530_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
438   : device_t(mconfig, MOS6530, "MOS6530", tag, owner, clock)
439{
440   m_token = global_alloc_clear(mos6530_state);
441}
442
443//-------------------------------------------------
444//  device_config_complete - perform any
445//  operations now that the configuration is
446//  complete
447//-------------------------------------------------
448
449void mos6530_device::device_config_complete()
450{
451}
452
453//-------------------------------------------------
454//  device_start - device-specific startup
455//-------------------------------------------------
456
457void mos6530_device::device_start()
458{
459   DEVICE_START_NAME( mos6530 )(this);
460}
461
462//-------------------------------------------------
463//  device_reset - device-specific reset
464//-------------------------------------------------
465
466void mos6530_device::device_reset()
467{
468   DEVICE_RESET_NAME( mos6530 )(this);
469}
Property changes on: trunk/src/emu/machine/mos6530.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/mos6530.h
r0r21685
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    MACROS / CONSTANTS
38***************************************************************************/
39
40class mos6530_device : public device_t
41{
42public:
43   mos6530_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
44   ~mos6530_device() { global_free(m_token); }
45
46   // access to legacy token
47   void *token() const { assert(m_token != NULL); return m_token; }
48protected:
49   // device-level overrides
50   virtual void device_config_complete();
51   virtual void device_start();
52   virtual void device_reset();
53private:
54   // internal state
55   void *m_token;
56};
57
58extern const device_type MOS6530;
59
60
61#define MCFG_MOS6530_ADD(_tag, _clock, _config) \
62   MCFG_DEVICE_ADD((_tag), MOS6530, _clock)    \
63   MCFG_DEVICE_CONFIG(_config)
64
65#define MOS6530_INTERFACE(name) \
66   const mos6530_interface (name) =
67
68/***************************************************************************
69    TYPE DEFINITIONS
70***************************************************************************/
71
72struct mos6530_interface
73{
74   devcb_read8             in_pa_func;
75   devcb_write8            out_pa_func;
76
77   devcb_read8             in_pb_func;
78   devcb_write8            out_pb_func;
79};
80
81/***************************************************************************
82    PROTOTYPES
83***************************************************************************/
84
85DECLARE_READ8_DEVICE_HANDLER( mos6530_r );
86DECLARE_WRITE8_DEVICE_HANDLER( mos6530_w );
87
88void mos6530_porta_in_set(device_t *device, UINT8 data, UINT8 mask);
89void mos6530_portb_in_set(device_t *device, UINT8 data, UINT8 mask);
90
91UINT8 mos6530_porta_in_get(device_t *device);
92UINT8 mos6530_portb_in_get(device_t *device);
93
94UINT8 mos6530_porta_out_get(device_t *device);
95UINT8 mos6530_portb_out_get(device_t *device);
96
97#endif
Property changes on: trunk/src/emu/machine/mos6530.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/wd2010.c
r0r21685
1/**********************************************************************
2
3    Western Digital WD2010 Winchester Disk Controller
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10#include "machine/wd2010.h"
11
12
13
14//**************************************************************************
15//  MACROS / CONSTANTS
16//**************************************************************************
17
18#define LOG 1
19
20
21// task file
22enum
23{
24   TASK_FILE_ERROR = 1,
25   TASK_FILE_WRITE_PRECOMP_CYLINDER = TASK_FILE_ERROR,
26   TASK_FILE_SECTOR_COUNT,
27   TASK_FILE_SECTOR_NUMBER,
28   TASK_FILE_CYLINDER_LOW,
29   TASK_FILE_CYLINDER_HIGH,
30   TASK_FILE_SDH_REGISTER,
31   TASK_FILE_STATUS,
32   TASK_FILE_COMMAND = TASK_FILE_STATUS
33};
34
35#define WRITE_PRECOMP_CYLINDER \
36   (m_task_file[TASK_FILE_WRITE_PRECOMP_CYLINDER] * 4)
37
38#define SECTOR_COUNT \
39   ((m_task_file[TASK_FILE_SECTOR_COUNT] + 1) * 256)
40
41#define SECTOR_NUMBER \
42   (m_task_file[TASK_FILE_SECTOR_NUMBER])
43
44#define CYLINDER \
45   (((m_task_file[TASK_FILE_CYLINDER_HIGH] & 0x07) << 8) | m_task_file[TASK_FILE_CYLINDER_LOW])
46
47#define HEAD \
48   (m_task_file[TASK_FILE_SDH_REGISTER] & 0x07)
49
50#define DRIVE \
51   ((m_task_file[TASK_FILE_SDH_REGISTER] >> 3) & 0x03)
52
53static const int SECTOR_SIZES[4] = { 256, 512, 1024, 128 };
54
55#define SECTOR_SIZE \
56   SECTOR_SIZES[(m_task_file[TASK_FILE_SDH_REGISTER] >> 5) & 0x03]
57
58
59// status register
60#define STATUS_BSY      0x80
61#define STATUS_RDY      0x40
62#define STATUS_WF       0x20
63#define STATUS_SC       0x10
64#define STATUS_DRQ      0x08
65#define STATUS_DWC      0x04
66#define STATUS_CIP      0x02
67#define STATUS_ERR      0x01
68
69
70// error register
71#define ERROR_BB        0x80
72#define ERROR_CRC_ECC   0x40
73#define ERROR_ID        0x10
74#define ERROR_AC        0x04
75#define ERROR_TK        0x02
76#define ERROR_DM        0x01
77
78
79// command register
80#define COMMAND_MASK                0xf0
81#define COMMAND_RESTORE             0x10
82#define COMMAND_SEEK                0x70
83#define COMMAND_READ_SECTOR         0x20
84#define COMMAND_WRITE_SECTOR        0x30
85#define COMMAND_SCAN_ID             0x40
86#define COMMAND_WRITE_FORMAT        0x50
87#define COMMAND_COMPUTE_CORRECTION  0x08
88#define COMMAND_SET_PARAMETER_MASK  0xfe
89#define COMMAND_SET_PARAMETER       0x00
90
91
92
93//**************************************************************************
94//  DEVICE DEFINITIONS
95//**************************************************************************
96
97const device_type WD2010 = &device_creator<wd2010_device>;
98
99
100//-------------------------------------------------
101//  device_config_complete - perform any
102//  operations now that the configuration is
103//  complete
104//-------------------------------------------------
105
106void wd2010_device::device_config_complete()
107{
108   // inherit a copy of the static data
109   const wd2010_interface *intf = reinterpret_cast<const wd2010_interface *>(static_config());
110   if (intf != NULL)
111      *static_cast<wd2010_interface *>(this) = *intf;
112
113   // or initialize to defaults if none provided
114   else
115   {
116      memset(&m_out_intrq_cb, 0, sizeof(m_out_intrq_cb));
117      memset(&m_out_bdrq_cb, 0, sizeof(m_out_bdrq_cb));
118      memset(&m_out_bcr_cb, 0, sizeof(m_out_bcr_cb));
119      memset(&m_in_bcs_cb, 0, sizeof(m_in_bcs_cb));
120      memset(&m_out_bcs_cb, 0, sizeof(m_out_bcs_cb));
121      memset(&m_out_dirin_cb, 0, sizeof(m_out_dirin_cb));
122      memset(&m_out_step_cb, 0, sizeof(m_out_step_cb));
123      memset(&m_out_rwc_cb, 0, sizeof(m_out_rwc_cb));
124      memset(&m_in_drdy_cb, 0, sizeof(m_in_drdy_cb));
125      memset(&m_in_index_cb, 0, sizeof(m_in_index_cb));
126      memset(&m_in_wf_cb, 0, sizeof(m_in_wf_cb));
127      memset(&m_in_tk000_cb, 0, sizeof(m_in_tk000_cb));
128      memset(&m_in_sc_cb, 0, sizeof(m_in_sc_cb));
129   }
130}
131
132
133
134//**************************************************************************
135//  LIVE DEVICE
136//**************************************************************************
137
138//-------------------------------------------------
139//  wd2010_device - constructor
140//-------------------------------------------------
141
142wd2010_device::wd2010_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
143   : device_t(mconfig, WD2010, "Western Digital WD2010", tag, owner, clock),
144   m_status(0),
145   m_error(0)
146{
147}
148
149
150//-------------------------------------------------
151//  device_start - device-specific startup
152//-------------------------------------------------
153
154void wd2010_device::device_start()
155{
156   // resolve callbacks
157   m_out_intrq_func.resolve(m_out_intrq_cb, *this);
158   m_out_bdrq_func.resolve(m_out_bdrq_cb, *this);
159   m_out_bcr_func.resolve(m_out_bcr_cb, *this);
160   m_in_bcs_func.resolve(m_in_bcs_cb, *this);
161   m_out_bcs_func.resolve(m_out_bcs_cb, *this);
162   m_out_dirin_func.resolve(m_out_dirin_cb, *this);
163   m_out_step_func.resolve(m_out_step_cb, *this);
164   m_out_rwc_func.resolve(m_out_rwc_cb, *this);
165   m_in_drdy_func.resolve(m_in_drdy_cb, *this);
166   m_in_index_func.resolve(m_in_index_cb, *this);
167   m_in_wf_func.resolve(m_in_wf_cb, *this);
168   m_in_tk000_func.resolve(m_in_tk000_cb, *this);
169   m_in_sc_func.resolve(m_in_sc_cb, *this);
170}
171
172
173//-------------------------------------------------
174//  device_reset - device-specific reset
175//-------------------------------------------------
176
177void wd2010_device::device_reset()
178{
179}
180
181
182//-------------------------------------------------
183//  read -
184//-------------------------------------------------
185
186READ8_MEMBER( wd2010_device::read )
187{
188   UINT8 data = 0;
189
190   switch (offset)
191   {
192   case TASK_FILE_ERROR:
193      data = m_error;
194      break;
195
196   case TASK_FILE_STATUS:
197      m_out_intrq_func(CLEAR_LINE);
198      data = m_status | STATUS_RDY | STATUS_SC;
199      break;
200
201   default:
202      data = m_task_file[offset];
203      break;
204   }
205
206   return data;
207}
208
209
210//-------------------------------------------------
211//  write -
212//-------------------------------------------------
213
214WRITE8_MEMBER( wd2010_device::write )
215{
216   m_task_file[offset] = data;
217
218   switch (offset)
219   {
220   case TASK_FILE_WRITE_PRECOMP_CYLINDER:
221      if (LOG) logerror("%s WD2010 '%s' Write Precomp Cylinder: %u\n", machine().describe_context(), tag(), WRITE_PRECOMP_CYLINDER);
222      break;
223
224   case TASK_FILE_SECTOR_COUNT:
225      if (LOG) logerror("%s WD2010 '%s' Sector Count: %u\n", machine().describe_context(), tag(), SECTOR_COUNT);
226      break;
227
228   case TASK_FILE_SECTOR_NUMBER:
229      if (LOG) logerror("%s WD2010 '%s' Sector Number: %u\n", machine().describe_context(), tag(), SECTOR_NUMBER);
230      break;
231
232   case TASK_FILE_CYLINDER_LOW:
233      if (LOG) logerror("%s WD2010 '%s' Cylinder Low: %u\n", machine().describe_context(), tag(), CYLINDER);
234      break;
235
236   case TASK_FILE_CYLINDER_HIGH:
237      if (LOG) logerror("%s WD2010 '%s' Cylinder Low: %u\n", machine().describe_context(), tag(), CYLINDER);
238      break;
239
240   case TASK_FILE_SDH_REGISTER:
241      if (LOG)
242      {
243         logerror("%s WD2010 '%s' Head: %u\n", machine().describe_context(), tag(), HEAD);
244         logerror("%s WD2010 '%s' Drive: %u\n", machine().describe_context(), tag(), DRIVE);
245         logerror("%s WD2010 '%s' Sector Size: %u\n", machine().describe_context(), tag(), SECTOR_SIZE);
246      }
247      break;
248
249   case TASK_FILE_COMMAND:
250      if (data == COMMAND_COMPUTE_CORRECTION)
251      {
252         if (LOG) logerror("%s WD2010 '%s' COMPUTE CORRECTION\n", machine().describe_context(), tag());
253         compute_correction(data);
254      }
255      else if ((data & COMMAND_SET_PARAMETER_MASK) == COMMAND_SET_PARAMETER)
256      {
257         if (LOG) logerror("%s WD2010 '%s' SET PARAMETER\n", machine().describe_context(), tag());
258         set_parameter(data);
259      }
260      else
261      {
262         switch (data & COMMAND_MASK)
263         {
264         case COMMAND_RESTORE:
265            if (LOG) logerror("%s WD2010 '%s' RESTORE\n", machine().describe_context(), tag());
266            restore(data);
267            break;
268
269         case COMMAND_SEEK:
270            if (LOG) logerror("%s WD2010 '%s' SEEK\n", machine().describe_context(), tag());
271            seek(data);
272            break;
273
274         case COMMAND_READ_SECTOR:
275            if (LOG) logerror("%s WD2010 '%s' READ SECTOR\n", machine().describe_context(), tag());
276            read_sector(data);
277            break;
278
279         case COMMAND_WRITE_SECTOR:
280            if (LOG) logerror("%s WD2010 '%s' WRITE SECTOR\n", machine().describe_context(), tag());
281            write_sector(data);
282            break;
283
284         case COMMAND_SCAN_ID:
285            if (LOG) logerror("%s WD2010 '%s' SCAN ID\n", machine().describe_context(), tag());
286            scan_id(data);
287            break;
288
289         case COMMAND_WRITE_FORMAT:
290            if (LOG) logerror("%s WD2010 '%s' WRITE FORMAT\n", machine().describe_context(), tag());
291            format(data);
292            break;
293         }
294      }
295      break;
296   }
297}
298
299
300//-------------------------------------------------
301//  compute_correction -
302//-------------------------------------------------
303
304void wd2010_device::compute_correction(UINT8 data)
305{
306}
307
308
309//-------------------------------------------------
310//  set_parameter -
311//-------------------------------------------------
312
313void wd2010_device::set_parameter(UINT8 data)
314{
315}
316
317
318//-------------------------------------------------
319//  restore -
320//-------------------------------------------------
321
322void wd2010_device::restore(UINT8 data)
323{
324   // reset INTRQ, errors, set BUSY, CIP
325   m_out_intrq_func(CLEAR_LINE);
326   m_error = 0;
327   m_status = STATUS_BSY | STATUS_CIP;
328
329   // reset RWC, set direction=OUT, store step rate
330   m_out_rwc_func(0);
331   m_out_dirin_func(0);
332
333   int step_pulses = 0;
334
335   while (step_pulses < 2048)
336   {
337      while (!m_in_sc_func())
338      {
339         // drive not ready or write fault?
340         if (!m_in_drdy_func() || m_in_wf_func())
341         {
342            // pulse BCR, set AC, INTRQ, reset BSY, CIP
343            m_out_bcr_func(0);
344            m_out_bcr_func(1);
345            m_error = ERROR_AC;
346            m_status = (m_in_drdy_func() << 6) | (m_in_wf_func() << 5) | STATUS_ERR;
347            m_out_intrq_func(ASSERT_LINE);
348            return;
349         }
350      }
351
352      if (m_in_tk000_func())
353      {
354         // pulse BCR, set INTRQ, reset BSY, CIP
355         m_out_bcr_func(0);
356         m_out_bcr_func(1);
357         m_status &= ~(STATUS_BSY | STATUS_CIP);
358         m_out_intrq_func(ASSERT_LINE);
359         return;
360      }
361
362      if (step_pulses == 2047)
363      {
364         // set TK000 error
365         m_error = ERROR_TK;
366         m_status |= STATUS_ERR;
367
368         // pulse BCR, set INTRQ, reset BSY, CIP
369         m_out_bcr_func(0);
370         m_out_bcr_func(1);
371         m_status &= ~(STATUS_BSY | STATUS_CIP);
372         m_out_intrq_func(ASSERT_LINE);
373         return;
374      }
375
376      // issue a step pulse
377      m_out_step_func(1);
378      m_out_step_func(0);
379      step_pulses++;
380   }
381}
382
383
384//-------------------------------------------------
385//  seek -
386//-------------------------------------------------
387
388void wd2010_device::seek(UINT8 data)
389{
390}
391
392
393//-------------------------------------------------
394//  read_sector -
395//-------------------------------------------------
396
397void wd2010_device::read_sector(UINT8 data)
398{
399}
400
401
402//-------------------------------------------------
403//  write_sector -
404//-------------------------------------------------
405
406void wd2010_device::write_sector(UINT8 data)
407{
408}
409
410
411//-------------------------------------------------
412//  scan_id -
413//-------------------------------------------------
414
415void wd2010_device::scan_id(UINT8 data)
416{
417}
418
419
420//-------------------------------------------------
421//  format -
422//-------------------------------------------------
423
424void wd2010_device::format(UINT8 data)
425{
426}
Property changes on: trunk/src/emu/machine/wd2010.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/wd2010.h
r0r21685
1/**********************************************************************
2
3    Western Digital WD2010 Winchester Disk Controller
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10#pragma once
11
12#ifndef __WD2010__
13#define __WD2010__
14
15
16#include "emu.h"
17
18
19
20//**************************************************************************
21//  INTERFACE CONFIGURATION MACROS
22//**************************************************************************
23
24#define MCFG_WD2010_ADD(_tag, _clock, _config) \
25   MCFG_DEVICE_ADD(_tag, WD2010, _clock) \
26   MCFG_DEVICE_CONFIG(_config)
27
28
29#define WD2010_INTERFACE(_name) \
30   const wd2010_interface (_name) =
31
32
33
34//**************************************************************************
35//  TYPE DEFINITIONS
36//**************************************************************************
37
38// ======================> wd2010_interface
39
40struct wd2010_interface
41{
42   devcb_write_line    m_out_intrq_cb;
43   devcb_write_line    m_out_bdrq_cb;
44   devcb_write_line    m_out_bcr_cb;
45   devcb_read8         m_in_bcs_cb;
46   devcb_write8        m_out_bcs_cb;
47   devcb_write_line    m_out_dirin_cb;
48   devcb_write_line    m_out_step_cb;
49   devcb_write_line    m_out_rwc_cb;
50   devcb_read_line     m_in_drdy_cb;
51   devcb_read_line     m_in_index_cb;
52   devcb_read_line     m_in_wf_cb;
53   devcb_read_line     m_in_tk000_cb;
54   devcb_read_line     m_in_sc_cb;
55};
56
57
58// ======================> wd2010_device
59
60class wd2010_device :   public device_t,
61                  public wd2010_interface
62{
63public:
64   // construction/destruction
65   wd2010_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
66
67   DECLARE_READ8_MEMBER( read );
68   DECLARE_WRITE8_MEMBER( write );
69
70protected:
71   // device-level overrides
72   virtual void device_start();
73   virtual void device_reset();
74   virtual void device_config_complete();
75
76private:
77   void compute_correction(UINT8 data);
78   void set_parameter(UINT8 data);
79   void restore(UINT8 data);
80   void seek(UINT8 data);
81   void read_sector(UINT8 data);
82   void write_sector(UINT8 data);
83   void scan_id(UINT8 data);
84   void format(UINT8 data);
85
86   devcb_resolved_write_line   m_out_intrq_func;
87   devcb_resolved_write_line   m_out_bdrq_func;
88   devcb_resolved_write_line   m_out_bcr_func;
89   devcb_resolved_read8        m_in_bcs_func;
90   devcb_resolved_write8       m_out_bcs_func;
91   devcb_resolved_write_line   m_out_dirin_func;
92   devcb_resolved_write_line   m_out_step_func;
93   devcb_resolved_write_line   m_out_rwc_func;
94   devcb_resolved_read_line    m_in_drdy_func;
95   devcb_resolved_read_line    m_in_index_func;
96   devcb_resolved_read_line    m_in_wf_func;
97   devcb_resolved_read_line    m_in_tk000_func;
98   devcb_resolved_read_line    m_in_sc_func;
99
100   UINT8 m_status;
101   UINT8 m_error;
102   UINT8 m_task_file[8];
103};
104
105
106// device type definition
107extern const device_type WD2010;
108
109#endif
Property changes on: trunk/src/emu/machine/wd2010.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/at45dbxx.c
r0r21685
1/*
2
3    Atmel Serial DataFlash
4
5    (c) 2001-2007 Tim Schuerewegen
6
7    AT45DB041 -  528 KByte
8    AT45DB081 - 1056 KByte
9    AT45DB161 - 2112 KByte
10
11*/
12
13#include "at45dbxx.h"
14
15#define LOG_LEVEL  1
16#define _logerror(level,x)  do { if (LOG_LEVEL > level) logerror x; } while (0)
17
18#define FLASH_CMD_52  0x52
19#define FLASH_CMD_57  0x57
20#define FLASH_CMD_60  0x60
21#define FLASH_CMD_82  0x82
22
23#define FLASH_MODE_XX  0 // unknown
24#define FLASH_MODE_SI  1 // input
25#define FLASH_MODE_SO  2 // output
26
27
28//**************************************************************************
29//  GLOBAL VARIABLES
30//**************************************************************************
31
32// device type definition
33const device_type AT45DB041 = &device_creator<at45db041_device>;
34const device_type AT45DB081 = &device_creator<at45db081_device>;
35const device_type AT45DB161 = &device_creator<at45db161_device>;
36
37
38//**************************************************************************
39//  LIVE DEVICE
40//**************************************************************************
41
42//-------------------------------------------------
43//  at45db041_device - constructor
44//-------------------------------------------------
45
46at45db041_device::at45db041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
47   : device_t(mconfig, AT45DB041, "AT45DB041", tag, owner, clock),
48   device_nvram_interface(mconfig, *this)
49{
50}
51
52
53at45db041_device::at45db041_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
54   : device_t(mconfig, type, name, tag, owner, clock),
55   device_nvram_interface(mconfig, *this)
56{
57}
58
59
60at45db081_device::at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
61   : at45db041_device(mconfig, AT45DB081, "AT45DB081", tag, owner, clock)
62{
63}
64
65
66at45db161_device::at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
67   : at45db041_device(mconfig, AT45DB161, "AT45DB161", tag, owner, clock)
68{
69}
70
71
72//-------------------------------------------------
73//  device_start - device-specific startup
74//-------------------------------------------------
75
76void at45db041_device::device_start()
77{
78   m_size = num_pages() * page_size();
79   m_data = auto_alloc_array(machine(), UINT8, m_size);
80   m_buffer1 = auto_alloc_array(machine(), UINT8, page_size());
81   m_buffer2 = auto_alloc_array(machine(), UINT8, page_size());
82
83   // data
84   save_pointer(NAME(m_data), m_size);
85   // pins
86   save_item(NAME(m_pin.cs));
87   save_item(NAME(m_pin.sck));
88   save_item(NAME(m_pin.si));
89   save_item(NAME(m_pin.so));
90   save_item(NAME(m_pin.wp));
91   save_item(NAME(m_pin.reset));
92   save_item(NAME(m_pin.busy));
93}
94
95
96//-------------------------------------------------
97//  device_reset - device-specific reset
98//-------------------------------------------------
99
100void at45db041_device::device_reset()
101{
102   _logerror( 1, ("at45dbxx_reset\n"));
103   // mode
104   m_mode = FLASH_MODE_SI;
105   // command
106   memset(&m_cmd.data[0], 0, sizeof(m_cmd.data));
107   m_cmd.size = 0;
108   // input/output
109   m_io.data = NULL;
110   m_io.size = 0;
111   m_io.pos  = 0;
112   // pins
113   m_pin.cs    = 0;
114   m_pin.sck   = 0;
115   m_pin.si    = 0;
116   m_pin.so    = 0;
117   m_pin.wp    = 0;
118   m_pin.reset = 0;
119   m_pin.busy  = 0;
120   // output
121   m_so_byte = 0;
122   m_so_bits = 0;
123   // input
124   m_si_byte = 0;
125   m_si_bits = 0;
126}
127
128
129//-------------------------------------------------
130//  nvram_default - called to initialize NVRAM to
131//  its default state
132//-------------------------------------------------
133
134void at45db041_device::nvram_default()
135{
136   memset(m_data, 0xff, m_size);
137
138   if (region() != NULL)
139   {
140      UINT32 bytes = region()->bytes();
141      if (bytes > m_size)
142         bytes = m_size;
143
144      memcpy(m_data, region()->base(), bytes);
145   }
146}
147
148//-------------------------------------------------
149//  nvram_read - called to read NVRAM from the
150//  .nv file
151//-------------------------------------------------
152
153void at45db041_device::nvram_read(emu_file &file)
154{
155   file.read(m_data, m_size);
156}
157
158//-------------------------------------------------
159//  nvram_write - called to write NVRAM to the
160//  .nv file
161//-------------------------------------------------
162
163void at45db041_device::nvram_write(emu_file &file)
164{
165   file.write(m_data, m_size);
166}
167
168UINT8 at45db041_device::read_byte()
169{
170   UINT8 data;
171   // check mode
172   if ((m_mode != FLASH_MODE_SO) || (!m_io.data)) return 0;
173   // read byte
174   data = m_io.data[m_io.pos++];
175   _logerror( 2, ("at45dbxx_read_byte (%02X) (%03d/%03d)\n", data, m_io.pos, m_io.size));
176   if (m_io.pos == m_io.size) m_io.pos = 0;
177   return data;
178}
179
180void at45db041_device::flash_set_io(UINT8* data, UINT32 size, UINT32 pos)
181{
182   m_io.data = data;
183   m_io.size = size;
184   m_io.pos  = pos;
185}
186
187UINT32 at45db041_device::flash_get_page_addr()
188{
189   return ((m_cmd.data[1] & 0x0F) << 7) | ((m_cmd.data[2] & 0xFE) >> 1);
190}
191
192UINT32 at45db041_device::flash_get_byte_addr()
193{
194   return ((m_cmd.data[2] & 0x01) << 8) | ((m_cmd.data[3] & 0xFF) >> 0);
195}
196
197UINT32 at45db081_device::flash_get_page_addr()
198{
199   return ((m_cmd.data[1] & 0x1F) << 7) | ((m_cmd.data[2] & 0xFE) >> 1);
200}
201
202UINT32 at45db161_device::flash_get_page_addr()
203{
204   return ((m_cmd.data[1] & 0x3F) << 6) | ((m_cmd.data[2] & 0xFC) >> 2);
205}
206
207UINT32 at45db161_device::flash_get_byte_addr()
208{
209   return ((m_cmd.data[2] & 0x03) << 8) | ((m_cmd.data[3] & 0xFF) >> 0);
210}
211
212void at45db041_device::write_byte(UINT8 data)
213{
214   // check mode
215   if (m_mode != FLASH_MODE_SI) return;
216   // process byte
217   if (m_cmd.size < 8)
218   {
219      UINT8 opcode;
220      _logerror( 2, ("at45dbxx_write_byte (%02X)\n", data));
221      // add to command buffer
222      m_cmd.data[m_cmd.size++] = data;
223      // check opcode
224      opcode = m_cmd.data[0];
225      switch (opcode)
226      {
227         // status register read
228         case FLASH_CMD_57 :
229         {
230            // 8 bits command
231            if (m_cmd.size == 1)
232            {
233               _logerror( 1, ("at45dbxx opcode %02X - status register read\n", opcode));
234               m_status = (m_status & 0xC7) | device_id(); // 80 = busy / 40 = compare fail
235               flash_set_io(&m_status, 1, 0);
236               m_mode = FLASH_MODE_SO;
237               m_cmd.size = 8;
238            }
239         }
240         break;
241         // main memory page to buffer 1 compare
242         case FLASH_CMD_60 :
243         {
244            // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits don't care
245            if (m_cmd.size == 4)
246            {
247               UINT32 page;
248               UINT8 comp;
249               page = flash_get_page_addr();
250               _logerror( 1, ("at45dbxx opcode %02X - main memory page to buffer 1 compare [%04X]\n", opcode, page));
251               comp = memcmp( m_data + page * page_size(), m_buffer1, page_size()) == 0 ? 0 : 1;
252               if (comp) m_status |= 0x40; else m_status &= ~0x40;
253               _logerror( 1, ("at45dbxx page compare %s\n", comp ? "failure" : "success"));
254               m_mode = FLASH_MODE_SI;
255               m_cmd.size = 8;
256            }
257         }
258         break;
259         // main memory page read
260         case FLASH_CMD_52 :
261         {
262            // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address + 32 bits don't care
263            if (m_cmd.size == 8)
264            {
265               UINT32 page, byte;
266               page = flash_get_page_addr();
267               byte = flash_get_byte_addr();
268               _logerror( 1, ("at45dbxx opcode %02X - main memory page read [%04X/%04X]\n", opcode, page, byte));
269               flash_set_io(m_data + page * page_size(), page_size(), byte);
270               m_mode = FLASH_MODE_SO;
271               m_cmd.size = 8;
272            }
273         }
274         break;
275         // main memory page program through buffer 1
276         case FLASH_CMD_82 :
277         {
278            // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address
279            if (m_cmd.size == 4)
280            {
281               UINT32 page, byte;
282               page = flash_get_page_addr();
283               byte = flash_get_byte_addr();
284               _logerror( 1, ("at45dbxx opcode %02X - main memory page program through buffer 1 [%04X/%04X]\n",opcode, page, byte));
285               flash_set_io(m_buffer1, page_size(), byte);
286               memset( m_buffer1, 0xFF, page_size());
287               m_mode = FLASH_MODE_SI;
288               m_cmd.size = 8;
289            }
290         }
291         break;
292         // other
293         default :
294         {
295            _logerror( 1, ("at45dbxx opcode %02X - unknown\n", opcode));
296            m_cmd.data[0] = 0;
297            m_cmd.size = 0;
298         }
299         break;
300      }
301   }
302   else
303   {
304      _logerror( 2, ("at45dbxx_write_byte (%02X) (%03d/%03d)\n", data, m_io.pos + 1, m_io.size));
305      // store byte
306      m_io.data[m_io.pos] = data;
307      m_io.pos++;
308      if (m_io.pos == m_io.size) m_io.pos = 0;
309   }
310}
311
312READ_LINE_MEMBER(at45db041_device::so_r)
313{
314   if (m_pin.cs == 0) return 0;
315   return m_pin.so;
316}
317
318WRITE_LINE_MEMBER(at45db041_device::si_w)
319{
320   if (m_pin.cs == 0) return;
321   m_pin.si = state;
322}
323
324WRITE_LINE_MEMBER(at45db041_device::cs_w)
325{
326   // check if changed
327   if (m_pin.cs == state) return;
328   // cs low-to-high
329   if (state != 0)
330   {
331      // complete program command
332      if ((m_cmd.size >= 4) && (m_cmd.data[0] == FLASH_CMD_82))
333      {
334         UINT32 page, byte;
335         page = flash_get_page_addr();
336         byte = flash_get_byte_addr();
337         _logerror( 1, ("at45dbxx - program data stored in buffer 1 into selected page in main memory [%04X/%04X]\n", page, byte));
338         memcpy( m_data + page * page_size(), m_buffer1, page_size());
339      }
340      // reset
341      at45db041_device::device_reset();
342   }
343   // save cs
344   m_pin.cs = state;
345}
346
347WRITE_LINE_MEMBER(at45db041_device::sck_w)
348{
349   // check if changed
350   if (m_pin.sck == state) return;
351   // sck high-to-low
352   if (state == 0)
353   {
354      // output (part 1)
355      if (m_so_bits == 8)
356      {
357         m_so_bits = 0;
358         m_so_byte = read_byte();
359      }
360      // input
361      if (m_pin.si) m_si_byte = m_si_byte | (1 << m_si_bits);
362      m_si_bits++;
363      if (m_si_bits == 8)
364      {
365         m_si_bits = 0;
366         write_byte(m_si_byte);
367         m_si_byte = 0;
368      }
369      // output (part 2)
370      m_pin.so = (m_so_byte >> m_so_bits) & 1;
371      m_so_bits++;
372   }
373   // save sck
374   m_pin.sck = state;
375}
Property changes on: trunk/src/emu/machine/at45dbxx.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/at45dbxx.h
r0r21685
1/*
2
3    Atmel Serial DataFlash
4
5    (c) 2001-2007 Tim Schuerewegen
6
7    AT45DB041 -  528 KByte
8    AT45DB081 - 1056 KByte
9    AT45DB161 - 2112 KByte
10
11*/
12
13#ifndef _AT45DBXX_H_
14#define _AT45DBXX_H_
15
16#include "emu.h"
17
18
19//**************************************************************************
20//  INTERFACE CONFIGURATION MACROS
21//**************************************************************************
22
23#define MCFG_AT45DB041_ADD(_tag) \
24   MCFG_DEVICE_ADD(_tag, AT45DB041, 0)
25
26#define MCFG_AT45DB081_ADD(_tag) \
27   MCFG_DEVICE_ADD(_tag, AT45DB081, 0)
28
29#define MCFG_AT45DB161_ADD(_tag) \
30   MCFG_DEVICE_ADD(_tag, AT45DB161, 0)
31
32
33// ======================> at45db041_device
34
35class at45db041_device : public device_t,
36                     public device_nvram_interface
37{
38public:
39   at45db041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
40   at45db041_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
41
42   DECLARE_WRITE_LINE_MEMBER(cs_w);
43   DECLARE_WRITE_LINE_MEMBER(sck_w);
44   DECLARE_WRITE_LINE_MEMBER(si_w);
45   DECLARE_READ_LINE_MEMBER(so_r);
46
47   UINT8 *get_ptr() {  return m_data;  }
48
49protected:
50   // device-level overrides
51   virtual void device_start();
52   virtual void device_reset();
53
54   // device_nvram_interface overrides
55   virtual void nvram_default();
56   virtual void nvram_read(emu_file &file);
57   virtual void nvram_write(emu_file &file);
58
59protected:
60   virtual int num_pages() const { return 2048; }
61   virtual int page_size() const { return 264; }
62   virtual UINT8 device_id() const { return 0x18; }
63
64   UINT8 read_byte();
65   void flash_set_io(UINT8* data, UINT32 size, UINT32 pos);
66   virtual UINT32 flash_get_page_addr();
67   virtual UINT32 flash_get_byte_addr();
68   void write_byte(UINT8 data);
69
70   // internal state
71   UINT8 *     m_data;
72   UINT32      m_size;
73   UINT8       m_mode;
74   UINT8       m_status;
75   UINT8 *     m_buffer1;
76   UINT8 *     m_buffer2;
77   UINT8       m_si_byte;
78   UINT8       m_si_bits;
79   UINT8       m_so_byte;
80   UINT8       m_so_bits;
81
82   struct AT45DBXX_PINS
83   {
84      int cs;    // chip select
85      int sck;   // serial clock
86      int si;    // serial input
87      int so;    // serial output
88      int wp;    // write protect
89      int reset; // reset
90      int busy;  // busy
91   } m_pin;
92
93   struct AT45DBXX_IO
94   {
95      UINT8 *data;
96      UINT32 size;
97      UINT32 pos;
98   } m_io;
99
100   struct AT45DBXX_CMD
101   {
102      UINT8 data[8];
103      UINT8 size;
104   } m_cmd;
105};
106
107// ======================> at45db081_device
108
109class at45db081_device : public at45db041_device
110{
111public:
112   at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
113
114protected:
115   virtual int num_pages() const { return 4096; }
116   virtual int page_size() const { return 264;  }
117   virtual UINT8 device_id() const { return 0x20; }
118
119   virtual UINT32 flash_get_page_addr();
120};
121
122// ======================> at45db161_device
123
124class at45db161_device : public at45db041_device
125{
126public:
127   at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
128
129protected:
130   virtual int num_pages() const { return 4096; }
131   virtual int page_size() const { return 528;  }
132   virtual UINT8 device_id() const { return 0x28; }
133
134   virtual UINT32 flash_get_page_addr();
135   virtual UINT32 flash_get_byte_addr();
136};
137
138
139// device type definition
140extern const device_type AT45DB041;
141extern const device_type AT45DB081;
142extern const device_type AT45DB161;
143
144#endif
Property changes on: trunk/src/emu/machine/at45dbxx.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/er59256.c
r0r21685
1/*********************************************************************
2
3    er59256.c
4
5    Microchip ER59256 serial eeprom.
6
7
8*********************************************************************/
9
10#include "emu.h"
11#include "er59256.h"
12
13/* LOGLEVEL 0=no logging, 1=just commands and data, 2=everything ! */
14
15#define LOGLEVEL            0
16
17#define LOG(level,...)      if(LOGLEVEL>=level) logerror(__VA_ARGS__)
18#define LOG_BITS(bits)      logerror("CS=%d CK=%d DI=%d DO=%d", (bits&CS_MASK) ? 1 : 0, (bits&CK_MASK) ? 1 : 0, (bits&DI_MASK) ? 1 : 0, (bits&DO_MASK) ? 1 : 0)
19
20/***************************************************************************
21    TYPE DEFINITIONS
22***************************************************************************/
23
24struct er59256_t
25{
26   /* The actual memory */
27   UINT16  eerom[EEROM_WORDS];
28
29   /* Bits as they appear on the io pins, current state */
30   UINT8   io_bits;
31
32   /* Bits as they appear on the io pins, previous state */
33   UINT8   old_io_bits;
34
35
36   /* the 16 bit shift in/out reg */
37   UINT16  in_shifter;
38   UINT32  out_shifter;
39
40   /* Count of bits received since last CS low->high */
41   UINT8   bitcount;
42
43   /* Command & addresss */
44   UINT8   command;
45
46   /* Write enable and write in progress flags */
47   UINT8   flags;
48};
49
50/***************************************************************************
51    FUNCTION PROTOTYPES
52************************************************************************/
53
54static void decode_command(er59256_t *er59256);
55
56/***************************************************************************
57    INLINE FUNCTIONS
58***************************************************************************/
59
60INLINE er59256_t *get_token(device_t *device)
61{
62   assert(device->type() == ER59256);
63   return (er59256_t *) downcast<er59256_device *>(device)->token();
64}
65
66
67/***************************************************************************
68    IMPLEMENTATION
69***************************************************************************/
70
71void er59256_preload_rom(device_t *device, const UINT16 *rom_data, int count)
72{
73   er59256_t *er59256 = get_token(device);
74   int WordNo;
75
76   logerror("Preloading %d words of data\n",count);
77
78   if(count>EEROM_WORDS)
79      memcpy(&er59256->eerom,rom_data,count*2);
80   else
81      memcpy(&er59256->eerom,rom_data,EEROM_WORDS*2);
82
83   for(WordNo=0;WordNo<EEROM_WORDS;WordNo++)
84      logerror("%04X ",er59256->eerom[WordNo]);
85
86   logerror("\n");
87}
88
89UINT8 er59256_data_loaded(device_t *device)
90{
91   er59256_t *er59256 = get_token(device);
92
93   return (er59256->flags & FLAG_DATA_LOADED) ? 1 : 0;
94}
95
96/*-------------------------------------------------
97    DEVICE_START( er59256 )
98-------------------------------------------------*/
99
100static DEVICE_START( er59256 )
101{
102   er59256_t *er59256 = get_token(device);
103
104   memset(er59256, 0x00, sizeof(er59256_t));
105
106   // Start with rom defaulted to erased
107   memset(&er59256->eerom, 0xFF, EEROM_WORDS*2);
108
109   er59256->command=CMD_INVALID;
110
111   er59256->flags&= ~FLAG_DATA_LOADED;
112}
113
114static DEVICE_STOP( er59256 )
115{
116   /* Save contents of eerom */
117}
118
119void er59256_set_iobits(device_t *device, UINT8 newbits)
120{
121   er59256_t *er59256 = get_token(device);
122   //UINT32  bit;
123
124   // Make sure we only apply valid bits
125   newbits&=ALL_MASK;
126
127   if(LOGLEVEL>1)
128   {
129      logerror("er59256:newbits=%02X : ",newbits);
130      LOG_BITS(newbits);
131      logerror(" io_bits=%02X : ",er59256->io_bits);
132      LOG_BITS(er59256->io_bits);
133      logerror(" old_io_bits=%02X : ",er59256->old_io_bits);
134      LOG_BITS(er59256->old_io_bits);
135      logerror(" bitcount=%d, in_shifter=%04X, out_shifter=%05X, flags=%02X\n",er59256->bitcount,er59256->in_shifter,er59256->out_shifter,er59256->flags);
136   }
137   // Only do anything if the inputs have changed
138   if((newbits&IN_MASK)!=(er59256->io_bits&IN_MASK))
139   {
140      // save the current state, then set the new one, remembering to preserve data out
141      er59256->old_io_bits=er59256->io_bits;
142      er59256->io_bits=(newbits & ~DO_MASK) | (er59256->old_io_bits&DO_MASK);
143
144      if(CS_RISE(er59256))
145      {
146         er59256->flags&=~FLAG_START_BIT;
147         er59256->command=CMD_INVALID;
148      }
149
150      if(LOGLEVEL>1)
151      {
152         if(CK_RISE(er59256)) logerror("er59256:CK rise\n");
153         if(CS_RISE(er59256)) logerror("er59256:CS rise\n");
154         if(CK_FALL(er59256)) logerror("er59256:CK fall\n");
155         if(CS_FALL(er59256)) logerror("er59256:CS fall\n");
156      }
157
158      if(CK_RISE(er59256) && CS_VALID(er59256))
159      {
160         if((STARTED(er59256)==0) && (GET_DI(er59256)==1))
161         {
162            er59256->bitcount=0;
163            er59256->flags|=FLAG_START_BIT;
164         }
165         else
166         {
167            SHIFT_IN(er59256);
168            er59256->bitcount++;
169
170            if(er59256->bitcount==CMD_BITLEN)
171               decode_command(er59256);
172
173            if((er59256->bitcount==WRITE_BITLEN) && ((er59256->command & CMD_MASK)==CMD_WRITE))
174            {
175               er59256->eerom[er59256->command & ADDR_MASK]=er59256->in_shifter;
176               LOG(1,"er59256:write[%02X]=%04X\n",(er59256->command & ADDR_MASK),er59256->in_shifter);
177               er59256->command=CMD_INVALID;
178            }
179            LOG(1,"out_shifter=%05X, io_bits=%02X\n",er59256->out_shifter,er59256->io_bits);
180            SHIFT_OUT(er59256);
181         }
182
183         LOG(2,"io_bits:out=%02X\n",er59256->io_bits);
184      }
185   }
186}
187
188UINT8 er59256_get_iobits(device_t *device)
189{
190   er59256_t *er59256 = get_token(device);
191
192   return er59256->io_bits;
193}
194
195
196static void decode_command(er59256_t *er59256)
197{
198   er59256->out_shifter=0x0000;
199   er59256->command=(er59256->in_shifter & (CMD_MASK | ADDR_MASK));
200
201   switch(er59256->command & CMD_MASK)
202   {
203      case CMD_READ   : er59256->out_shifter=er59256->eerom[er59256->command & ADDR_MASK];
204                     LOG(1,"er59256:read[%02X]=%04X\n",(er59256->command&ADDR_MASK),er59256->eerom[er59256->command & ADDR_MASK]);
205                     break;
206      case CMD_WRITE  : break;
207      case CMD_ERASE  : if (WRITE_ENABLED(er59256)) er59256->eerom[er59256->command & ADDR_MASK]=0xFF;
208                     LOG(1,"er59256:erase[%02X]\n",(er59256->command&ADDR_MASK));
209                     break;
210      case CMD_EWEN   : er59256->flags|=FLAG_WRITE_EN;
211                     LOG(1,"er59256:erase/write enabled\n");
212                     break;
213      case CMD_EWDS   : er59256->flags&=~FLAG_WRITE_EN;
214                     LOG(1,"er59256:erase/write disabled\n");
215                     break;
216      case CMD_ERAL   : if (WRITE_ENABLED(er59256)) memset(&er59256->eerom, 0xFF, EEROM_WORDS*2);
217                     LOG(1,"er59256:erase all\n");
218                     break;
219   }
220
221   if ((er59256->command & CMD_MASK)!=CMD_WRITE)
222      er59256->command=CMD_INVALID;
223}
224
225const device_type ER59256 = &device_creator<er59256_device>;
226
227er59256_device::er59256_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
228   : device_t(mconfig, ER59256, "Microchip ER59256 serial eeprom.", tag, owner, clock)
229{
230   m_token = global_alloc_clear(er59256_t);
231}
232
233//-------------------------------------------------
234//  device_config_complete - perform any
235//  operations now that the configuration is
236//  complete
237//-------------------------------------------------
238
239void er59256_device::device_config_complete()
240{
241}
242
243//-------------------------------------------------
244//  device_start - device-specific startup
245//-------------------------------------------------
246
247void er59256_device::device_start()
248{
249   DEVICE_START_NAME( er59256 )(this);
250}
251
252//-------------------------------------------------
253//  device_stop - device-specific stop
254//-------------------------------------------------
255
256void er59256_device::device_stop()
257{
258   DEVICE_STOP_NAME( er59256 )(this);
259}
Property changes on: trunk/src/emu/machine/er59256.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/er59256.h
r0r21685
1/*********************************************************************
2
3    er59256.h
4
5    Microchip ER59256 serial eeprom.
6
7
8*********************************************************************/
9
10#ifndef _ER59256_H_
11#define _ER59256_H_
12
13/***************************************************************************
14    MACROS
15***************************************************************************/
16
17class er59256_device : public device_t
18{
19public:
20   er59256_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
21   ~er59256_device() { global_free(m_token); }
22
23   // access to legacy token
24   void *token() const { assert(m_token != NULL); return m_token; }
25protected:
26   // device-level overrides
27   virtual void device_config_complete();
28   virtual void device_start();
29   virtual void device_stop();
30private:
31   // internal state
32   void *m_token;
33};
34
35extern const device_type ER59256;
36
37
38#define MCFG_ER59256_ADD(_tag)  \
39   MCFG_DEVICE_ADD((_tag), ER59256, 0)
40
41/***************************************************************************
42    CONSTANTS
43***************************************************************************/
44
45#define EEROM_WORDS         0x10
46
47#define CK_SHIFT            0x00
48#define DI_SHIFT            0x01
49#define DO_SHIFT            0x02
50#define CS_SHIFT            0x03
51
52#define CK_MASK             (1<<CK_SHIFT)
53#define DI_MASK             (1<<DI_SHIFT)
54#define DO_MASK             (1<<DO_SHIFT)
55#define CS_MASK             (1<<CS_SHIFT)
56
57#define ALL_MASK            (CK_MASK | DI_MASK | DO_MASK | CS_MASK)
58#define IN_MASK             (CK_MASK | DI_MASK | CS_MASK)
59
60#define GET_CK(eep)         ((eep->io_bits & CK_MASK) >> CK_SHIFT)
61#define GET_DI(eep)         ((eep->io_bits & DI_MASK) >> DI_SHIFT)
62#define GET_DO(eep)         ((eep->io_bits & DO_MASK) >> DO_SHIFT)
63#define GET_CS(eep)         ((eep->io_bits & CS_MASK) >> CS_SHIFT)
64
65#define SET_CK(eep,data)    eep->io_bits=((eep->io_bits & ~CK_MASK) | ((data & 0x01) << CK_SHIFT))
66#define SET_DI(eep,data)    eep->io_bits=((eep->io_bits & ~DI_MASK) | ((data & 0x01) << DI_SHIFT))
67#define SET_DO(eep,data)    eep->io_bits=((eep->io_bits & ~DO_MASK) | ((data & 0x01) << DO_SHIFT))
68#define SET_CS(eep,data)    eep->io_bits=((eep->io_bits & ~CS_MASK) | ((data & 0x01) << CS_SHIFT))
69
70#define CK_RISE(eep)        ((eep->io_bits & CK_MASK) & ~(eep->old_io_bits & CK_MASK))
71#define CS_RISE(eep)        ((eep->io_bits & CS_MASK) & ~(eep->old_io_bits & CS_MASK))
72#define CS_VALID(eep)       ((eep->io_bits & CS_MASK) & (eep->old_io_bits & CS_MASK))
73
74#define CK_FALL(eep)        (~(eep->io_bits & CK_MASK) & (eep->old_io_bits & CK_MASK))
75#define CS_FALL(eep)        (~(eep->io_bits & CS_MASK) & (eep->old_io_bits & CS_MASK))
76
77
78#define SHIFT_IN(eep)       eep->in_shifter=(eep->in_shifter<<1) | GET_DI(eep)
79#define SHIFT_OUT(eep)      SET_DO(eep,(eep->out_shifter & 0x10000)>>16); eep->out_shifter=(eep->out_shifter<<1)
80
81#define CMD_READ            0x80
82#define CMD_WRITE           0x40
83#define CMD_ERASE           0xC0
84#define CMD_EWEN            0x30
85#define CMD_EWDS            0x00
86#define CMD_ERAL            0x20
87#define CMD_INVALID         0xF0
88
89#define CMD_MASK            0xF0
90#define ADDR_MASK           0x0F
91
92// CMD_BITLEN is 1 start bit plus 4 command bits plus 4 address bits
93#define CMD_BITLEN          8
94#define DATA_BITLEN         16
95#define WRITE_BITLEN        CMD_BITLEN+DATA_BITLEN
96
97#define FLAG_WRITE_EN       0x01
98#define FLAG_START_BIT      0x02
99#define FLAG_DATA_LOADED    0x04
100
101#define WRITE_ENABLED(eep)  ((eep->flags & FLAG_WRITE_EN) ? 1 : 0)
102#define STARTED(eep)        ((eep->flags & FLAG_START_BIT) ? 1 : 0)
103
104/***************************************************************************
105    FUNCTION PROTOTYPES
106***************************************************************************/
107
108void er59256_set_iobits(device_t *device, UINT8 newbits);
109UINT8 er59256_get_iobits(device_t *device);
110void er59256_preload_rom(device_t *device, const UINT16 *rom_data, int count);
111UINT8 er59256_data_loaded(device_t *device);
112#endif
Property changes on: trunk/src/emu/machine/er59256.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/at29040a.c
r0r21685
1/*
2    Atmel at29c040a flash EEPROM
3
4    512k*8 FEEPROM, organized in pages of 256 bytes.
5
6    References:
7    Datasheets were found on Atmel's site (www.atmel.com)
8
9    Raphael Nabet 2003
10
11    September 2010: Rewritten as device
12    February 2012: Rewritten as class
13*/
14
15#include "at29040a.h"
16
17#define VERBOSE 2
18#define LOG logerror
19
20#define FEEPROM_SIZE        0x80000
21#define SECTOR_SIZE         0x00100
22#define BOOT_BLOCK_SIZE     0x04000
23
24#define ADDRESS_MASK        0x7ffff
25#define SECTOR_ADDRESS_MASK 0x7ff00
26#define BYTE_ADDRESS_MASK   0x000ff
27
28#define PRG_TIMER 1
29
30#define VERSION 0
31
32/*
33    Constructor.
34*/
35at29040a_device::at29040a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
36: device_t(mconfig, AT29040A, "ATMEL 29040A 512K*8 FEEPROM", tag, owner, clock),
37   device_nvram_interface(mconfig, *this)
38{
39}
40
41//-------------------------------------------------
42//  nvram_default - called to initialize NVRAM to
43//  its default state
44//-------------------------------------------------
45
46void at29040a_device::nvram_default()
47{
48   memset(m_eememory, 0, FEEPROM_SIZE+2);
49}
50
51//-------------------------------------------------
52//  nvram_read - called to read NVRAM from the
53//  .nv file
54//-------------------------------------------------
55
56void at29040a_device::nvram_read(emu_file &file)
57{
58   file.read(m_eememory, FEEPROM_SIZE+2);
59}
60
61//-------------------------------------------------
62//  nvram_write - called to write NVRAM to the
63//  .nv file
64//-------------------------------------------------
65
66void at29040a_device::nvram_write(emu_file &file)
67{
68   m_eememory[0] = VERSION;
69   file.write(m_eememory, FEEPROM_SIZE+2);
70}
71
72/*
73    programming timer callback
74*/
75void at29040a_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
76{
77   switch (m_pgm)
78   {
79   case PGM_1:
80      /* programming cycle timeout */
81      if (VERBOSE>7) LOG("at29040a: Programming cycle timeout\n");
82      m_pgm = PGM_0;
83      break;
84
85   case PGM_2:
86      /* programming cycle start */
87      if (VERBOSE>7) LOG("at29040a: Sector write start\n");
88      m_pgm = PGM_3;
89      /* max delay 10ms, typical delay 5 to 7 ms */
90      m_programming_timer->adjust(attotime::from_msec(5));
91      break;
92
93   case PGM_3:
94      /* programming cycle end */
95      memcpy(m_eememory + 2 + (m_programming_last_offset & ~0xff), m_programming_buffer, SECTOR_SIZE);
96      if (VERBOSE>7) LOG("at29040a: Sector write completed at location %04x + 2\n", (m_programming_last_offset & ~0xff));
97      if (m_enabling_sdb)
98      {
99         m_sdp = true;
100      }
101      if (m_disabling_sdb)
102      {
103         m_sdp = false;
104      }
105      if (VERBOSE>7) LOG("at29040a: Software data protection = %d\n", m_sdp);
106
107      m_pgm = PGM_0;
108      m_enabling_sdb = false;
109      m_disabling_sdb = false;
110
111      break;
112
113   default:
114      if (VERBOSE>1) LOG("internal error in %s %d\n", __FILE__, __LINE__);
115      break;
116   }
117}
118
119void at29040a_device::sync_flags()
120{
121   if (m_lower_bbl) m_eememory[1] |= 0x04;
122   else m_eememory[1] &= ~0x04;
123
124   if (m_higher_bbl) m_eememory[1] |= 0x02;
125   else m_eememory[1] &= ~0x02;
126
127   if (m_sdp) m_eememory[1] |= 0x01;
128   else m_eememory[1] &= ~0x01;
129}
130
131/*
132    read a byte from FEEPROM
133*/
134READ8_MEMBER( at29040a_device::read )
135{
136   int reply;
137
138   offset &= ADDRESS_MASK;
139
140   /* reading in the midst of any command sequence cancels it (right???) */
141   m_cmd = CMD_0;
142   m_long_sequence = false;
143   // m_higher_bbl = true;         // who says that?
144
145   sync_flags();
146
147   /* reading before the start of a programming cycle cancels it (right???) */
148   if (m_pgm == PGM_1)
149   {
150      // attempt to access a locked out boot block: cancel programming
151      // command if necessary
152      m_pgm = PGM_0;
153      m_enabling_sdb = false;
154      m_disabling_sdb = false;
155      m_programming_timer->adjust(attotime::never);
156   }
157
158   if (m_id_mode)
159   {
160      switch (offset)
161      {
162      case 0x00000:
163         reply = 0x1f;       // Manufacturer code
164         break;
165
166      case 0x00001:
167         reply = 0xa4;       // Device code
168         break;
169
170      case 0x00002:
171         reply = m_lower_bbl? 0xff : 0xfe;
172         break;
173
174      case 0x7fff2:
175         reply = m_higher_bbl? 0xff : 0xfe;
176         break;
177
178      default:
179         reply = 0;
180         break;
181      }
182   }
183   else if ((m_pgm == PGM_2) || (m_pgm == PGM_3))
184   {
185      if (m_pgm == PGM_2)
186      {   // DATA* polling starts the programming cycle (right???)
187         m_pgm = PGM_3;
188         /* max delay 10ms, typical delay 5 to 7 ms */
189         m_programming_timer->adjust(attotime::from_msec(5));
190      }
191
192      reply = m_toggle_bit? 0x02 : 0x00;
193      m_toggle_bit = !m_toggle_bit;
194
195      if ((offset == m_programming_last_offset) && (! (m_programming_buffer[m_programming_last_offset & 0xff] & 0x01)))
196         reply |= 0x01;
197   }
198   else
199      reply = m_eememory[offset+2];
200
201   if (VERBOSE>7) LOG("at29040a: %05x -> %02x\n", offset, reply);
202
203   return reply;
204}
205
206/*
207    Write a byte to FEEPROM
208*/
209WRITE8_MEMBER( at29040a_device::write )
210{
211   offset &= ADDRESS_MASK;
212   if (VERBOSE>7) LOG("at29040a: %05x <- %02x\n", offset, data);
213
214   /* The special CFI commands assume a smaller address space according */
215   /* to the specification ("address format A14-A0") */
216   offs_t cfi_offset = offset & 0x7fff;
217
218   if (m_enabling_bbl)
219   {
220      if (VERBOSE>7) LOG("at29040a: Enabling boot block lockout\n");
221      m_enabling_bbl = false;
222
223      if ((offset == 0x00000) && (data == 0x00))
224      {
225         if (VERBOSE>7) LOG("at29040a: Enabling lower boot block lockout\n");
226         m_lower_bbl = true;
227         sync_flags();
228         return;
229      }
230      else
231      {
232         if ((offset == 0x7ffff) && (data == 0xff))
233         {
234            if (VERBOSE>7) LOG("at29040a: Enabling higher boot block lockout\n");
235            m_higher_bbl = true;
236            sync_flags();
237            return;
238         }
239         else
240         {
241            if (VERBOSE>1) LOG("at29040a: Invalid boot block specification: %05x/%02x\n", offset, data);
242         }
243      }
244   }
245
246   switch (m_cmd)
247   {
248   case CMD_0:
249      if ((cfi_offset == 0x5555) && (data == 0xaa))
250      {
251         if (VERBOSE>7) LOG("at29040a: Command sequence started\n");
252         m_cmd = CMD_1;
253      }
254      else
255      {
256         m_cmd = CMD_0;
257         m_long_sequence = false;
258      }
259      break;
260
261   case CMD_1:
262      if ((cfi_offset == 0x2aaa) && (data == 0x55))
263      {
264         m_cmd = CMD_2;
265      }
266      else
267      {
268         m_cmd = CMD_0;
269         m_long_sequence = false;
270         if (VERBOSE>7) LOG("at29040a: Command sequence aborted\n");
271      }
272      break;
273
274   case CMD_2:
275      if (cfi_offset == 0x5555)
276      {
277         if (!m_long_sequence)
278            if (VERBOSE>7) LOG("at29040a: Command sequence completed\n");
279
280         m_pgm = PGM_0;
281         m_enabling_sdb = false;
282         m_disabling_sdb = false;
283         m_programming_timer->adjust(attotime::never);
284
285         /* process command */
286         switch (data)
287         {
288         case 0x10:
289            /*  Software chip erase */
290            if (m_long_sequence)
291            {
292               if (m_lower_bbl || m_higher_bbl)
293               {
294                  if (VERBOSE>1) LOG("at29040a: Chip erase sequence deactivated due to previous boot block lockout.\n");
295               }
296               else
297               {
298                  if (VERBOSE>7) LOG("at29040a: Erase chip\n");
299                  memset(m_eememory+2, 0xff, FEEPROM_SIZE);
300               }
301            }
302            break;
303
304         case 0x20:
305            /* Software data protection disable */
306            if (VERBOSE>7) LOG("at29040a: Software data protection disable\n");
307            // The complete sequence is aa-55-80-aa-55-20
308            // so we need a 80 before, else the sequence is invalid
309            if (m_long_sequence)
310            {
311               m_pgm = PGM_1;
312               m_disabling_sdb = true;
313               /* set command timeout (right???) */
314               //m_programming_timer->adjust(attotime::from_usec(150), id, 0.);
315            }
316            break;
317
318         case 0x40:
319            /* Boot block lockout enable */
320            // Complete sequence is aa-55-80-aa-55-40
321            if (VERBOSE>7) LOG("at29040a: Boot block lockout enable\n");
322            if (m_long_sequence) m_enabling_bbl = true;
323            break;
324
325         case 0x80:
326            m_long_sequence = true;
327            break;
328
329         case 0x90:
330            /* Software product identification entry */
331            if (VERBOSE>7) LOG("at29040a: Identification mode (start)\n");
332            m_id_mode = true;
333            break;
334
335         case 0xa0:
336            /* Software data protection enable */
337            if (VERBOSE>7) LOG("at29040a: Software data protection enable\n");
338            m_pgm = PGM_1;
339            m_enabling_sdb = true;
340            /* set command timeout (right???) */
341            //m_programming_timer->adjust(attotime::from_usec(150), id, 0.);
342            break;
343
344         case 0xf0:
345            /* Software product identification exit */
346            if (VERBOSE>7) LOG("at29040a: Identification mode (end)\n");
347            m_id_mode = false;
348            break;
349         }
350         m_cmd = CMD_0;
351         if (data != 0x80) m_long_sequence = false;
352
353         /* return, because we don't want to write the EEPROM with the command byte */
354         return;
355      }
356      else
357      {
358         m_cmd = CMD_0;
359         m_long_sequence = false;
360      }
361   }
362   if ((m_pgm == PGM_2)
363         && ((offset & ~0xff) != (m_programming_last_offset & ~0xff)))
364   {
365      /* cancel current programming cycle */
366      if (VERBOSE>7) LOG("at29040a: invalid sector change (from %05x to %05x); cancel programming cycle\n",(offset & ~0xff), (m_programming_last_offset & ~0xff));
367      m_pgm = PGM_0;
368      m_enabling_sdb = false;
369      m_disabling_sdb = false;
370      m_programming_timer->adjust(attotime::never);
371   }
372
373   if (((m_pgm == PGM_0) && !m_sdp)  // write directly
374      || (m_pgm == PGM_1))          // write after unlocking
375   {
376      if (((offset < BOOT_BLOCK_SIZE) && m_lower_bbl)
377         || ((offset >= FEEPROM_SIZE-BOOT_BLOCK_SIZE) && m_higher_bbl))
378      {
379         // attempt to access a locked out boot block: cancel programming
380         // command if necessary
381         if (VERBOSE>7) LOG("at29040a: attempt to access a locked out boot block: offset = %05x, lowblock=%d, highblock=%d\n", offset, m_lower_bbl, m_higher_bbl);
382
383         m_pgm = PGM_0;
384         m_enabling_sdb = false;
385         m_disabling_sdb = false;
386      }
387      else
388      {   /* enter programming mode */
389         if (VERBOSE>7) LOG("at29040a: enter programming mode (m_pgm=%d)\n", m_pgm);
390         memset(m_programming_buffer, 0xff, SECTOR_SIZE);
391         m_pgm = PGM_2;
392      }
393   }
394   if (m_pgm == PGM_2)
395   {
396      /* write data to programming buffer */
397      if (VERBOSE>7) LOG("at29040a: Write data to programming buffer\n");
398      m_programming_buffer[offset & 0xff] = data;
399      m_programming_last_offset = offset;
400      m_programming_timer->adjust(attotime::from_usec(150));  // next byte must be written before the timer expires
401   }
402}
403
404void at29040a_device::device_start(void)
405{
406   m_programming_buffer = (UINT8*)malloc(SECTOR_SIZE);
407   m_programming_timer = timer_alloc(PRG_TIMER);
408
409   m_eememory = (UINT8*)malloc(FEEPROM_SIZE+2);
410}
411
412void at29040a_device::device_stop(void)
413{
414   free(m_programming_buffer);
415   free(m_eememory);
416}
417
418void at29040a_device::device_reset(void)
419{
420   if (m_eememory[0] != VERSION)
421   {
422      if (VERBOSE>1) LOG("AT29040A: Warning: Version mismatch; expected %d but found %d for %s. Resetting.\n", VERSION, m_eememory[0], tag());
423      m_eememory[0] = 0;
424      m_eememory[1] = 0;
425   }
426
427   m_lower_bbl =   ((m_eememory[1] & 0x04)!=0);
428   m_higher_bbl =  ((m_eememory[1] & 0x02)!=0);
429   m_sdp =         ((m_eememory[1] & 0x01)!=0);
430
431   if (VERBOSE>7) LOG("at29040a (%s): LowerBBL = %d, HigherBBL = %d, SoftDataProt = %d\n", tag(), m_lower_bbl, m_higher_bbl, m_sdp);
432
433   m_id_mode = false;
434   m_cmd = CMD_0;
435   m_enabling_bbl = false;
436   m_long_sequence = false;
437   m_pgm = PGM_0;
438   m_enabling_sdb = false;
439   m_disabling_sdb = false;
440   m_toggle_bit = false;
441   m_programming_last_offset = 0;
442}
443
444const device_type AT29040A = &device_creator<at29040a_device>;
Property changes on: trunk/src/emu/machine/at29040a.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/at29040a.h
r0r21685
1/*
2    ATMEL 29040a
3
4    Michael Zapf
5    September 2010: Rewritten as device
6    February 2012: Rewritten as class
7*/
8
9#ifndef __AT29040__
10#define __AT29040__
11
12#include "emu.h"
13
14extern const device_type AT29040A;
15
16/*
17    at29c40a state
18
19    Command states (CMD_0 is the initial state):
20    CMD_0: default state
21    CMD_1: state after writing aa to 5555
22    CMD_2: state after writing 55 to 2aaa
23
24    Programming states (s_programming_0 is the initial state):
25    PGM_0: default state
26    PGM_1: a program and enable/disable lock command has been executed, but programming has not actually started.
27    PGM_2: the programming buffer is being written to
28    PGM_3: the programming buffer is being burnt to flash ROM
29*/
30enum  s_cmd_t
31{
32   CMD_0 = 0x0,
33   CMD_1 = 0x1,
34   CMD_2 = 0x2
35};
36
37enum  s_pgm_t
38{
39   PGM_0 = 0x0,
40   PGM_1 = 0x1,
41   PGM_2 = 0x2,
42   PGM_3 = 0x3
43};
44
45class at29040a_device : public device_t, public device_nvram_interface
46{
47public:
48   at29040a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
49   DECLARE_READ8_MEMBER( read );
50   DECLARE_WRITE8_MEMBER( write );
51
52protected:
53   virtual void device_start(void);
54   virtual void device_reset(void);
55   virtual void device_stop(void);
56   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
57
58   void nvram_default();
59   void nvram_read(emu_file &file);
60   void nvram_write(emu_file &file);
61
62private:
63   void        sync_flags(void);
64
65   UINT8*      m_eememory;
66
67   bool        m_lower_bbl;        /* set when lower boot block lockout is enabled */
68   bool        m_higher_bbl;       /* set when upper boot block lockout is enabled */
69   bool        m_sdp;              /* set when in software data protect mode */
70
71   bool        m_id_mode;          /* set when in chip id mode */
72   s_cmd_t     m_cmd;              /* command state */
73   bool        m_enabling_bbl;     /* set when a boot block lockout command is expecting its parameter */
74   bool        m_long_sequence;    /* set if 0x80 command has just been executed (some command require this prefix) */
75   s_pgm_t     m_pgm;              /* programming state */
76   bool        m_enabling_sdb;     /* set when a sdp enable command is in progress */
77   bool        m_disabling_sdb;    /* set when a sdp disable command is in progress */
78   bool        m_dirty;            /* set when the memory contents should be set */
79   bool        m_toggle_bit;       // indicates flashing in progress (toggles for each query)
80   UINT8*      m_programming_buffer;
81   int         m_programming_last_offset;
82   emu_timer*  m_programming_timer;
83};
84
85#define MCFG_AT29040A_ADD(_tag )    \
86   MCFG_DEVICE_ADD(_tag, AT29040A, 0)
87
88#endif
Property changes on: trunk/src/emu/machine/at29040a.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/video/dl1416.c
r0r21685
1/*****************************************************************************
2 *
3 * video/dl1416.c
4 *
5 * DL1416
6 *
7 * 4-Digit 16-Segment Alphanumeric Intelligent Display
8 * with Memory/Decoder/Driver
9 *
10 * Notes:
11 *   - Currently supports the DL1416T and by virtue of it being nearly the same, the DL1414.
12 *   - Partial support for DL1416B is available, it just needs the right
13 *     character set and MAME core support for its display.
14 *   - Cursor support is implemented but not tested, as the AIM65 does not
15 *     seem to use it.
16 *
17 * Todo:
18 *   - Is the DL1416A identical to the DL1416T? If not, we need to add
19 *     support for it.
20 *   - Add proper support for DL1414 (pretty much DL1416T without the cursor)
21 *
22 * Changes:
23 *   - 2007-07-30: Initial version.  [Dirk Best]
24 *   - 2008-02-25: Converted to the new device interface.  [Dirk Best]
25 *   - 2008-12-18: Cleanups.  [Dirk Best]
26 *   - 2011-10-08: Changed the ram to store character rather than segment data. [Lord Nightmare]
27 *
28 *
29 * We use the following order for the segments:
30 *
31 *   000 111
32 *  7D  A  E2
33 *  7 D A E 2
34 *  7  DAE  2
35 *   888 999
36 *  6  CBF  3
37 *  6 C B F 3
38 *  6C  B  F3
39 *   555 444
40 *
41 ****************************************************************************/
42
43#include "emu.h"
44#include "dl1416.h"
45
46
47/***************************************************************************
48    CONSTANTS
49***************************************************************************/
50
51#define SEG_UNDEF  (-2)
52#define SEG_BLANK  (0)
53#define SEG_CURSOR (0xffff)
54#define CURSOR_ON  (1)
55#define CURSOR_OFF (0)
56
57/* character set DL1416T */
58static const int dl1416t_segments[128] = {
59   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
60   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
61   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
62   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
63   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
64   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
65   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
66   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
67   0x0000,    0x2421,    0x0480,    0x0f3c,    /*   ! " # */
68   0x0fbb,    0x5f99,    0xa579,    0x4000,    /* $ % & ' */
69   0xc000,    0x3000,    0xff00,    0x0f00,    /* ( ) * + */
70   0x1000,    0x0300,    0x0020,    0x5000,    /* , - . / */
71   0x0ce1,    0x0c00,    0x0561,    0x0d21,    /* 0 1 2 3 */
72   0x0d80,    0x09a1,    0x09e1,    0x0c01,    /* 4 5 6 7 */
73   0x0de1,    0x0da1,    0x0021,    0x1001,    /* 8 9 : ; */
74   0x5030,    0x0330,    0xa030,    0x0a07,    /* < = > ? */
75   0x097f,    0x03cf,    0x0e3f,    0x00f3,    /* @ A B C */
76   0x0c3f,    0x01f3,    0x01c3,    0x02fb,    /* D E F G */
77   0x03cc,    0x0c33,    0x0c63,    0xc1c0,    /* H I J K */
78   0x00f0,    0x60cc,    0xa0cc,    0x00ff,    /* L M N O */
79   0x03c7,    0x80ff,    0x83c7,    0x03bb,    /* P Q R S */
80   0x0c03,    0x00fc,    0x50c0,    0x90cc,    /* T U V W */
81   0xf000,    0x6800,    0x5033,    0x00e1,    /* X Y Z [ */
82   0xa000,    0x001e,    0x9000,    0x0030,    /* \ ] ^ _ */
83   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
84   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
85   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
86   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
87   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
88   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
89   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
90   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF  /* undefined */
91};
92
93
94/***************************************************************************
95    TYPE DEFINITIONS
96***************************************************************************/
97
98struct dl1416_state
99{
100   int write_enable;
101   int chip_enable;
102   int cursor_enable;
103
104   UINT16 digit_ram[4]; // holds the digit code for each position
105   UINT8 cursor_state[4]; // holds the cursor state for each position, 0=off, 1=on
106};
107
108
109/*****************************************************************************
110    INLINE FUNCTIONS
111*****************************************************************************/
112
113INLINE dl1416_state *get_safe_token(device_t *device)
114{
115   assert(device != NULL);
116   assert(device->type() == DL1416B || device->type() == DL1416T);
117
118   return (dl1416_state *)downcast<dl1416_device *>(device)->token();
119}
120
121
122/*****************************************************************************
123    DEVICE INTERFACE
124*****************************************************************************/
125
126static DEVICE_START( dl1416 )
127{
128   dl1416_state *dl1416 = get_safe_token(device);
129
130   /* register for state saving */
131   state_save_register_item(device->machine(), "dl1416", device->tag(), 0, dl1416->chip_enable);
132   state_save_register_item(device->machine(), "dl1416", device->tag(), 0, dl1416->cursor_enable);
133   state_save_register_item(device->machine(), "dl1416", device->tag(), 0, dl1416->write_enable);
134   state_save_register_item_array(device->machine(), "dl1416", device->tag(), 0, dl1416->digit_ram);
135}
136
137
138static DEVICE_RESET( dl1416 )
139{
140   int i, pattern;
141   dl1416_state *chip = get_safe_token(device);
142   const dl1416_interface *intf = (const dl1416_interface *)device->static_config();
143   /* disable all lines */
144   chip->chip_enable = FALSE;
145   chip->write_enable = FALSE;
146   chip->cursor_enable = FALSE;
147
148   /* randomize digit and cursor memory */
149   for (i = 0; i < 4; i++)
150   {
151      chip->digit_ram[i] = device->machine().rand()&0x3F;
152      // TODO: only enable the following line if the device actually has a cursor (DL1416T and DL1416B), if DL1414 then cursor is always 0!
153      //chip->cursor_state[i] = ((device->machine().rand()&0xFF) >= 0x80) ? CURSOR_ON : CURSOR_OFF;
154      chip->cursor_state[i] = CURSOR_OFF;
155      pattern = dl1416t_segments[chip->digit_ram[i]];
156
157      /* If cursor for this digit position is enabled and segment is not */
158      /* undefined, replace digit with cursor */
159      if ((chip->cursor_state[i] == CURSOR_ON) && (pattern != SEG_UNDEF))
160         pattern = SEG_CURSOR;
161
162      /* Undefined characters are replaced by blanks */
163      if (pattern == SEG_UNDEF)
164         pattern = SEG_BLANK;
165
166      /* Call update function */
167      if (intf->update)
168         intf->update(device, i, pattern);
169   }
170}
171
172
173/*****************************************************************************
174    IMPLEMENTATION
175*****************************************************************************/
176
177/* write enable, active low */
178WRITE_LINE_DEVICE_HANDLER( dl1416_wr_w )
179{
180   dl1416_state *chip = get_safe_token(device);
181   chip->write_enable = !state;
182}
183
184/* chip enable, active low */
185WRITE_LINE_DEVICE_HANDLER( dl1416_ce_w )
186{
187   dl1416_state *chip = get_safe_token(device);
188   chip->chip_enable = !state;
189}
190
191/* cursor enable, active low */
192WRITE_LINE_DEVICE_HANDLER( dl1416_cu_w )
193{
194   dl1416_state *chip = get_safe_token(device);
195   chip->cursor_enable = !state;
196}
197
198/* data */
199WRITE8_DEVICE_HANDLER( dl1416_data_w )
200{
201   dl1416_state *chip = get_safe_token(device);
202   const dl1416_interface *intf = (const dl1416_interface *)device->static_config();
203
204   offset &= 0x03; /* A0-A1 */
205   data &= 0x7f;   /* D0-D6 */
206
207   /* Only try to update the data if we are enabled and write is enabled */
208   if (chip->chip_enable && chip->write_enable)
209   {
210      /* fprintf(stderr,"DL1416 Write: Cursor: %d, Offset: %d, Data: %02X\n (%c)", chip->cursor_enable, offset, data, data); */
211      int i, pattern, previous_state;
212
213      if (chip->cursor_enable) /* cursor enable is set */
214      {
215         if (device->type() == DL1416B)
216         {
217            /* DL1416B uses offset to decide cursor pos to change and D0 to hold new state */
218
219            /* The cursor will be set if D0 is high and the original */
220            /* character restored otherwise */
221            previous_state = chip->cursor_state[offset];
222            chip->cursor_state[offset] = data & 1 ? CURSOR_ON : CURSOR_OFF;
223
224            if (previous_state != chip->cursor_state[offset])
225            {
226               pattern = dl1416t_segments[chip->digit_ram[offset]];
227
228               /* If cursor for this digit position is enabled and segment is not */
229               /* undefined, replace digit with cursor */
230               if ((chip->cursor_state[offset] == CURSOR_ON) && (pattern != SEG_UNDEF))
231                  pattern = SEG_CURSOR;
232
233               /* Undefined characters are replaced by blanks */
234               if (pattern == SEG_UNDEF)
235                  pattern = SEG_BLANK;
236
237               /* Call update function */
238               if (intf->update)
239                  intf->update(device, offset, pattern);
240            }
241         }
242         else {
243         /* DL1416T uses a bitmap of 4 data bits D0,D1,D2,D3 to decide cursor pos to change and new state */
244
245            for (i = 0; i < 4; i++)
246            {
247               /* The cursor will be set if D0-D3 is high and the original */
248               /* character at the appropriate position restored otherwise */
249               previous_state = chip->cursor_state[i];
250               chip->cursor_state[i] = data & (1<<i) ? CURSOR_ON : CURSOR_OFF;
251
252               if (previous_state != chip->cursor_state[i])
253               {
254                  pattern = dl1416t_segments[chip->digit_ram[i]];
255
256                  /* If cursor for this digit position is enabled and segment is not */
257                  /* undefined, replace digit with cursor */
258                  if ((chip->cursor_state[i] == CURSOR_ON) && (pattern != SEG_UNDEF))
259                     pattern = SEG_CURSOR;
260
261                  /* Undefined characters are replaced by blanks */
262                  if (pattern == SEG_UNDEF)
263                     pattern = SEG_BLANK;
264
265                  /* Call update function */
266                  if (intf->update)
267                     intf->update(device, i, pattern);
268               }
269            }
270         }
271      }
272      else /* cursor enable is not set, so standard write */
273      {
274         /* Save written value */
275         chip->digit_ram[offset] = data&0x3f;
276
277         /* Load segment pattern from ROM */
278         pattern = dl1416t_segments[data]; /** TODO: handle DL1416T vs DL1416B vs DL1414 here */
279
280         /* If cursor for this digit position is enabled and segment is not */
281         /* undefined, replace digit with cursor */
282         if ((chip->cursor_state[offset] == CURSOR_ON) && (pattern != SEG_UNDEF))
283            pattern = SEG_CURSOR;
284
285         /* Undefined characters are replaced by blanks */
286         if (pattern == SEG_UNDEF)
287            pattern = SEG_BLANK;
288
289         /* Call update function */
290         if (intf->update)
291            intf->update(device, offset, pattern);
292      }
293   }
294}
295
296dl1416_device::dl1416_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
297   : device_t(mconfig, type, name, tag, owner, clock)
298{
299   m_token = global_alloc_clear(dl1416_state);
300}
301
302//-------------------------------------------------
303//  device_config_complete - perform any
304//  operations now that the configuration is
305//  complete
306//-------------------------------------------------
307
308void dl1416_device::device_config_complete()
309{
310}
311
312//-------------------------------------------------
313//  device_start - device-specific startup
314//-------------------------------------------------
315
316void dl1416_device::device_start()
317{
318   DEVICE_START_NAME( dl1416 )(this);
319}
320
321//-------------------------------------------------
322//  device_reset - device-specific reset
323//-------------------------------------------------
324
325void dl1416_device::device_reset()
326{
327   DEVICE_RESET_NAME( dl1416 )(this);
328}
329
330
331const device_type DL1416B = &device_creator<dl1416b_device>;
332
333dl1416b_device::dl1416b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
334   : dl1416_device(mconfig, DL1416B, "DL1416B", tag, owner, clock)
335{
336}
337
338
339const device_type DL1416T = &device_creator<dl1416t_device>;
340
341dl1416t_device::dl1416t_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
342   : dl1416_device(mconfig, DL1416T, "DL1416T", tag, owner, clock)
343{
344}
Property changes on: trunk/src/emu/video/dl1416.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/video/dl1416.h
r0r21685
1/*****************************************************************************
2 *
3 * video/dl1416.h
4 *
5 * DL1416
6 *
7 * 4-Digit 16-Segment Alphanumeric Intelligent Display
8 * with Memory/Decoder/Driver
9 *
10 * See video/dl1416.c for more info
11 *
12 ****************************************************************************/
13
14#ifndef DL1416_H_
15#define DL1416_H_
16
17#include "devcb.h"
18
19/***************************************************************************
20    TYPE DEFINITIONS
21***************************************************************************/
22
23typedef void (*dl1416_update_func)(device_t *device, int digit, int data);
24
25struct dl1416_interface
26{
27   dl1416_update_func update;
28};
29
30
31/***************************************************************************
32    DEVICE CONFIGURATION MACROS
33***************************************************************************/
34
35#define MCFG_DL1416B_ADD(_tag, _config) \
36   MCFG_DEVICE_ADD(_tag, DL1416B, 0) \
37   MCFG_DEVICE_CONFIG(_config)
38
39#define MCFG_DL1416T_ADD(_tag, _config) \
40   MCFG_DEVICE_ADD(_tag, DL1416T, 0) \
41   MCFG_DEVICE_CONFIG(_config)
42
43
44/***************************************************************************
45    FUNCTION PROTOTYPES
46***************************************************************************/
47
48/* inputs */
49WRITE_LINE_DEVICE_HANDLER( dl1416_wr_w ); /* write enable */
50WRITE_LINE_DEVICE_HANDLER( dl1416_ce_w ); /* chip enable */
51WRITE_LINE_DEVICE_HANDLER( dl1416_cu_w ); /* cursor enable */
52DECLARE_WRITE8_DEVICE_HANDLER( dl1416_data_w );
53
54/* device get info callback */
55class dl1416_device : public device_t
56{
57public:
58   dl1416_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
59   ~dl1416_device() { global_free(m_token); }
60
61   // access to legacy token
62   void *token() const { assert(m_token != NULL); return m_token; }
63protected:
64   // device-level overrides
65   virtual void device_config_complete();
66   virtual void device_start();
67   virtual void device_reset();
68private:
69   // internal state
70   void *m_token;
71};
72
73class dl1416b_device : public dl1416_device
74{
75public:
76   dl1416b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
77};
78
79extern const device_type DL1416B;
80
81class dl1416t_device : public dl1416_device
82{
83public:
84   dl1416t_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
85};
86
87extern const device_type DL1416T;
88
89
90#endif /* DL1416_H_ */
Property changes on: trunk/src/emu/video/dl1416.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/video/tms3556.c
r0r21685
1/*
2    tms3556 emulation
3
4    TODO:
5    * implement remaining flags in control registers
6    * test the whole thing
7    * find the bloody tms3556 manual.  I mean the register and VRAM interfaces
8      are mostly guesswork full of hacks, and I'd like to compare it with
9      documentation.
10
11    Raphael Nabet, 2004
12*/
13
14#include "emu.h"
15#include "tms3556.h"
16
17//**************************************************************************
18//  MACROS / CONSTANTS
19//**************************************************************************
20
21#define LOG 0
22
23//**************************************************************************
24//  GLOBAL VARIABLES
25//**************************************************************************
26
27// devices
28const device_type TMS3556 = &device_creator<tms3556_device>;
29
30
31// default address map
32static ADDRESS_MAP_START( tms3556, AS_0, 8, tms3556_device )
33   AM_RANGE(0x0000, 0xffff) AM_RAM
34ADDRESS_MAP_END
35
36//-------------------------------------------------
37//  memory_space_config - return a description of
38//  any address spaces owned by this device
39//-------------------------------------------------
40
41const address_space_config *tms3556_device::memory_space_config(address_spacenum spacenum) const
42{
43   return (spacenum == AS_0) ? &m_space_config : NULL;
44}
45
46
47//**************************************************************************
48//  INLINE HELPERS
49//**************************************************************************
50
51//-------------------------------------------------
52//  readbyte - read a byte at the given address
53//-------------------------------------------------
54
55inline UINT8 tms3556_device::readbyte(offs_t address)
56{
57   return space().read_byte(address);
58}
59
60
61//-------------------------------------------------
62//  writebyte - write a byte at the given address
63//-------------------------------------------------
64
65inline void tms3556_device::writebyte(offs_t address, UINT8 data)
66{
67   space().write_byte(address, data);
68}
69
70
71//**************************************************************************
72//  LIVE DEVICE
73//**************************************************************************
74
75//-------------------------------------------------
76//  tms3556_device - constructor
77//-------------------------------------------------
78
79tms3556_device::tms3556_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
80   : device_t(mconfig, TMS3556, "Texas Instruments VDP TMS3556", tag, owner, clock),
81      device_memory_interface(mconfig, *this),
82      m_space_config("videoram", ENDIANNESS_LITTLE, 8, 17, 0, NULL, *ADDRESS_MAP_NAME(tms3556)),
83      m_write_ptr(0),
84      m_reg_ptr(0),
85      m_reg_access_phase(0),
86      m_magical_mystery_flag(0),
87      m_scanline(0),
88      m_blink(0),
89      m_blink_count(0)
90{
91   for (int i = 0; i < 8; i++)
92   {
93      m_control_regs[i] = 0;
94      m_address_regs[i] = 0;
95   }
96}
97
98
99//-------------------------------------------------
100//  device_start - device-specific startup
101//-------------------------------------------------
102
103void tms3556_device::device_start()
104{
105   // register for state saving
106   save_item(NAME(m_control_regs));
107   save_item(NAME(m_address_regs));
108   save_item(NAME(m_write_ptr));
109   save_item(NAME(m_reg_ptr));
110   save_item(NAME(m_reg_access_phase));
111   save_item(NAME(m_magical_mystery_flag));
112   save_item(NAME(m_scanline));
113   save_item(NAME(m_blink));
114   save_item(NAME(m_blink_count));
115   save_item(NAME(m_bg_color));
116   save_item(NAME(m_name_offset));
117   save_item(NAME(m_cg_flag));
118   save_item(NAME(m_char_line_counter));
119   save_item(NAME(m_dbl_h_phase));
120
121   machine().primary_screen->register_screen_bitmap(m_bitmap);
122}
123
124
125/*static const char *const tms3556_mode_names[] = { "DISPLAY OFF", "TEXT", "GRAPHIC", "MIXED" };*/
126
127
128UINT32 tms3556_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
129{
130   copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
131   return 0;
132}
133
134
135//-------------------------------------------------
136//  vram_r - VRAM read
137//-------------------------------------------------
138
139READ8_MEMBER( tms3556_device::vram_r )
140{
141   if (LOG) logerror("TMS3556 VRAM Read: %06x\n", offset);
142
143   if (m_magical_mystery_flag)
144   {
145      m_write_ptr = ((m_control_regs[2] << 8) | m_control_regs[1]) + 1;
146      m_magical_mystery_flag = 0;
147   }
148
149   return readbyte(m_address_regs[1]++);
150}
151
152//-------------------------------------------------
153//  vram_w - VRAM write
154//-------------------------------------------------
155
156WRITE8_MEMBER( tms3556_device::vram_w )
157{
158   if (LOG) logerror("TMS3556 VRAM Write: %06x = %02x\n", offset, data);
159
160   if (m_magical_mystery_flag)
161   {
162      m_write_ptr = (m_control_regs[2] << 8) | m_control_regs[1];
163      m_magical_mystery_flag = 0;
164   }
165
166   writebyte(m_write_ptr++, data);
167}
168
169
170//-------------------------------------------------
171//  reg_r - read from register port
172//-------------------------------------------------
173
174READ8_MEMBER( tms3556_device::reg_r )
175{
176   if (LOG) logerror("TMS3556 Reg Read: %06x\n", offset);
177
178   int reply = 0;
179
180   if (m_reg_ptr < 8)
181   {
182      reply = m_control_regs[m_reg_ptr];
183      m_reg_access_phase = 0;
184   }
185   else
186   {
187      // ???
188   }
189
190   return reply;
191}
192
193//-------------------------------------------------
194//  reg_w - write to register port
195//-------------------------------------------------
196
197WRITE8_MEMBER( tms3556_device::reg_w )
198{
199   if (LOG) logerror("TMS3556 Reg Write: %06x = %02x\n", offset, data);
200
201   if ((m_reg_access_phase == 3) && (data))
202      m_reg_access_phase = 0; /* ???????????? */
203
204   switch (m_reg_access_phase)
205   {
206   case 0:
207      m_reg_ptr = data & 0x0f;
208      m_reg_access_phase = 1;
209      break;
210
211   case 1:
212      if (m_reg_ptr < 8)
213      {
214         m_control_regs[m_reg_ptr] = data;
215         m_reg_access_phase = 0;
216         if (m_reg_ptr == 2)
217            m_magical_mystery_flag = 1;
218      }
219      else if (m_reg_ptr == 9)
220      {   /* I don't understand what is going on, but it is the only way to
221            get this to work */
222         m_address_regs[m_reg_ptr - 8] = ((m_control_regs[2] << 8) | m_control_regs[1]) + 1;
223         m_reg_access_phase = 0;
224         m_magical_mystery_flag = 0;
225      }
226      else
227      {
228         m_address_regs[m_reg_ptr - 8] = (m_control_regs[m_reg_ptr - 8] & 0xff00) | m_control_regs[1];
229         m_reg_access_phase = 2;
230         m_magical_mystery_flag = 0;
231      }
232      break;
233
234   case 2:
235      m_address_regs[m_reg_ptr - 8] = (m_control_regs[m_reg_ptr - 8] & 0x00ff) | (m_control_regs[2] << 8);
236      if ((m_reg_ptr <= 10) || (m_reg_ptr == 15))
237         m_address_regs[m_reg_ptr - 8]++;
238      else
239         m_address_regs[m_reg_ptr - 8] += 2;
240      m_reg_access_phase = 3;
241      break;
242
243   case 3:
244      m_reg_access_phase = 0;
245      break;
246   }
247}
248
249
250//-------------------------------------------------
251//  redraw code
252//-------------------------------------------------
253
254
255//-------------------------------------------------
256//  draw_line_empty - draw an empty line (used for
257//  top and bottom borders, and screen off mode)
258//-------------------------------------------------
259
260void tms3556_device::draw_line_empty(UINT16 *ln)
261{
262   int i;
263
264   for (i = 0; i < TMS3556_TOTAL_WIDTH; i++)
265#if TMS3556_DOUBLE_WIDTH
266      *ln++ = m_bg_color;
267#endif
268      *ln++ = m_bg_color;
269}
270
271
272//-------------------------------------------------
273//  draw_line_text_common - draw a line of text
274//  (called by draw_line_text and draw_line_mixed)
275//-------------------------------------------------
276
277void tms3556_device::draw_line_text_common(UINT16 *ln)
278{
279   int pattern, x, xx, i, name_offset;
280   UINT16 fg, bg;
281   offs_t nametbl_base;
282   offs_t patterntbl_base[4];
283   int name_hi, name_lo;
284   int pattern_ix;
285   int alphanumeric_mode, dbl_w, dbl_h, dbl_w_phase = 0;
286
287   nametbl_base = m_address_regs[2];
288   for (i = 0; i < 4; i++)
289      patterntbl_base[i] = m_address_regs[i + 3];
290
291   for (xx = 0; xx < TMS3556_LEFT_BORDER; xx++)
292#if TMS3556_DOUBLE_WIDTH
293      *ln++ = m_bg_color;
294#endif
295      *ln++ = m_bg_color;
296
297   name_offset = m_name_offset;
298
299   for (x = 0; x < 40; x++)
300   {
301      name_hi = readbyte(nametbl_base + name_offset);
302      name_lo = readbyte(nametbl_base + name_offset + 1);
303      pattern_ix = ((name_hi >> 2) & 2) | ((name_hi >> 4) & 1);
304      alphanumeric_mode = (pattern_ix < 2) || ((pattern_ix == 3) && !(m_control_regs[7] & 0x08));
305      fg = (name_hi >> 5) & 0x7;
306      if (alphanumeric_mode)
307      {
308         if (name_hi & 4)
309         {   /* inverted color */
310            bg = fg;
311            fg = m_bg_color;
312         }
313         else
314            bg = m_bg_color;
315         dbl_w = name_hi & 0x2;
316         dbl_h = name_hi & 0x1;
317      }
318      else
319      {
320         bg = name_hi & 0x7;
321         dbl_w = 0;
322         dbl_h = 0;
323      }
324      if ((name_lo & 0x80) && m_blink)
325         fg = bg;    /* blink off time */
326      if (! dbl_h)
327      {   /* single height */
328         pattern = readbyte(patterntbl_base[pattern_ix] + (name_lo & 0x7f) + 128 * m_char_line_counter);
329         if (m_char_line_counter == 0)
330            m_dbl_h_phase[x] = 0;
331      }
332      else
333      {   /* double height */
334         if (! m_dbl_h_phase[x])
335            /* first phase: pattern from upper half */
336            pattern = readbyte(patterntbl_base[pattern_ix] + (name_lo & 0x7f) + 128 * (5 + (m_char_line_counter >> 1)));
337         else
338            /* second phase: pattern from lower half */
339            pattern = readbyte(patterntbl_base[pattern_ix] + (name_lo & 0x7f) + 128 * (m_char_line_counter >> 1));
340         if (m_char_line_counter == 0)
341            m_dbl_h_phase[x] = !m_dbl_h_phase[x];
342      }
343      if (!dbl_w)
344      {   /* single width */
345         for (xx = 0; xx < 8; xx++)
346         {
347            UINT16 color = (pattern & 0x80) ? fg : bg;
348#if TMS3556_DOUBLE_WIDTH
349            *ln++ = color;
350#endif
351            *ln++ = color;
352            pattern <<= 1;
353         }
354         dbl_w_phase = 0;
355      }
356      else
357      {   /* double width */
358         if (dbl_w_phase)
359            /* second phase: display right half */
360            pattern <<= 4;
361         for (xx = 0; xx < 4; xx++)
362         {
363            UINT16 color = (pattern & 0x80) ? fg : bg;
364#if TMS3556_DOUBLE_WIDTH
365            *ln++ = color; *ln++ = color;
366#endif
367            *ln++ = color; *ln++ = color;
368            pattern <<= 1;
369         }
370         dbl_w_phase = !dbl_w_phase;
371      }
372      name_offset += 2;
373   }
374
375   for (xx = 0; xx < TMS3556_RIGHT_BORDER; xx++)
376#if TMS3556_DOUBLE_WIDTH
377      *ln++ = m_bg_color;
378#endif
379      *ln++ = m_bg_color;
380
381   if (m_char_line_counter == 0)
382      m_name_offset = name_offset;
383}
384
385
386//-------------------------------------------------
387//  draw_line_bitmap_common - draw a line of bitmap
388//  (called by draw_line_bitmap and draw_line_mixed)
389//-------------------------------------------------
390
391void tms3556_device::draw_line_bitmap_common(UINT16 *ln)
392{
393   int x, xx;
394   offs_t nametbl_base;
395   int name_b, name_g, name_r;
396
397   nametbl_base = m_address_regs[2];
398
399   for (xx = 0; xx < TMS3556_LEFT_BORDER; xx++)
400#if TMS3556_DOUBLE_WIDTH
401      *ln++ = m_bg_color;
402#endif
403      *ln++ = m_bg_color;
404
405   for (x = 0; x < 40; x++)
406   {
407      name_b = readbyte(nametbl_base + m_name_offset);
408      name_g = readbyte(nametbl_base + m_name_offset + 1);
409      name_r = readbyte(nametbl_base + m_name_offset + 2);
410      for (xx = 0; xx < 8; xx++)
411      {
412         UINT16 color = ((name_b >> 5) & 0x4) | ((name_g >> 6) & 0x2) | ((name_r >> 7) & 0x1);
413#if TMS3556_DOUBLE_WIDTH
414         *ln++ = color;
415#endif
416         *ln++ = color;
417         name_b <<= 1;
418         name_g <<= 1;
419         name_r <<= 1;
420      }
421      m_name_offset += 3;
422   }
423
424   for (xx = 0; xx < TMS3556_RIGHT_BORDER; xx++)
425#if TMS3556_DOUBLE_WIDTH
426      *ln++ = m_bg_color;
427#endif
428      *ln++ = m_bg_color;
429}
430
431
432//-------------------------------------------------
433//  draw_line_text - draw a line in text mode
434//-------------------------------------------------
435
436void tms3556_device::draw_line_text(UINT16 *ln)
437{
438   if (m_char_line_counter == 0)
439      m_char_line_counter = 10;
440   m_char_line_counter--;
441   draw_line_text_common(ln);
442}
443
444
445//-------------------------------------------------
446//  draw_line_bitmap - draw a line in bitmap mode
447//-------------------------------------------------
448
449void tms3556_device::draw_line_bitmap(UINT16 *ln)
450{
451   draw_line_bitmap_common(ln);
452   m_bg_color = (readbyte(m_address_regs[2] + m_name_offset) >> 5) & 0x7;
453   m_name_offset += 2;
454}
455
456
457//-------------------------------------------------
458//  draw_line_mixed - draw a line in mixed mode
459//-------------------------------------------------
460
461void tms3556_device::draw_line_mixed(UINT16 *ln)
462{
463   if (m_cg_flag)
464   {   /* bitmap line */
465      draw_line_bitmap_common(ln);
466      m_bg_color = (readbyte(m_address_regs[2] + m_name_offset) >> 5) & 0x7;
467      m_cg_flag = (readbyte(m_address_regs[2] + m_name_offset) >> 4) & 0x1;
468      m_name_offset += 2;
469   }
470   else
471   {   /* text line */
472      if (m_char_line_counter == 0)
473         m_char_line_counter = 10;
474      m_char_line_counter--;
475      draw_line_text_common(ln);
476      if (m_char_line_counter == 0)
477      {
478         m_bg_color = (readbyte(m_address_regs[2] + m_name_offset) >> 5) & 0x7;
479         m_cg_flag = (readbyte(m_address_regs[2] + m_name_offset) >> 4) & 0x1;
480         m_name_offset += 2;
481      }
482   }
483}
484
485
486//-------------------------------------------------
487//  draw_line - draw a line. If non-interlaced mode,
488//  duplicate the line.
489//-------------------------------------------------
490
491void tms3556_device::draw_line(bitmap_ind16 &bmp, int line)
492{
493   int double_lines = 0;
494   UINT16 *ln, *ln2 = NULL;
495
496//  if (m_control_regs[4] & 0x??)
497//  {   // interlaced mode
498//      ln = &bmp->pix16(line, m_field);
499//  }
500//  else
501   {   /* non-interlaced mode */
502      ln = &bmp.pix16(line);
503      ln2 = &bmp.pix16(line, 1);
504      double_lines = 1;
505   }
506
507   if ((line < TMS3556_TOP_BORDER) || (line >= (TMS3556_TOP_BORDER + 250)))
508   {
509      /* draw top and bottom borders */
510      draw_line_empty(ln);
511   }
512   else
513   {
514      /* draw useful area */
515      switch (m_control_regs[6] >> 6)
516      {
517      case TMS3556_MODE_OFF:
518         draw_line_empty(ln);
519         break;
520      case TMS3556_MODE_TEXT:
521         draw_line_text(ln);
522         break;
523      case TMS3556_MODE_BITMAP:
524         draw_line_bitmap(ln);
525         break;
526      case TMS3556_MODE_MIXED:
527         draw_line_mixed(ln);
528         break;
529      }
530   }
531
532   if (double_lines)
533   {
534      memcpy (ln2, ln, TMS3556_TOTAL_WIDTH * (TMS3556_DOUBLE_WIDTH ? 2 : 1));
535   }
536}
537
538
539//-------------------------------------------------
540//  interrupt_start_vblank - Do vblank-time tasks
541//-------------------------------------------------
542
543void tms3556_device::interrupt_start_vblank(void)
544{
545   /* at every frame, vdp switches fields */
546   //m_field = !m_field;
547
548   /* color blinking */
549   if (m_blink_count)
550      m_blink_count--;
551   if (!m_blink_count)
552   {
553      m_blink = !m_blink;
554      m_blink_count = 60; /*no idea what the real value is*/
555   }
556   /* reset background color */
557   m_bg_color = (m_control_regs[7] >> 5) & 0x7;
558   /* reset name offset */
559   m_name_offset = 0;
560   /* reset character line counter */
561   m_char_line_counter = 0;
562   /* reset c/g flag */
563   m_cg_flag = 0;
564   /* reset double height phase flags */
565   memset(m_dbl_h_phase, 0, sizeof(m_dbl_h_phase));
566}
567
568
569//-------------------------------------------------
570//  interrupt - scanline handler
571//-------------------------------------------------
572
573void tms3556_device::interrupt(running_machine &machine)
574{
575   /* check for start of vblank */
576   if (m_scanline == 310)  /*no idea what the real value is*/
577      interrupt_start_vblank();
578
579   /* render the current line */
580   if ((m_scanline >= 0) && (m_scanline < TMS3556_TOTAL_HEIGHT))
581   {
582      //if (!video_skip_this_frame())
583         draw_line(m_bitmap, m_scanline);
584   }
585
586   if (++m_scanline == 313)
587      m_scanline = 0;
588}
Property changes on: trunk/src/emu/video/tms3556.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/video/tms3556.h
r0r21685
1/***************************************************************************
2
3  Texas Instruments TMS3556 Video Display Processor
4
5 ***************************************************************************/
6
7
8#pragma once
9
10#ifndef __TMS3556_H__
11#define __TMS3556_H__
12
13///*************************************************************************
14//  MACROS / CONSTANTS
15///*************************************************************************
16
17#define TMS3556_TOP_BORDER 1
18#define TMS3556_BOTTOM_BORDER 1
19#define TMS3556_LEFT_BORDER 8
20#define TMS3556_RIGHT_BORDER 8
21#define TMS3556_TOTAL_WIDTH (320 + TMS3556_LEFT_BORDER + TMS3556_RIGHT_BORDER)
22#define TMS3556_TOTAL_HEIGHT (250 + TMS3556_TOP_BORDER + TMS3556_BOTTOM_BORDER)
23
24/* if DOUBLE_WIDTH set, the horizontal resolution is doubled */
25#define TMS3556_DOUBLE_WIDTH 1
26
27#define TMS3556_MODE_OFF    0
28#define TMS3556_MODE_TEXT   1
29#define TMS3556_MODE_BITMAP 2
30#define TMS3556_MODE_MIXED  3
31
32
33///*************************************************************************
34//  INTERFACE CONFIGURATION MACROS
35///*************************************************************************
36
37#define MCFG_TMS3556_ADD(_tag) \
38   MCFG_DEVICE_ADD(_tag, TMS3556, 0)
39
40///*************************************************************************
41//  TYPE DEFINITIONS
42///*************************************************************************
43
44// ======================> tms3556_device
45
46class tms3556_device :  public device_t,
47                  public device_memory_interface
48{
49public:
50   // construction/destruction
51   tms3556_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
52
53   DECLARE_READ8_MEMBER( vram_r );
54   DECLARE_WRITE8_MEMBER( vram_w );
55   DECLARE_READ8_MEMBER( reg_r );
56   DECLARE_WRITE8_MEMBER( reg_w );
57
58   void interrupt(running_machine &machine);
59
60   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
61
62protected:
63   // device-level overrides
64   virtual void device_start();
65
66   // device_config_memory_interface overrides
67   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
68
69   // address space configurations
70   const address_space_config      m_space_config;
71
72   inline UINT8 readbyte(offs_t address);
73   inline void writebyte(offs_t address, UINT8 data);
74
75   void draw_line_empty(UINT16 *ln);
76   void draw_line_text_common(UINT16 *ln);
77   void draw_line_bitmap_common(UINT16 *ln);
78   void draw_line_text(UINT16 *ln);
79   void draw_line_bitmap(UINT16 *ln);
80   void draw_line_mixed(UINT16 *ln);
81   void draw_line(bitmap_ind16 &bmp, int line);
82   void interrupt_start_vblank(void);
83
84private:
85   // registers
86   UINT8 m_control_regs[8];
87   UINT16 m_address_regs[8];
88   UINT16 m_write_ptr;
89
90   // register interface
91   int m_reg_ptr;
92   int m_reg_access_phase;
93   int m_magical_mystery_flag;
94
95   int m_scanline;             // scanline counter
96   int m_blink, m_blink_count; // blinking
97   int m_bg_color;             // background color for current line
98   int m_name_offset;          // current offset in name table
99   int m_cg_flag;              // c/g flag (mixed mode only)
100   int m_char_line_counter;    // character line counter (decrements from 10, 0 when we have reached
101                        // last line of character row)
102   int m_dbl_h_phase[40];      // double height phase flags (one per horizontal character position)
103
104   bitmap_ind16 m_bitmap;
105};
106
107
108// device type definition
109extern const device_type TMS3556;
110
111
112#endif
Property changes on: trunk/src/emu/video/tms3556.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/video/hd66421.c
r0r21685
1/*
2
3    Hitachi HD66421 LCD Controller/Driver
4
5    (c) 2001-2007 Tim Schuerewegen
6
7*/
8
9#include "emu.h"
10#include "hd66421.h"
11
12//**************************************************************************
13//  MACROS / CONSTANTS
14//**************************************************************************
15
16#define LOG_LEVEL  1
17#define _logerror(level,x)  do { if (LOG_LEVEL > level) logerror x; } while (0)
18
19#define HD66421_RAM_SIZE  (HD66421_WIDTH * HD66421_HEIGHT / 4) // 2-bits per pixel
20
21// R0 - control register 1
22#define LCD_R0_RMW      0x80 // read-modify-write mode
23#define LCD_R0_DISP     0x40 // display on/off
24#define LCD_R0_STBY     0x20 // standby (internal operation and power circuit halt)
25#define LCD_R0_PWR      0x10
26#define LCD_R0_AMP      0x08
27#define LCD_R0_REV      0x04 // reverse
28#define LCD_R0_HOLT     0x02
29#define LCD_R0_ADC      0x01
30
31// R1 - control register 2
32#define LCD_R1_BIS1     0x80 // bias ratio (bit 1)
33#define LCD_R1_BIS0     0x40 // bias ratio (bit 0)
34#define LCD_R1_WLS      0x20
35#define LCD_R1_GRAY     0x10 // grayscale palette 4/32
36#define LCD_R1_DTY1     0x08 // display duty cycle (bit 1)
37#define LCD_R1_DTY0     0x04 // display duty cycle (bit 0)
38#define LCD_R1_INC      0x02
39#define LCD_R1_BLK      0x01 // blink function
40
41// register 0 to 16
42#define LCD_REG_CONTROL_1   0x00 // control register 1
43#define LCD_REG_CONTROL_2   0x01 // control register 2
44#define LCD_REG_ADDR_X      0x02 // x address register
45#define LCD_REG_ADDR_Y      0x03 // y address register
46#define LCD_REG_RAM         0x04 // display ram access register
47#define LCD_REG_START_Y     0x05 // display start line register
48#define LCD_REG_BLINK_START 0x06 // blink start line register
49#define LCD_REG_BLINK_END   0x07 // blink end line register
50#define LCD_REG_BLINK_1     0x08 // blink register 1
51#define LCD_REG_BLINK_2     0x09 // blink register 2
52#define LCD_REG_BLINK_3     0x0A // blink register 3
53#define LCD_REG_PARTIAL     0x0B // partial display block register
54#define LCD_REG_COLOR_1     0x0C // gray scale palette 1 (0,0)
55#define LCD_REG_COLOR_2     0x0D // gray scale palette 2 (0,1)
56#define LCD_REG_COLOR_3     0x0E // gray scale palette 3 (1,0)
57#define LCD_REG_COLOR_4     0x0F // gray scale palette 4 (1,1)
58#define LCD_REG_CONTRAST    0x10 // contrast control register
59#define LCD_REG_PLANE       0x11 // plane selection register
60
61//**************************************************************************
62//  GLOBAL VARIABLES
63//**************************************************************************
64
65// devices
66const device_type HD66421 = &device_creator<hd66421_device>;
67
68
69// default address map
70static ADDRESS_MAP_START( hd66421, AS_0, 8, hd66421_device )
71   AM_RANGE(0x0000, HD66421_RAM_SIZE) AM_RAM
72ADDRESS_MAP_END
73
74//-------------------------------------------------
75//  memory_space_config - return a description of
76//  any address spaces owned by this device
77//-------------------------------------------------
78
79const address_space_config *hd66421_device::memory_space_config(address_spacenum spacenum) const
80{
81   return (spacenum == AS_0) ? &m_space_config : NULL;
82}
83
84
85//**************************************************************************
86//  INLINE HELPERS
87//**************************************************************************
88
89//-------------------------------------------------
90//  readbyte - read a byte at the given address
91//-------------------------------------------------
92
93inline UINT8 hd66421_device::readbyte(offs_t address)
94{
95   return space().read_byte(address);
96}
97
98
99//-------------------------------------------------
100//  writebyte - write a byte at the given address
101//-------------------------------------------------
102
103inline void hd66421_device::writebyte(offs_t address, UINT8 data)
104{
105   space().write_byte(address, data);
106}
107
108
109//**************************************************************************
110//  LIVE DEVICE
111//**************************************************************************
112
113//-------------------------------------------------
114//  hd66421_device - constructor
115//-------------------------------------------------
116
117hd66421_device::hd66421_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
118   : device_t(mconfig, HD66421, "Hitachi HD66421 LCD Controller", tag, owner, clock),
119      device_memory_interface(mconfig, *this),
120      m_space_config("videoram", ENDIANNESS_LITTLE, 8, 17, 0, NULL, *ADDRESS_MAP_NAME(hd66421)),
121      m_cmd(0),
122      m_x(0),
123      m_y(0)
124{
125   for (int i = 0; i < 32; i++)
126   {
127      m_reg[i] = 0;
128   }
129}
130
131
132//-------------------------------------------------
133//  device_start - device-specific startup
134//-------------------------------------------------
135
136void hd66421_device::device_start()
137{
138   // register for state saving
139   save_item(NAME(m_cmd));
140   save_item(NAME(m_reg));
141   save_item(NAME(m_x));
142   save_item(NAME(m_y));
143}
144
145READ8_MEMBER( hd66421_device::reg_idx_r )
146{
147   _logerror( 2, ("reg_idx_r\n"));
148   return m_cmd;
149}
150
151WRITE8_MEMBER( hd66421_device::reg_idx_w )
152{
153   _logerror( 2, ("reg_idx_w (%02X)\n", data));
154   m_cmd = data;
155}
156
157READ8_MEMBER( hd66421_device::reg_dat_r )
158{
159   _logerror( 2, ("reg_dat_r\n"));
160   return m_reg[m_cmd];
161}
162
163WRITE8_MEMBER( hd66421_device::reg_dat_w )
164{
165   _logerror( 2, ("reg_dat_w (%02X)\n", data));
166   m_reg[m_cmd] = data;
167
168   switch (m_cmd)
169   {
170      case LCD_REG_ADDR_X :
171         m_x = data;
172         break;
173
174      case LCD_REG_ADDR_Y :
175         m_y = data;
176         break;
177
178      case LCD_REG_RAM :
179      {
180         UINT8 r1;
181         writebyte(m_y * (HD66421_WIDTH / 4) + m_x, data);
182         r1 = m_reg[LCD_REG_CONTROL_2];
183         if (r1 & 0x02)
184            m_x++;
185         else
186            m_y++;
187
188         if (m_x >= (HD66421_WIDTH / 4))
189         {
190            m_x = 0;
191            m_y++;
192         }
193
194         if (m_y >= HD66421_HEIGHT)
195            m_y = 0;
196      }
197      break;
198   }
199}
200
201void hd66421_device::plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color)
202{
203   bitmap.pix16(y, x) = (UINT16)color;
204}
205
206UINT32 hd66421_device::update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
207{
208   pen_t pen[4];
209
210   _logerror( 1, ("video_update_hd66421\n"));
211
212   // update palette
213   for (int i = 0; i < 4; i++)
214   {
215      double bright;
216      int temp;
217      temp = 31 - (m_reg[LCD_REG_COLOR_1 + i] - m_reg[LCD_REG_CONTRAST] + 0x03);
218      if (temp <  0) temp =  0;
219      if (temp > 31) temp = 31;
220      bright = 1.0 * temp / 31;
221      pen[i] = i;
222      #ifdef HD66421_BRIGHTNESS_DOES_NOT_WORK
223      palette_set_color(machine(), pen[i], 255 * bright, 255 * bright, 255 * bright);
224      #else
225      palette_set_pen_contrast(machine(), pen[i], bright);
226      #endif
227   }
228
229   // draw bitmap (bottom to top)
230   if (m_reg[0] & LCD_R0_DISP)
231   {
232      int x, y;
233      x = 0;
234      y = HD66421_HEIGHT - 1;
235
236      for (int i = 0; i < HD66421_RAM_SIZE; i++)
237      {
238         plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 6) & 3]);
239         plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 4) & 3]);
240         plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 2) & 3]);
241         plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 0) & 3]);
242         if (x >= HD66421_WIDTH)
243         {
244            x = 0;
245            y = y - 1;
246         }
247      }
248   }
249   else
250   {
251      rectangle rect(0, HD66421_WIDTH - 1, 0, HD66421_HEIGHT - 1);
252      bitmap.fill(get_white_pen(machine()), rect);
253   }
254   
255   return 0;
256}
Property changes on: trunk/src/emu/video/hd66421.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/video/hd66421.h
r0r21685
1/***************************************************************************
2
3  Hitachi HD66421 LCD Controller
4
5  (c) 2001-2007 Tim Schuerewegen
6
7 ***************************************************************************/
8
9#pragma once
10
11#ifndef __HD66421_H__
12#define __HD66421_H__
13
14
15///*************************************************************************
16//  MACROS / CONSTANTS
17///*************************************************************************
18
19//#define HD66421_BRIGHTNESS_DOES_NOT_WORK
20
21#define HD66421_WIDTH   160
22#define HD66421_HEIGHT  100
23
24
25/*----------- defined in video/hd66421.c -----------*/
26
27///*************************************************************************
28//  INTERFACE CONFIGURATION MACROS
29///*************************************************************************
30
31#define MCFG_HD66421_ADD(_tag) \
32   MCFG_DEVICE_ADD(_tag, HD66421, 0)
33
34///*************************************************************************
35//  TYPE DEFINITIONS
36///*************************************************************************
37
38// ======================> hd66421_device
39
40class hd66421_device :  public device_t,
41                  public device_memory_interface
42{
43public:
44   // construction/destruction
45   hd66421_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
46
47   DECLARE_READ8_MEMBER( reg_idx_r );
48   DECLARE_WRITE8_MEMBER( reg_idx_w );
49   DECLARE_READ8_MEMBER( reg_dat_r );
50   DECLARE_WRITE8_MEMBER( reg_dat_w );
51
52   UINT32 update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
53
54protected:
55   // device-level overrides
56   virtual void device_start();
57
58   // device_config_memory_interface overrides
59   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
60
61   // address space configurations
62   const address_space_config      m_space_config;
63
64   inline UINT8 readbyte(offs_t address);
65   inline void writebyte(offs_t address, UINT8 data);
66
67   void plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color);
68
69private:
70   UINT8 m_cmd, m_reg[32];
71   int m_x, m_y;
72};
73
74
75// device type definition
76extern const device_type HD66421;
77
78
79#endif
Property changes on: trunk/src/emu/video/hd66421.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/video/mc6847.c
r0r21685
1/*********************************************************************
2
3    mc6847.c
4
5    Implementation of Motorola 6847 video hardware chip
6
7    Sources:
8    M6847 data sheet
9    M6847T1 info from Rainbow magazine (10/1986-12/1986)
10
11
12    AG  AS  INTEXT  INV  GM2  GM1  GM0
13    --  --  ------  ---  ---  ---  ---
14     0   0       0    0    X    X    X  Internal Alphanumerics
15     0   0       0    1    X    X    X  Internal Alphanumerics Inverted
16     0   0       1    0    X    X    X  External Alphanumerics
17     0   0       1    1    X    X    X  External Alphanumerics Inverted
18     0   1       0    X    X    X    X  Semigraphics 4
19     0   1       1    X    X    X    X  Semigraphics 6
20     1   X       X    X    0    0    0  Graphics CG1 (64x64x4)    (16 bpr)
21     1   X       X    X    0    0    1  Graphics RG1 (128x64x2)   (16 bpr)
22     1   X       X    X    0    1    0  Graphics CG2 (128x64x4)   (32 bpr)
23     1   X       X    X    0    1    1  Graphics RG2 (128x96x2)   (16 bpr)
24     1   X       X    X    1    0    0  Graphics CG3 (128x96x4)   (32 bpr)
25     1   X       X    X    1    0    1  Graphics RG3 (128x192x2)  (16 bpr)
26     1   X       X    X    1    1    0  Graphics CG6 (128x192x4)  (32 bpr)
27     1   X       X    X    1    1    1  Graphics RG6 (256x192x2)  (32 bpr)
28
29    Note: The M6847 relies on an external source (typically a 6883 SAM chip)
30    to feed it bytes; so the BPR (bytes per row) figures are effectively
31    suggestions.  Mismatching modes is responsible for the semigraphic modes
32    on the CoCo.
33
34    Timing:    (source Motorola M6847 Manual, experimentation, SockMaster)
35
36    Horizontal Sync:  Total Period: 228 clock cycles
37        @ CLK(0) + DHS_F            - falling edge (high to low)
38        @ CLK(16.5) + DHS_R         - rising edge (low to high)
39        @ CLK(42)                   - left border start
40        @ CLK(71.5)                 - body start
41        @ CLK(199.5)                - right border start
42        @ CLK(228) + DHS_F          - falling edge (high to low)
43        ...
44
45    Field Sync: Total Period 262*228 clock cycles
46        @ CLK(0) + DFS_F            - falling edge (high to low)
47        @ CLK(32*228) + DFS_R       - rising edge (low to high)
48        @ CLK(262*228) + DFS_F      - falling edge (high to low) (262.5 for the M6847Y)
49
50    DHS_F:  550ns
51    DHS_R:  740ns
52    DFS_F:  520ns
53    DFS_R:  500ns
54
55    The M6847T1 is a later variant of the M6847 chip that implements lower
56    case support and some other nifty features.  This chip is in the CoCo 2B.
57    I have not been able to find a pinout diagram for this chip so I am
58    assuming that the extra text modes on the CoCo 2B are activated by the
59    GM2-0 pins.  This needs to be confirmed.
60
61    The MC6847 datasheet states that a scanline is 227.5 clock cycles,
62    but experimentation suggests that it is 228.  The game "Dragon Fire"
63    has a fine tuned loop that runs in 57 clock cycles by the CPU's
64    reckoning (228 actual clock cycles) and would not function correctly
65    if skew existed.  SockMaster has confirmed that scanlines are in
66    fact 228 clock cycles.
67
68**********************************************************************/
69
70
71#include "emu.h"
72#include "video/mc6847.h"
73
74
75//**************************************************************************
76//  CONSTANTS
77//**************************************************************************
78
79#define TOP_BORDER              25
80#define USE_HORIZONTAL_CLIP     false
81
82#define TIMER_HSYNC_PERIOD      (228)
83#define TIMER_HSYNC_OFF_TIME    (10.0)
84#define TIMER_HSYNC_ON_TIME     (TIMER_HSYNC_OFF_TIME + 16.5)
85#define TIMER_FSYNC_OFF_TIME    (TIMER_HSYNC_PERIOD * TOP_BORDER + TIMER_HSYNC_ON_TIME)
86#define TIMER_FSYNC_ON_TIME     (TIMER_HSYNC_PERIOD * (TOP_BORDER + 192) + TIMER_HSYNC_ON_TIME)
87
88#define LOG_SCANLINE            0
89#define LOG_HSYNC               0
90#define LOG_FSYNC               1
91#define LOG_FLUSH               1
92#define LOG_INPUT               0
93
94
95const UINT32 mc6847_base_device::s_palette[mc6847_base_device::PALETTE_LENGTH] =
96{
97   MAKE_RGB(0x07, 0xff, 0x00), /* GREEN */
98   MAKE_RGB(0xff, 0xff, 0x00), /* YELLOW */
99   MAKE_RGB(0x3b, 0x08, 0xff), /* BLUE */
100   MAKE_RGB(0xcc, 0x00, 0x3b), /* RED */
101   MAKE_RGB(0xff, 0xff, 0xff), /* BUFF */
102   MAKE_RGB(0x07, 0xe3, 0x99), /* CYAN */
103   MAKE_RGB(0xff, 0x1c, 0xff), /* MAGENTA */
104   MAKE_RGB(0xff, 0x81, 0x00), /* ORANGE */
105
106   MAKE_RGB(0x00, 0x00, 0x00), /* BLACK */
107   MAKE_RGB(0x07, 0xff, 0x00), /* GREEN */
108   MAKE_RGB(0x00, 0x00, 0x00), /* BLACK */
109   MAKE_RGB(0xff, 0xff, 0xff), /* BUFF */
110
111   MAKE_RGB(0x00, 0x7c, 0x00), /* ALPHANUMERIC DARK GREEN */
112   MAKE_RGB(0x07, 0xff, 0x00), /* ALPHANUMERIC BRIGHT GREEN */
113   MAKE_RGB(0x91, 0x00, 0x00), /* ALPHANUMERIC DARK ORANGE */
114   MAKE_RGB(0xff, 0x81, 0x00)  /* ALPHANUMERIC BRIGHT ORANGE */
115};
116
117
118
119//**************************************************************************
120//  FRIEND DEVICE
121//**************************************************************************
122
123//-------------------------------------------------
124//  ctor
125//-------------------------------------------------
126
127mc6847_friend_device::mc6847_friend_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock,
128      const UINT8 *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, bool supports_partial_body_scanlines)
129   : device_t(mconfig, type, name, tag, owner, clock),
130      m_character_map(fontdata, is_mc6847t1)
131{
132   m_tpfs = tpfs;
133   m_supports_partial_body_scanlines = supports_partial_body_scanlines;
134
135   // The MC6847 and the GIME apply field sync on different scanlines
136   m_field_sync_falling_edge_scanline = field_sync_falling_edge_scanline;
137}
138
139
140
141//-------------------------------------------------
142//  setup_timer - sets up a single timer relative
143//  to the clock
144//-------------------------------------------------
145
146ATTR_FORCE_INLINE emu_timer *mc6847_friend_device::setup_timer(device_timer_id id, double offset, double period)
147{
148   emu_timer *timer = timer_alloc(id);
149   timer->adjust(
150      attotime::from_ticks(offset * 4, m_clock * 4),
151      0,
152      attotime::from_ticks(period * 4, m_clock * 4));
153   return timer;
154}
155
156
157
158//-------------------------------------------------
159//  device_start - device-specific startup
160//-------------------------------------------------
161
162void mc6847_friend_device::device_start(void)
163{
164   /* create the timers */
165   m_frame_timer = setup_timer(    TIMER_FRAME,        0,                      m_tpfs * TIMER_HSYNC_PERIOD);
166   m_hsync_on_timer = setup_timer( TIMER_HSYNC_ON,     TIMER_HSYNC_ON_TIME,    TIMER_HSYNC_PERIOD);
167   m_hsync_off_timer = setup_timer(TIMER_HSYNC_OFF,    TIMER_HSYNC_OFF_TIME,   TIMER_HSYNC_PERIOD);
168   m_fsync_timer = timer_alloc(TIMER_FSYNC);
169
170   m_top_border_scanlines = 0;
171   m_body_scanlines = 0;
172   m_wide = false;
173   m_recording_scanline = false;
174   m_physical_scanline = 0;
175   m_logical_scanline_zone = 0;
176   m_field_sync = false;
177   m_horizontal_sync = false;
178   set_geometry(25, 192, false);
179
180   /* save states */
181   save_item(NAME(m_physical_scanline));
182   save_item(NAME(m_logical_scanline));
183   save_item(NAME(m_logical_scanline_zone));
184   save_item(NAME(m_horizontal_sync));
185   save_item(NAME(m_field_sync));
186
187   /* artifacting */
188   m_artifacter.setup_config(this);
189}
190
191
192
193//-------------------------------------------------
194//  device_start - device-specific reset
195//-------------------------------------------------
196
197void mc6847_friend_device::device_reset(void)
198{
199   device_t::device_reset();
200   m_video_changed = true;
201}
202
203
204
205//-------------------------------------------------
206//  device_post_load - device-specific post load
207//-------------------------------------------------
208
209void mc6847_friend_device::device_post_load(void)
210{
211   device_t::device_post_load();
212   m_video_changed = true;
213}
214
215
216
217//-------------------------------------------------
218//  update_field_sync_timer
219//-------------------------------------------------
220
221void mc6847_friend_device::update_field_sync_timer(void)
222{
223   /* are we expecting field sync? */
224   bool expected_field_sync = (m_physical_scanline < m_field_sync_falling_edge_scanline)
225      || (m_logical_scanline_zone == SCANLINE_ZONE_VBLANK);
226
227   /* determine the duration */
228   attotime duration = (expected_field_sync != m_field_sync) ? attotime::from_ticks(160, m_clock) : attotime::never;
229
230   /* and reset the timer */
231   m_fsync_timer->adjust(duration, expected_field_sync ? 1 : 0);
232}
233
234
235
236//-------------------------------------------------
237//  device_timer
238//-------------------------------------------------
239
240void mc6847_friend_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
241{
242   switch(id)
243   {
244      case TIMER_FRAME:       new_frame();                    break;
245      case TIMER_HSYNC_ON:    change_horizontal_sync(true);   break;
246      case TIMER_HSYNC_OFF:   change_horizontal_sync(false);  break;
247      case TIMER_FSYNC:       change_field_sync(param != 0);  break;
248   }
249}
250
251
252
253//-------------------------------------------------
254//  new_frame
255//-------------------------------------------------
256
257ATTR_FORCE_INLINE void mc6847_friend_device::new_frame(void)
258{
259   m_physical_scanline = 0;
260   m_logical_scanline = 0;
261   m_logical_scanline_zone = SCANLINE_ZONE_FRAME_END;
262}
263
264
265
266//-------------------------------------------------
267//  scanline_zone_string
268//-------------------------------------------------
269
270const char *mc6847_friend_device::scanline_zone_string(scanline_zone zone)
271{
272   const char *result;
273   switch(zone)
274   {
275      case SCANLINE_ZONE_TOP_BORDER:      result = "SCANLINE_ZONE_TOP_BORDER";    break;
276      case SCANLINE_ZONE_BODY:            result = "SCANLINE_ZONE_BODY";          break;
277      case SCANLINE_ZONE_BOTTOM_BORDER:   result = "SCANLINE_ZONE_BOTTOM_BORDER"; break;
278      case SCANLINE_ZONE_RETRACE:         result = "SCANLINE_ZONE_RETRACE";       break;
279      case SCANLINE_ZONE_VBLANK:          result = "SCANLINE_ZONE_VBLANK";        break;
280      case SCANLINE_ZONE_FRAME_END:       result = "SCANLINE_ZONE_FRAME_END";     break;
281      default:
282         fatalerror("Should not get here\n");
283         break;
284   }
285   return result;
286}
287
288
289
290//-------------------------------------------------
291//  change_horizontal_sync
292//-------------------------------------------------
293
294ATTR_FORCE_INLINE void mc6847_friend_device::change_horizontal_sync(bool line)
295{
296   g_profiler.start(PROFILER_USER1);
297   if (line && !m_horizontal_sync)
298   {
299      if (LOG_SCANLINE)
300         logerror("%s: change_horizontal_sync():  Recording scanline\n", describe_context());
301
302      /* first store the scanline */
303      g_profiler.start(PROFILER_USER2);
304      switch((scanline_zone) m_logical_scanline_zone)
305      {
306         case SCANLINE_ZONE_TOP_BORDER:
307         case SCANLINE_ZONE_BOTTOM_BORDER:
308            record_border_scanline(m_physical_scanline);
309            break;
310
311         case SCANLINE_ZONE_BODY:
312            m_recording_scanline = true;
313            if (m_partial_scanline_clocks > 0)
314               record_partial_body_scanline(m_physical_scanline, m_logical_scanline, m_partial_scanline_clocks, 228);
315            else
316               record_body_scanline(m_physical_scanline, m_logical_scanline);
317            m_recording_scanline = false;
318            break;
319
320         case SCANLINE_ZONE_RETRACE:
321         case SCANLINE_ZONE_VBLANK:
322         case SCANLINE_ZONE_FRAME_END:
323            /* do nothing */
324            break;
325      }
326      g_profiler.stop();
327
328      /* advance to next scanline */
329      next_scanline();
330   }
331
332   /* finally output horizontal sync */
333   if (line != m_horizontal_sync)
334   {
335      m_horizontal_sync = line;
336
337      /* log if apprpriate */
338      if (LOG_HSYNC)
339         logerror("%s: change_horizontal_sync(): line=%d\n", describe_context(), line ? 1 : 0);
340
341      /* invoke callback */
342      if (!m_res_out_hsync_func.isnull())
343         m_res_out_hsync_func(line);
344
345      /* call virtual function */
346      horizontal_sync_changed(m_horizontal_sync);
347   }
348
349   /* and update the field sync timer */
350   update_field_sync_timer();
351   g_profiler.stop();
352}
353
354
355
356//-------------------------------------------------
357//  change_field_sync
358//-------------------------------------------------
359
360ATTR_FORCE_INLINE void mc6847_friend_device::change_field_sync(bool line)
361{
362   /* output field sync */
363   if (line != m_field_sync)
364   {
365      m_field_sync = line;
366
367      /* log if apprpriate */
368      if (LOG_FSYNC)
369         logerror("%s: change_field_sync(): line=%d\n", describe_context(), line ? 1 : 0);
370
371      /* invoke callback */
372      if (!m_res_out_fsync_func.isnull())
373         m_res_out_fsync_func(line);
374
375      /* call virtual function */
376      field_sync_changed(m_field_sync);
377   }
378}
379
380
381
382//-------------------------------------------------
383//  next_scanline
384//-------------------------------------------------
385
386ATTR_FORCE_INLINE void mc6847_friend_device::next_scanline(void)
387{
388   /* advance to next scanline */
389   m_physical_scanline++;
390   m_logical_scanline++;
391   m_partial_scanline_clocks = 0;
392
393   /* check for movement into the next "zone" */
394   if (m_logical_scanline_zone == SCANLINE_ZONE_FRAME_END)
395   {
396      /* we're now in the top border */
397      m_logical_scanline = 0;
398      m_logical_scanline_zone = SCANLINE_ZONE_TOP_BORDER;
399   }
400   else if ((m_logical_scanline_zone < SCANLINE_ZONE_VBLANK) && (m_physical_scanline >= 25+192+26+6))
401   {
402      /* we're now into vblank */
403      m_logical_scanline = 0;
404      m_logical_scanline_zone = SCANLINE_ZONE_VBLANK;
405   }
406   else if ((m_logical_scanline_zone < SCANLINE_ZONE_RETRACE) && (m_physical_scanline >= 25+192+26))
407   {
408      /* we're now into retrace */
409      m_logical_scanline = 0;
410      m_logical_scanline_zone = SCANLINE_ZONE_RETRACE;
411   }
412   else if ((m_logical_scanline_zone == SCANLINE_ZONE_TOP_BORDER) && (m_logical_scanline >= m_top_border_scanlines))
413   {
414      /* we're now into the body */
415      m_logical_scanline = 0;
416      m_logical_scanline_zone = SCANLINE_ZONE_BODY;
417   }
418   else if ((m_logical_scanline_zone == SCANLINE_ZONE_BODY) && (m_logical_scanline >= m_body_scanlines))
419   {
420      /* we're now into the bottom border */
421      m_logical_scanline = 0;
422      m_logical_scanline_zone = SCANLINE_ZONE_BOTTOM_BORDER;
423      enter_bottom_border();
424   }
425}
426
427
428
429//-------------------------------------------------
430//  horizontal_sync_changed
431//-------------------------------------------------
432
433void mc6847_friend_device::horizontal_sync_changed(bool line)
434{
435}
436
437
438
439//-------------------------------------------------
440//  field_sync_changed
441//-------------------------------------------------
442
443void mc6847_friend_device::field_sync_changed(bool line)
444{
445}
446
447
448
449//-------------------------------------------------
450//  enter_bottom_border
451//-------------------------------------------------
452
453void mc6847_friend_device::enter_bottom_border(void)
454{
455}
456
457
458
459//-------------------------------------------------
460//  record_border_scanline
461//-------------------------------------------------
462
463void mc6847_friend_device::record_border_scanline(UINT16 physical_scanline)
464{
465}
466
467
468
469//-------------------------------------------------
470//  get_clocks_since_hsync
471//-------------------------------------------------
472
473INT32 mc6847_friend_device::get_clocks_since_hsync()
474{
475   UINT64 hsync_on_clocks = attotime_to_clocks(m_hsync_on_timer->start());
476   UINT64 current_clocks = attotime_to_clocks(machine().time());
477   return (INT32) (current_clocks - hsync_on_clocks);
478}
479
480
481
482//-------------------------------------------------
483//  video_flush
484//-------------------------------------------------
485
486void mc6847_friend_device::video_flush()
487{
488   // first, only flush if...
489   //   1.  We support partial scanlines
490   //   2.  We're not already recording
491   //   3.  We're in the body
492   if (m_supports_partial_body_scanlines && !m_recording_scanline && (m_logical_scanline_zone == SCANLINE_ZONE_BODY))
493   {
494      UINT32 new_partial_scanline_clocks = get_clocks_since_hsync();
495      if (m_partial_scanline_clocks < new_partial_scanline_clocks)
496      {
497         if (LOG_FLUSH)
498            logerror("%s: new_partial_scanline_clocks=%u\n", describe_context(), new_partial_scanline_clocks);
499
500         m_recording_scanline = true;
501         record_partial_body_scanline(m_physical_scanline, m_logical_scanline, m_partial_scanline_clocks, new_partial_scanline_clocks);
502         m_recording_scanline = false;
503
504         m_partial_scanline_clocks = new_partial_scanline_clocks;
505      }
506   }
507}
508
509
510
511//-------------------------------------------------
512//  describe_context
513//-------------------------------------------------
514
515const char *mc6847_friend_device::describe_context(void)
516{
517   static char buffer[128];
518   snprintf(buffer, ARRAY_LENGTH(buffer), "%s (scanline %s:%d)",
519      machine().describe_context(),
520      scanline_zone_string((scanline_zone) m_logical_scanline_zone),
521      m_logical_scanline);
522   return buffer;
523}
524
525
526
527//**************************************************************************
528//  BASE DEVICE
529//**************************************************************************
530
531//-------------------------------------------------
532//  ctor
533//-------------------------------------------------
534
535mc6847_base_device::mc6847_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const UINT8 *fontdata, double tpfs)
536   :   mc6847_friend_device(mconfig, type, name, tag, owner, clock, fontdata, (type == MC6847T1_NTSC) || (type == MC6847T1_PAL), tpfs, 25+191, true)
537{
538   m_palette = s_palette;
539
540   for (int i = 0; i < ARRAY_LENGTH(s_palette); i++)
541   {
542      m_bw_palette[i] = black_and_white(s_palette[i]);
543   }
544}
545
546
547
548//-------------------------------------------------
549//  setup_fixed_mode - sets up a particular video
550//  mode bit with a decb callback
551//-------------------------------------------------
552
553void mc6847_base_device::setup_fixed_mode(struct devcb_read_line callback, UINT8 mode)
554{
555   if (callback.type == DEVCB_TYPE_NULL)
556   {
557      // do nothing
558   }
559   else if (callback.type == DEVCB_TYPE_CONSTANT && (callback.index == 0 || callback.index == 1))
560   {
561      // this mode is fixed
562      m_fixed_mode |= (callback.index ? mode : 0x00);
563      m_fixed_mode_mask |= mode;
564   }
565   else
566   {
567      // for reasons of performance, we currently only support DEVCB_NULL,
568      // DEVCB_LINE_GND and DEVCB_LINE_VCC
569      emu_fatalerror("mc6847 does not support this callback type for mode bits\n");
570   }
571}
572
573
574
575//-------------------------------------------------
576//  device_start - device-specific startup
577//-------------------------------------------------
578
579void mc6847_base_device::device_start()
580{
581   const mc6847_interface *config = (const mc6847_interface *) static_config();
582   assert(config);
583
584   /* inherited function */
585   mc6847_friend_device::device_start();
586
587   /* setup */
588   memset(m_data, 0, sizeof(m_data));
589
590   /* resolve callbacks */
591   m_res_input_func.resolve(config->m_input_func, *this);
592   m_res_out_hsync_func.resolve(config->m_out_hsync_func, *this);
593   m_res_out_fsync_func.resolve(config->m_out_fsync_func, *this);
594   m_get_char_rom = config->m_get_char_rom;
595
596   /* set up fixed mode */
597   m_fixed_mode = 0x00;
598   m_fixed_mode_mask = 0x00;
599   setup_fixed_mode(config->m_in_gm2_func,     MODE_GM2);
600   setup_fixed_mode(config->m_in_gm1_func,     MODE_GM1);
601   setup_fixed_mode(config->m_in_gm0_func,     MODE_GM0);
602   setup_fixed_mode(config->m_in_intext_func,  MODE_INTEXT);
603   setup_fixed_mode(config->m_in_inv_func,     MODE_INV);
604   setup_fixed_mode(config->m_in_as_func,      MODE_AS);
605   setup_fixed_mode(config->m_in_ag_func,      MODE_AG);
606   setup_fixed_mode(config->m_in_css_func,     MODE_CSS);
607
608   m_dirty = false;
609
610   /* state save */
611   save_item(NAME(m_dirty));
612   save_item(NAME(m_mode));
613
614   /* colors */
615   m_palette = config->m_black_and_white ? m_bw_palette : s_palette;
616}
617
618
619
620//-------------------------------------------------
621//  device_reset - device-specific reset
622//-------------------------------------------------
623
624void mc6847_base_device::device_reset()
625{
626   mc6847_friend_device::device_reset();
627   m_mode = m_fixed_mode;
628}
629
630
631
632//-------------------------------------------------
633//  input
634//-------------------------------------------------
635
636UINT8 mc6847_base_device::input(UINT16 address)
637{
638   UINT8 data = m_res_input_func(address);
639   if (LOG_INPUT)
640      logerror("%s: input: address=0x%04X data=0x%02X\n", describe_context(), address, data);
641   return data;
642}
643
644
645
646//-------------------------------------------------
647//  record_scanline_res
648//-------------------------------------------------
649
650template<int sample_count, int yres>
651void mc6847_base_device::record_scanline_res(int scanline, INT32 start_pos, INT32 end_pos)
652{
653   UINT8 current_sample_count = (start_pos > 0) ? m_data[scanline].m_sample_count : 0;
654
655   // main loop
656   for (INT32 pos = start_pos; pos < end_pos; pos++)
657   {
658      // set address at beginning of line
659      if (pos == 0)
660         m_video_address = scanline / (192 / yres) * sample_count;
661
662      if ((sample_count == 32) || ((pos % 1) == 0))
663      {
664         // input data
665         UINT8 data = input(m_video_address++);
666
667         if (pos < 32)
668         {
669            // update values
670            //assert(current_sample_count >= 0);
671            assert(current_sample_count < ARRAY_LENGTH(m_data[scanline].m_mode));
672            update_value(&m_data[scanline].m_mode[current_sample_count], simplify_mode(data, m_mode));
673            update_value(&m_data[scanline].m_data[current_sample_count], data);
674            current_sample_count++;
675         }
676      }
677   }
678
679   // update sample count
680   update_value(&m_data[scanline].m_sample_count, current_sample_count);
681}
682
683
684
685//-------------------------------------------------
686//  record_body_scanline
687//-------------------------------------------------
688
689ATTR_FORCE_INLINE void mc6847_base_device::record_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_pos, INT32 end_pos)
690{
691   // sanity checks
692   assert(scanline < 192);
693
694   if (m_mode & MODE_AG)
695   {
696      switch(m_mode & (MODE_GM2|MODE_GM1|MODE_GM0))
697      {
698         case 0:
699         case MODE_GM0:
700            record_scanline_res<16, 64>(scanline, start_pos, end_pos);
701            break;
702
703         case MODE_GM1:
704            record_scanline_res<32, 64>(scanline, start_pos, end_pos);
705            break;
706
707         case MODE_GM1|MODE_GM0:
708            record_scanline_res<16, 96>(scanline, start_pos, end_pos);
709            break;
710
711         case MODE_GM2:
712            record_scanline_res<32, 96>(scanline, start_pos, end_pos);
713            break;
714
715         case MODE_GM2|MODE_GM0:
716            record_scanline_res<16, 192>(scanline, start_pos, end_pos);
717            break;
718
719         case MODE_GM2|MODE_GM1:
720         case MODE_GM2|MODE_GM1|MODE_GM0:
721            record_scanline_res<32, 192>(scanline, start_pos, end_pos);
722            break;
723
724         default:
725            /* should not get here */
726            fatalerror("should not get here\n");
727            break;
728      }
729   }
730   else
731   {
732      record_scanline_res<32, 16>(scanline, start_pos, end_pos);
733   }
734}
735
736
737
738//-------------------------------------------------
739//  record_body_scanline
740//-------------------------------------------------
741
742void mc6847_base_device::record_body_scanline(UINT16 physical_scanline, UINT16 scanline)
743{
744   record_body_scanline(physical_scanline, scanline, 0, 32);
745}
746
747
748
749//-------------------------------------------------
750//  record_partial_body_scanline
751//-------------------------------------------------
752
753void mc6847_base_device::record_partial_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_clock, INT32 end_clock)
754{
755   INT32 start_pos = MAX(scanline_position_from_clock(start_clock), 0);
756   INT32 end_pos = MIN(scanline_position_from_clock(end_clock), 42);
757
758   if (start_pos < end_pos)
759      record_body_scanline(physical_scanline, scanline, start_pos, end_pos);
760}
761
762
763
764//-------------------------------------------------
765//  scanline_position_from_clock
766//-------------------------------------------------
767
768INT32 mc6847_base_device::scanline_position_from_clock(INT32 clocks_since_hsync)
769{
770   return (clocks_since_hsync - 20) / 4;
771}
772
773
774
775//-------------------------------------------------
776//  field_sync_changed
777//-------------------------------------------------
778
779void mc6847_base_device::field_sync_changed(bool line)
780{
781   /* when field sync is on, the DA* enter the Hi-Z state */
782   if (line && !m_res_input_func.isnull())
783      m_res_input_func(~0);
784}
785
786
787
788//-------------------------------------------------
789//  border_value
790//-------------------------------------------------
791
792ATTR_FORCE_INLINE mc6847_base_device::pixel_t mc6847_base_device::border_value(UINT8 mode, const pixel_t *palette, bool is_mc6847t1)
793{
794   pixel_t result;
795   switch(mc6847_friend_device::border_value(mode, is_mc6847t1))
796   {
797      case BORDER_COLOR_BLACK:
798         result = palette[8];
799         break;
800      case BORDER_COLOR_GREEN:
801         result = palette[0];
802         break;
803      case BORDER_COLOR_WHITE:
804         result = palette[4];
805         break;
806      case BORDER_COLOR_ORANGE:
807         result = palette[7];
808         break;
809      default:
810         fatalerror("Should not get here\n");
811         break;
812   }
813   return result;
814}
815
816
817
818//-------------------------------------------------
819//  update
820//-------------------------------------------------
821
822UINT32 mc6847_base_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
823{
824   int base_x = 32;
825   int base_y = 25;
826   int x, x2, y;
827   bool is_mc6847t1 = (type() == MC6847T1_NTSC) || (type() == MC6847T1_PAL);
828   int min_x = USE_HORIZONTAL_CLIP ? cliprect.min_x : 0;
829   int max_x = USE_HORIZONTAL_CLIP ? cliprect.max_x : (base_x * 2 + 256 - 1);
830   int min_y = cliprect.min_y;
831   int max_y = cliprect.max_y;
832   const pixel_t *palette = m_palette;
833
834   /* if the video didn't change, indicate as much */
835   if (!has_video_changed())
836      return UPDATE_HAS_NOT_CHANGED;
837
838   /* top border */
839   for (y = min_y; y < base_y; y++)
840   {
841      for (x = min_x; x <= max_x; x++)
842      {
843         *bitmap_addr(bitmap, y, x) = border_value(m_data[0].m_mode[0], palette, is_mc6847t1);
844      }
845   }
846
847   for (y = MAX(0, min_y - base_y); y <= MIN(192, max_y - base_y); y++)
848   {
849      /* left border */
850      for (x = min_x; x < base_x; x++)
851      {
852         *bitmap_addr(bitmap, y + base_y, x) = border_value(m_data[y].m_mode[0], palette, is_mc6847t1);
853      }
854
855      /* body */
856      x = 0;
857      int width = m_data[y].m_sample_count;
858      pixel_t *RESTRICT pixels = bitmap_addr(bitmap, base_y + y, base_x);
859      while(x < width)
860      {
861         /* determine how many bytes exist for which the mode is identical */
862         for (x2 = x + 1; (x2 < width) && (m_data[y].m_mode[x] == m_data[y].m_mode[x2]); x2++)
863            ;
864
865         /* emit the samples */
866         pixels += emit_mc6847_samples<1>(
867            m_data[y].m_mode[x],
868            &m_data[y].m_data[x],
869            x2 - x,
870            pixels,
871            m_palette,
872            m_get_char_rom,
873            x,
874            y);
875
876         /* update x */
877         x = x2;
878      }
879
880      /* right border */
881      for (x = base_x + 256; x <= max_x; x++)
882      {
883         *bitmap_addr(bitmap, y + base_y, x) = border_value(m_data[y].m_mode[width - 1], palette, is_mc6847t1);
884      }
885
886      /* artifacting */
887      m_artifacter.process_artifacts<1>(bitmap_addr(bitmap, y + base_y, base_x), m_data[y].m_mode[0], palette);
888   }
889
890   /* bottom border */
891   for (y = base_y + 192; y <= max_y; y++)
892   {
893      for (x = min_x; x <= max_x; x++)
894      {
895         int width = m_data[191].m_sample_count;
896         *bitmap_addr(bitmap, y, x) = border_value(m_data[191].m_mode[width - 1], palette, is_mc6847t1);
897      }
898   }
899   return 0;
900}
901
902
903
904//**************************************************************************
905//  CHARACTER MAP
906//**************************************************************************
907
908mc6847_friend_device::character_map::character_map(const UINT8 *text_fontdata, bool is_mc6847t1)
909{
910   int mode, i;
911
912   // set up font data
913   for (i = 0; i < 64*12; i++)
914   {
915      m_text_fontdata_inverse[i]              = text_fontdata[i] ^ 0xFF;
916      m_text_fontdata_lower_case[i]           = text_fontdata[i + (i < 32*12 ? 64*12 : 0)] ^ (i < 32*12 ? 0xFF : 0x00);
917      m_text_fontdata_lower_case_inverse[i]   = m_text_fontdata_lower_case[i] ^ 0xFF;
918   }
919
920   // loop through all modes
921   for (mode = 0; mode < sizeof(m_entries) / sizeof(m_entries[0]); mode++)
922   {
923      const UINT8 *fontdata;
924      UINT8 character_mask;
925      UINT8 color_shift_0 = 0;
926      UINT8 color_shift_1 = 0;
927      UINT8 color_mask_0 = 0x00;
928      UINT8 color_mask_1 = 0x00;
929      UINT16 color_base_0;
930      UINT16 color_base_1;
931
932      if ((mode & MODE_INTEXT) && !is_mc6847t1)
933      {
934         // semigraphics 6
935         fontdata            = semigraphics6_fontdata8x12;
936         character_mask      = 0x3F;
937         color_base_0        = 8;
938         color_base_1        = mode & MODE_CSS ? 4 : 0;
939         color_shift_1       = 6;
940         color_mask_1        = 0x03;
941      }
942      else if (mode & MODE_AS)
943      {
944         // semigraphics 4
945         fontdata            = semigraphics4_fontdata8x12;
946         character_mask      = 0x0F;
947         color_base_0        = 8;
948         color_base_1        = 0;
949         color_shift_1       = 4;
950         color_mask_1        = 0x07;
951      }
952      else
953      {
954         // text
955         bool is_lower_case  = is_mc6847t1 && ((mode & MODE_INV) == 0) && (mode & MODE_GM0);
956         bool is_inverse1    = (mode & MODE_INV) ? true : false;
957         bool is_inverse2    = is_mc6847t1 && (mode & MODE_GM1);
958         bool is_inverse     = (is_inverse1 && !is_inverse2) || (!is_inverse1 && is_inverse2);
959         fontdata            = is_inverse
960                           ? (is_lower_case ? m_text_fontdata_lower_case_inverse : m_text_fontdata_inverse)
961                           : (is_lower_case ? m_text_fontdata_lower_case : text_fontdata);
962         character_mask      = 0x3F;
963         color_base_0        = (mode & MODE_CSS ? 14 : 12);
964         color_base_1        = (mode & MODE_CSS ? 15 : 13);
965      }
966
967      // populate the entry
968      memset(&m_entries[mode], 0, sizeof(m_entries[mode]));
969      m_entries[mode].m_fontdata          = fontdata;
970      m_entries[mode].m_character_mask    = character_mask;
971      m_entries[mode].m_color_shift_0     = color_shift_0;
972      m_entries[mode].m_color_shift_1     = color_shift_1;
973      m_entries[mode].m_color_mask_0      = color_mask_0;
974      m_entries[mode].m_color_mask_1      = color_mask_1;
975      m_entries[mode].m_color_base_0      = color_base_0;
976      m_entries[mode].m_color_base_1      = color_base_1;
977   }
978}
979
980
981
982//-------------------------------------------------
983//  pal_round_fontdata8x12
984//-------------------------------------------------
985
986const UINT8 mc6847_friend_device::pal_round_fontdata8x12[] =
987{
988   0x00, 0x00, 0x38, 0x44, 0x04, 0x34, 0x4C, 0x4C, 0x38, 0x00, 0x00, 0x00,
989   0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x00, 0x00, 0x00,
990   0x00, 0x00, 0x78, 0x24, 0x24, 0x38, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
991   0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
992   0x00, 0x00, 0x78, 0x24, 0x24, 0x24, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
993   0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
994   0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
995   0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x4C, 0x44, 0x38, 0x00, 0x00, 0x00,
996   0x00, 0x00, 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
997   0x00, 0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
998   0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
999   0x00, 0x00, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
1000   0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
1001   0x00, 0x00, 0x44, 0x6C, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1002   0x00, 0x00, 0x44, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x44, 0x00, 0x00, 0x00,
1003   0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1004   0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
1005   0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
1006   0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
1007   0x00, 0x00, 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1008   0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1009   0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1010   0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00,
1011   0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x54, 0x6C, 0x44, 0x00, 0x00, 0x00,
1012   0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00, 0x00, 0x00,
1013   0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1014   0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7C, 0x00, 0x00, 0x00,
1015   0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00, 0x00,
1016   0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
1017   0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
1018   0x00, 0x00, 0x10, 0x38, 0x54, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1019   0x00, 0x00, 0x00, 0x10, 0x20, 0x7C, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00,
1020   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1021   0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
1022   0x00, 0x00, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1023   0x00, 0x00, 0x28, 0x28, 0x7C, 0x28, 0x7C, 0x28, 0x28, 0x00, 0x00, 0x00,
1024   0x00, 0x00, 0x10, 0x3C, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00, 0x00, 0x00,
1025   0x00, 0x00, 0x60, 0x64, 0x08, 0x10, 0x20, 0x4C, 0x0C, 0x00, 0x00, 0x00,
1026   0x00, 0x00, 0x20, 0x50, 0x50, 0x20, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
1027   0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1028   0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
1029   0x00, 0x00, 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
1030   0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00,
1031   0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
1032   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x40, 0x00, 0x00,
1033   0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1034   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1035   0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
1036   0x00, 0x00, 0x38, 0x44, 0x4C, 0x54, 0x64, 0x44, 0x38, 0x00, 0x00, 0x00,
1037   0x00, 0x00, 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1038   0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
1039   0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1040   0x00, 0x00, 0x08, 0x18, 0x28, 0x48, 0x7C, 0x08, 0x08, 0x00, 0x00, 0x00,
1041   0x00, 0x00, 0x7C, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1042   0x00, 0x00, 0x38, 0x40, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1043   0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00,
1044   0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1045   0x00, 0x00, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x38, 0x00, 0x00, 0x00,
1046   0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
1047   0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00,
1048   0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
1049   0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
1050   0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
1051   0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
1052
1053   /* Lower case */
1054   0x00, 0x00, 0x18, 0x24, 0x20, 0x70, 0x20, 0x24, 0x78, 0x00, 0x00, 0x00,
1055   0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x3C, 0x44, 0x3C, 0x00, 0x00, 0x00,
1056   0x00, 0x00, 0x40, 0x40, 0x58, 0x64, 0x44, 0x64, 0x58, 0x00, 0x00, 0x00,
1057   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
1058   0x00, 0x00, 0x04, 0x04, 0x34, 0x4C, 0x44, 0x4C, 0x34, 0x00, 0x00, 0x00,
1059   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x7C, 0x40, 0x38, 0x00, 0x00, 0x00,
1060   0x00, 0x00, 0x08, 0x14, 0x10, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1061   0x00, 0x00, 0x00, 0x00, 0x34, 0x4C, 0x44, 0x4C, 0x34, 0x04, 0x38, 0x00,
1062   0x00, 0x00, 0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1063   0x00, 0x00, 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1064   0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00,
1065   0x00, 0x00, 0x40, 0x40, 0x48, 0x50, 0x60, 0x50, 0x48, 0x00, 0x00, 0x00,
1066   0x00, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1067   0x00, 0x00, 0x00, 0x00, 0x78, 0x54, 0x54, 0x54, 0x54, 0x00, 0x00, 0x00,
1068   0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1069   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1070   0x00, 0x00, 0x00, 0x00, 0x78, 0x44, 0x44, 0x44, 0x78, 0x40, 0x40, 0x00,
1071   0x00, 0x00, 0x00, 0x00, 0x3C, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x00,
1072   0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
1073   0x00, 0x00, 0x00, 0x00, 0x3C, 0x40, 0x38, 0x04, 0x78, 0x00, 0x00, 0x00,
1074   0x00, 0x00, 0x20, 0x20, 0x70, 0x20, 0x20, 0x24, 0x18, 0x00, 0x00, 0x00,
1075   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x4C, 0x34, 0x00, 0x00, 0x00,
1076   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00,
1077   0x00, 0x00, 0x00, 0x00, 0x44, 0x54, 0x54, 0x28, 0x28, 0x00, 0x00, 0x00,
1078   0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00,
1079   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x38, 0x00, 0x00,
1080   0x00, 0x00, 0x00, 0x00, 0x7C, 0x08, 0x10, 0x20, 0x7C, 0x00, 0x00, 0x00,
1081   0x00, 0x00, 0x08, 0x10, 0x10, 0x20, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,
1082   0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1083   0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00,
1084   0x00, 0x00, 0x20, 0x54, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1085   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00
1086};
1087
1088
1089
1090//-------------------------------------------------
1091//  pal_square_fontdata8x12
1092//-------------------------------------------------
1093
1094const UINT8 mc6847_friend_device::pal_square_fontdata8x12[] =
1095{
1096   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x1A, 0x2A, 0x2A, 0x1C, 0x00, 0x00,
1097   0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x00, 0x00,
1098   0x00, 0x00, 0x00, 0x3C, 0x12, 0x12, 0x1C, 0x12, 0x12, 0x3C, 0x00, 0x00,
1099   0x00, 0x00, 0x00, 0x1C, 0x22, 0x20, 0x20, 0x20, 0x22, 0x1C, 0x00, 0x00,
1100   0x00, 0x00, 0x00, 0x3C, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3C, 0x00, 0x00,
1101   0x00, 0x00, 0x00, 0x3E, 0x20, 0x20, 0x3C, 0x20, 0x20, 0x3E, 0x00, 0x00,
1102   0x00, 0x00, 0x00, 0x3E, 0x20, 0x20, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00,
1103   0x00, 0x00, 0x00, 0x1E, 0x20, 0x20, 0x26, 0x22, 0x22, 0x1E, 0x00, 0x00,
1104   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22, 0x00, 0x00,
1105   0x00, 0x00, 0x00, 0x1C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1106   0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x22, 0x22, 0x1C, 0x00, 0x00,
1107   0x00, 0x00, 0x00, 0x22, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22, 0x00, 0x00,
1108   0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3E, 0x00, 0x00,
1109   0x00, 0x00, 0x00, 0x22, 0x36, 0x2A, 0x2A, 0x22, 0x22, 0x22, 0x00, 0x00,
1110   0x00, 0x00, 0x00, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x22, 0x22, 0x00, 0x00,
1111   0x00, 0x00, 0x00, 0x3E, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3E, 0x00, 0x00,
1112   0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00,
1113   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x2A, 0x24, 0x1A, 0x00, 0x00,
1114   0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x3C, 0x28, 0x24, 0x22, 0x00, 0x00,
1115   0x00, 0x00, 0x00, 0x1C, 0x22, 0x10, 0x08, 0x04, 0x22, 0x1C, 0x00, 0x00,
1116   0x00, 0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1117   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00,
1118   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00,
1119   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x2A, 0x2A, 0x36, 0x22, 0x00, 0x00,
1120   0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00,
1121   0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1122   0x00, 0x00, 0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x3E, 0x00, 0x00,
1123   0x00, 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00,
1124   0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00,
1125   0x00, 0x00, 0x00, 0x0E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E, 0x00, 0x00,
1126   0x00, 0x00, 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1127   0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x3E, 0x10, 0x08, 0x00, 0x00, 0x00,
1128   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1129   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00,
1130   0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1131   0x00, 0x00, 0x00, 0x14, 0x14, 0x36, 0x00, 0x36, 0x14, 0x14, 0x00, 0x00,
1132   0x00, 0x00, 0x00, 0x08, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x08, 0x00, 0x00,
1133   0x00, 0x00, 0x00, 0x32, 0x32, 0x04, 0x08, 0x10, 0x26, 0x26, 0x00, 0x00,
1134   0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x10, 0x2A, 0x24, 0x1A, 0x00, 0x00,
1135   0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1136   0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00,
1137   0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00, 0x00,
1138   0x00, 0x00, 0x00, 0x00, 0x08, 0x1C, 0x3E, 0x1C, 0x08, 0x00, 0x00, 0x00,
1139   0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x00,
1140   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x10, 0x20, 0x00, 0x00,
1141   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00,
1142   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
1143   0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00,
1144   0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00, 0x00,
1145   0x00, 0x00, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1146   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x1C, 0x20, 0x20, 0x3E, 0x00, 0x00,
1147   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x0C, 0x02, 0x22, 0x1C, 0x00, 0x00,
1148   0x00, 0x00, 0x00, 0x04, 0x0C, 0x14, 0x3E, 0x04, 0x04, 0x04, 0x00, 0x00,
1149   0x00, 0x00, 0x00, 0x3E, 0x20, 0x3C, 0x02, 0x02, 0x22, 0x1C, 0x00, 0x00,
1150   0x00, 0x00, 0x00, 0x1C, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x1C, 0x00, 0x00,
1151   0x00, 0x00, 0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00,
1152   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x1C, 0x22, 0x22, 0x1C, 0x00, 0x00,
1153   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x1E, 0x02, 0x02, 0x1C, 0x00, 0x00,
1154   0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
1155   0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00,
1156   0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00,
1157   0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00,
1158   0x00, 0x00, 0x00, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00,
1159   0x00, 0x00, 0x00, 0x18, 0x24, 0x04, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00,
1160
1161   /* Lower case */
1162   0x00, 0x00, 0x00, 0x0C, 0x12, 0x10, 0x38, 0x10, 0x12, 0x3C, 0x00, 0x00,
1163   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x02, 0x1E, 0x22, 0x1E, 0x00, 0x00,
1164   0x00, 0x00, 0x00, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x22, 0x3C, 0x00, 0x00,
1165   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x20, 0x20, 0x20, 0x1C, 0x00, 0x00,
1166   0x00, 0x00, 0x00, 0x02, 0x02, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x00, 0x00,
1167   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x3E, 0x20, 0x1C, 0x00, 0x00,
1168   0x00, 0x00, 0x00, 0x0C, 0x12, 0x10, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00,
1169   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x1C,
1170   0x00, 0x00, 0x00, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00,
1171   0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1172   0x00, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x24, 0x18,
1173   0x00, 0x00, 0x00, 0x20, 0x20, 0x24, 0x28, 0x38, 0x24, 0x22, 0x00, 0x00,
1174   0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1175   0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x2A, 0x2A, 0x2A, 0x2A, 0x00, 0x00,
1176   0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00, 0x00,
1177   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00,
1178   0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x22, 0x3C, 0x20, 0x20,
1179   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x03,
1180   0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
1181   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x00, 0x00,
1182   0x00, 0x00, 0x00, 0x10, 0x3C, 0x10, 0x10, 0x10, 0x12, 0x0C, 0x00, 0x00,
1183   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x26, 0x1A, 0x00, 0x00,
1184   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00,
1185   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x2A, 0x2A, 0x1C, 0x14, 0x00, 0x00,
1186   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00,
1187   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x1C,
1188   0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x04, 0x08, 0x10, 0x3E, 0x00, 0x00,
1189   0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x20, 0x10, 0x10, 0x08, 0x00, 0x00,
1190   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00,
1191   0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, 0x00,
1192   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00, 0x00,
1193   0x00, 0x00, 0x00, 0x08, 0x04, 0x3E, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00,
1194};
1195
1196
1197
1198//-------------------------------------------------
1199//  ntsc_round_fontdata8x12
1200//-------------------------------------------------
1201
1202const UINT8 mc6847_friend_device::ntsc_round_fontdata8x12[] =
1203{
1204   0x00, 0x00, 0x38, 0x44, 0x04, 0x34, 0x4C, 0x4C, 0x38, 0x00, 0x00, 0x00,
1205   0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x00, 0x00, 0x00,
1206   0x00, 0x00, 0x78, 0x24, 0x24, 0x38, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
1207   0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
1208   0x00, 0x00, 0x78, 0x24, 0x24, 0x24, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
1209   0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
1210   0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
1211   0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x4C, 0x44, 0x38, 0x00, 0x00, 0x00,
1212   0x00, 0x00, 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1213   0x00, 0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1214   0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1215   0x00, 0x00, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
1216   0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
1217   0x00, 0x00, 0x44, 0x6C, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1218   0x00, 0x00, 0x44, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x44, 0x00, 0x00, 0x00,
1219   0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1220   0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
1221   0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
1222   0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
1223   0x00, 0x00, 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1224   0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1225   0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1226   0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00,
1227   0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x54, 0x6C, 0x44, 0x00, 0x00, 0x00,
1228   0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00, 0x00, 0x00,
1229   0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1230   0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7C, 0x00, 0x00, 0x00,
1231   0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00, 0x00,
1232   0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
1233   0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
1234   0x00, 0x00, 0x10, 0x38, 0x54, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1235   0x00, 0x00, 0x00, 0x10, 0x20, 0x7C, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00,
1236   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237   0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
1238   0x00, 0x00, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239   0x00, 0x00, 0x28, 0x28, 0x7C, 0x28, 0x7C, 0x28, 0x28, 0x00, 0x00, 0x00,
1240   0x00, 0x00, 0x10, 0x3C, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00, 0x00, 0x00,
1241   0x00, 0x00, 0x60, 0x64, 0x08, 0x10, 0x20, 0x4C, 0x0C, 0x00, 0x00, 0x00,
1242   0x00, 0x00, 0x20, 0x50, 0x50, 0x20, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
1243   0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1244   0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
1245   0x00, 0x00, 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
1246   0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00,
1247   0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
1248   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x40, 0x00, 0x00,
1249   0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1251   0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
1252   0x00, 0x00, 0x38, 0x44, 0x4C, 0x54, 0x64, 0x44, 0x38, 0x00, 0x00, 0x00,
1253   0x00, 0x00, 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1254   0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
1255   0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1256   0x00, 0x00, 0x08, 0x18, 0x28, 0x48, 0x7C, 0x08, 0x08, 0x00, 0x00, 0x00,
1257   0x00, 0x00, 0x7C, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1258   0x00, 0x00, 0x38, 0x40, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1259   0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00,
1260   0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1261   0x00, 0x00, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x38, 0x00, 0x00, 0x00,
1262   0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
1263   0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00,
1264   0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
1265   0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
1266   0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
1267   0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
1268
1269   /* Lower case */
1270   0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1271   0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x3C, 0x44, 0x3C, 0x00, 0x00, 0x00,
1272   0x00, 0x00, 0x40, 0x40, 0x58, 0x64, 0x44, 0x64, 0x58, 0x00, 0x00, 0x00,
1273   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
1274   0x00, 0x00, 0x04, 0x04, 0x34, 0x4C, 0x44, 0x4C, 0x34, 0x00, 0x00, 0x00,
1275   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x7C, 0x40, 0x38, 0x00, 0x00, 0x00,
1276   0x00, 0x00, 0x08, 0x14, 0x10, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1277   0x00, 0x00, 0x00, 0x00, 0x34, 0x4C, 0x44, 0x4C, 0x34, 0x04, 0x38, 0x00,
1278   0x00, 0x00, 0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1279   0x00, 0x00, 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1280   0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00,
1281   0x00, 0x00, 0x40, 0x40, 0x48, 0x50, 0x60, 0x50, 0x48, 0x00, 0x00, 0x00,
1282   0x00, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1283   0x00, 0x00, 0x00, 0x00, 0x78, 0x54, 0x54, 0x54, 0x54, 0x00, 0x00, 0x00,
1284   0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1285   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1286   0x00, 0x00, 0x00, 0x00, 0x78, 0x44, 0x44, 0x44, 0x78, 0x40, 0x40, 0x00,
1287   0x00, 0x00, 0x00, 0x00, 0x3C, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x00,
1288   0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
1289   0x00, 0x00, 0x00, 0x00, 0x3C, 0x40, 0x38, 0x04, 0x78, 0x00, 0x00, 0x00,
1290   0x00, 0x00, 0x20, 0x20, 0x70, 0x20, 0x20, 0x24, 0x18, 0x00, 0x00, 0x00,
1291   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x4C, 0x34, 0x00, 0x00, 0x00,
1292   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00,
1293   0x00, 0x00, 0x00, 0x00, 0x44, 0x54, 0x54, 0x28, 0x28, 0x00, 0x00, 0x00,
1294   0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00,
1295   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x38, 0x00, 0x00,
1296   0x00, 0x00, 0x00, 0x00, 0x7C, 0x08, 0x10, 0x20, 0x7C, 0x00, 0x00, 0x00,
1297   0x00, 0x00, 0x08, 0x10, 0x10, 0x20, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,
1298   0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1299   0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00,
1300   0x00, 0x00, 0x20, 0x54, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1301   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00,
1302};
1303
1304
1305
1306//-------------------------------------------------
1307//  ntsc_square_fontdata8x12
1308//-------------------------------------------------
1309
1310const UINT8 mc6847_friend_device::ntsc_square_fontdata8x12[] =
1311{
1312   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x1A, 0x2A, 0x2A, 0x1C, 0x00, 0x00,
1313   0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x00, 0x00,
1314   0x00, 0x00, 0x00, 0x3C, 0x12, 0x12, 0x1C, 0x12, 0x12, 0x3C, 0x00, 0x00,
1315   0x00, 0x00, 0x00, 0x1C, 0x22, 0x20, 0x20, 0x20, 0x22, 0x1C, 0x00, 0x00,
1316   0x00, 0x00, 0x00, 0x3C, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3C, 0x00, 0x00,
1317   0x00, 0x00, 0x00, 0x3E, 0x20, 0x20, 0x38, 0x20, 0x20, 0x3E, 0x00, 0x00,
1318   0x00, 0x00, 0x00, 0x3E, 0x20, 0x20, 0x38, 0x20, 0x20, 0x20, 0x00, 0x00,
1319   0x00, 0x00, 0x00, 0x1E, 0x20, 0x20, 0x26, 0x22, 0x22, 0x1E, 0x00, 0x00,
1320   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22, 0x00, 0x00,
1321   0x00, 0x00, 0x00, 0x1C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1322   0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x22, 0x22, 0x1C, 0x00, 0x00,
1323   0x00, 0x00, 0x00, 0x22, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22, 0x00, 0x00,
1324   0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3E, 0x00, 0x00,
1325   0x00, 0x00, 0x00, 0x22, 0x36, 0x2A, 0x2A, 0x22, 0x22, 0x22, 0x00, 0x00,
1326   0x00, 0x00, 0x00, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x22, 0x22, 0x00, 0x00,
1327   0x00, 0x00, 0x00, 0x3E, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3E, 0x00, 0x00,
1328   0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00,
1329   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x2A, 0x24, 0x1A, 0x00, 0x00,
1330   0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x3C, 0x28, 0x24, 0x22, 0x00, 0x00,
1331   0x00, 0x00, 0x00, 0x1C, 0x22, 0x10, 0x08, 0x04, 0x22, 0x1C, 0x00, 0x00,
1332   0x00, 0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1333   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00,
1334   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00,
1335   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x2A, 0x2A, 0x36, 0x22, 0x00, 0x00,
1336   0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00,
1337   0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1338   0x00, 0x00, 0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x3E, 0x00, 0x00,
1339   0x00, 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00,
1340   0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00,
1341   0x00, 0x00, 0x00, 0x0E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E, 0x00, 0x00,
1342   0x00, 0x00, 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1343   0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x3E, 0x10, 0x08, 0x00, 0x00, 0x00,
1344   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1345   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00,
1346   0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1347   0x00, 0x00, 0x00, 0x14, 0x14, 0x36, 0x00, 0x36, 0x14, 0x14, 0x00, 0x00,
1348   0x00, 0x00, 0x00, 0x08, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x08, 0x00, 0x00,
1349   0x00, 0x00, 0x00, 0x32, 0x32, 0x04, 0x08, 0x10, 0x26, 0x26, 0x00, 0x00,
1350   0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x10, 0x2A, 0x24, 0x1A, 0x00, 0x00,
1351   0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1352   0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00,
1353   0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00, 0x00,
1354   0x00, 0x00, 0x00, 0x00, 0x08, 0x1C, 0x3E, 0x1C, 0x08, 0x00, 0x00, 0x00,
1355   0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x00,
1356   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x10, 0x20, 0x00, 0x00,
1357   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00,
1358   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
1359   0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00,
1360   0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00, 0x00,
1361   0x00, 0x00, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1362   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x1C, 0x20, 0x20, 0x3E, 0x00, 0x00,
1363   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x04, 0x02, 0x22, 0x1C, 0x00, 0x00,
1364   0x00, 0x00, 0x00, 0x04, 0x0C, 0x14, 0x3E, 0x04, 0x04, 0x04, 0x00, 0x00,
1365   0x00, 0x00, 0x00, 0x3E, 0x20, 0x3C, 0x02, 0x02, 0x22, 0x1C, 0x00, 0x00,
1366   0x00, 0x00, 0x00, 0x1C, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x1C, 0x00, 0x00,
1367   0x00, 0x00, 0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00,
1368   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x1C, 0x22, 0x22, 0x1C, 0x00, 0x00,
1369   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x1E, 0x02, 0x02, 0x1C, 0x00, 0x00,
1370   0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
1371   0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00,
1372   0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00,
1373   0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00,
1374   0x00, 0x00, 0x00, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00,
1375   0x00, 0x00, 0x00, 0x18, 0x24, 0x04, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00,
1376
1377   /* Lower case */
1378   0x00, 0x00, 0x00, 0x0C, 0x12, 0x10, 0x38, 0x10, 0x12, 0x3C, 0x00, 0x00,
1379   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x02, 0x1E, 0x22, 0x1E, 0x00, 0x00,
1380   0x00, 0x00, 0x00, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x22, 0x3C, 0x00, 0x00,
1381   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x20, 0x20, 0x20, 0x1C, 0x00, 0x00,
1382   0x00, 0x00, 0x00, 0x02, 0x02, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x00, 0x00,
1383   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x3E, 0x20, 0x1C, 0x00, 0x00,
1384   0x00, 0x00, 0x00, 0x0C, 0x12, 0x10, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00,
1385   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x1C,
1386   0x00, 0x00, 0x00, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00,
1387   0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1388   0x00, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x24, 0x18,
1389   0x00, 0x00, 0x00, 0x20, 0x20, 0x24, 0x28, 0x38, 0x24, 0x22, 0x00, 0x00,
1390   0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1391   0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x2A, 0x2A, 0x2A, 0x2A, 0x00, 0x00,
1392   0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00, 0x00,
1393   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00,
1394   0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x22, 0x3C, 0x20, 0x20,
1395   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x03,
1396   0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
1397   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x00, 0x00,
1398   0x00, 0x00, 0x00, 0x10, 0x3C, 0x10, 0x10, 0x10, 0x12, 0x0C, 0x00, 0x00,
1399   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x26, 0x1A, 0x00, 0x00,
1400   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00,
1401   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x2A, 0x2A, 0x1C, 0x14, 0x00, 0x00,
1402   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00,
1403   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x1C,
1404   0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x04, 0x08, 0x10, 0x3E, 0x00, 0x00,
1405   0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x20, 0x10, 0x10, 0x08, 0x00, 0x00,
1406   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00,
1407   0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, 0x00,
1408   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00, 0x00,
1409   0x00, 0x00, 0x00, 0x08, 0x04, 0x3E, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00
1410};
1411
1412
1413
1414//-------------------------------------------------
1415//  semigraphics4_fontdata8x12
1416//-------------------------------------------------
1417
1418const UINT8 mc6847_friend_device::semigraphics4_fontdata8x12[] =
1419{
1420   /* Block Graphics (Semigraphics 4 Graphics ) */
1421   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1422   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1423   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1424   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1425   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1426   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1427   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1428   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1429   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1430   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1431   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1432   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1433   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1434   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1435   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1436   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1437};
1438
1439
1440
1441//-------------------------------------------------
1442//  semigraphics6_fontdata8x12
1443//-------------------------------------------------
1444
1445const UINT8 mc6847_friend_device::semigraphics6_fontdata8x12[] =
1446{
1447   /* Semigraphics 6 */
1448   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1449   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F,
1450   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0,
1451   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
1452   0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
1453   0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1454   0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0,
1455   0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
1456   0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
1457   0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
1458   0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1459   0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
1460   0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
1461   0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F,
1462   0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0,
1463   0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1464   0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1465   0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F,
1466   0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0,
1467   0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
1468   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
1469   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1470   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0,
1471   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
1472   0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
1473   0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
1474   0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1475   0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
1476   0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
1477   0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F,
1478   0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0,
1479   0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1480   0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1481   0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F,
1482   0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0,
1483   0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
1484   0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
1485   0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1486   0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0,
1487   0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
1488   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
1489   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
1490   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1491   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
1492   0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
1493   0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F,
1494   0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0,
1495   0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1496   0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1497   0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F,
1498   0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0,
1499   0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
1500   0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
1501   0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1502   0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0,
1503   0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
1504   0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
1505   0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
1506   0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1507   0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
1508   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
1509   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F,
1510   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0,
1511   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1512};
1513
1514
1515
1516//**************************************************************************
1517//  ARTIFACTING
1518//**************************************************************************
1519
1520INPUT_PORTS_START(mc6847_artifacting)
1521   PORT_START(ARTIFACTING_TAG)
1522   PORT_CONFNAME( 0x03, 0x01, "Artifacting" )
1523   PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
1524   PORT_CONFSETTING(    0x01, DEF_STR( Standard ) )
1525   PORT_CONFSETTING(    0x02, DEF_STR( Reverse ) )
1526INPUT_PORTS_END
1527
1528ioport_constructor mc6847_base_device::device_input_ports() const
1529{
1530   return INPUT_PORTS_NAME(mc6847_artifacting);
1531}
1532
1533
1534
1535//-------------------------------------------------
1536//  ctor
1537//-------------------------------------------------
1538
1539mc6847_base_device::artifacter::artifacter()
1540{
1541   m_config = NULL;
1542   m_artifacting = 0;
1543   m_saved_artifacting = 0;
1544   m_saved_c0 = 0;
1545   m_saved_c1 = 0;
1546   memset(m_expanded_colors, 0, sizeof(m_expanded_colors));
1547}
1548
1549
1550
1551//-------------------------------------------------
1552//  artifacter::setup_config
1553//-------------------------------------------------
1554
1555void mc6847_base_device::artifacter::setup_config(device_t *device)
1556{
1557   char port_name[32];
1558   snprintf(port_name, ARRAY_LENGTH(port_name), "%s:%s", device->tag(), ARTIFACTING_TAG);
1559   m_config = device->ioport(port_name);
1560}
1561
1562
1563
1564//-------------------------------------------------
1565//  artifacter::update_colors
1566//-------------------------------------------------
1567
1568void mc6847_base_device::artifacter::update_colors(pixel_t c0, pixel_t c1)
1569{
1570   /* Boy this code sucks; this code was adapted from the old M6847
1571    * artifacting implmentation.  The only reason that it didn't look as
1572    * horrible was because the code around it sucked as well.  Now that I
1573    * have cleaned everything up, the ugliness is much more prominent.
1574    *
1575    * Hopefully we will have a generic artifacting algorithm that plugs into
1576    * the MESS/MAME core directly so we can chuck this hack */
1577   static const double artifact_colors[14*3] =
1578   {
1579      0.157, 0.000, 0.157, /* [ 1] - dk purple   (reverse  2) */
1580      0.000, 0.157, 0.000, /* [ 2] - dk green    (reverse  1) */
1581      1.000, 0.824, 1.000, /* [ 3] - lt purple   (reverse  4) */
1582      0.824, 1.000, 0.824, /* [ 4] - lt green    (reverse  3) */
1583      0.706, 0.236, 0.118, /* [ 5] - dk blue     (reverse  6) */
1584      0.000, 0.197, 0.471, /* [ 6] - dk red      (reverse  5) */
1585      1.000, 0.550, 0.393, /* [ 7] - lt blue     (reverse  8) */
1586      0.275, 0.785, 1.000, /* [ 8] - lt red      (reverse  7) */
1587      0.000, 0.500, 1.000, /* [ 9] - red         (reverse 10) */
1588      1.000, 0.500, 0.000, /* [10] - blue        (reverse  9) */
1589      1.000, 0.942, 0.785, /* [11] - cyan        (reverse 12) */
1590      0.393, 0.942, 1.000, /* [12] - yellow      (reverse 11) */
1591      0.236, 0.000, 0.000, /* [13] - black-blue  (reverse 14) */
1592      0.000, 0.000, 0.236  /* [14] - black-red   (reverse 13) */
1593   };
1594
1595   static const UINT8 artifact_correction[128] =
1596   {
1597      0,  0,       0,  0,      0,  6,      0,  2,
1598      5,  7,       5,  7,      1,  3,      1, 11,
1599      8,  6,       8, 14,      8,  9,      8,  9,
1600      4,  4,       4, 15,     12, 12,     12, 15,
1601
1602      5, 13,       5, 13,     13,  0,     13,  2,
1603      10, 10,     10, 10,     10, 15,     10, 11,
1604      3,  1,       3,  1,     15,  9,     15,  9,
1605      11, 11,     11, 11,     15, 15,     15, 15,
1606
1607      14,  0,     14,  0,     14,  6,     14,  2,
1608      0,  7,       0,  7,      1,  3,      1, 11,
1609      9,  6,       9, 14,      9,  9,      9,  9,
1610      15,  4,     15, 15,     12, 12,     12, 15,
1611
1612      2, 13,       2, 13,      2,  0,      2,  2,
1613      10, 10,     10, 10,     10, 15,     10, 11,
1614      12,  1,     12,  1,     12,  9,     12,  9,
1615      15, 11,     15, 11,     15, 15,     15, 15
1616   };
1617
1618   pixel_t colors[16];
1619   int i;
1620
1621   /* do we need to update our artifact colors table? */
1622   if ((m_artifacting != m_saved_artifacting) || (c0 != m_saved_c0) || (c1 != m_saved_c1))
1623   {
1624      m_saved_artifacting = m_artifacting;
1625      m_saved_c0 = colors[0] = c0;
1626      m_saved_c1 = colors[15] = c1;
1627
1628      /* mix the other colors */
1629      for (i = 1; i <= 14; i++)
1630      {
1631         const double *factors = &artifact_colors[((i - 1) ^ (m_artifacting & 0x01)) * 3];
1632
1633         colors[i] = (mix_color(factors[0], c0 >> 16, c1 >> 16) << 16)
1634               |   (mix_color(factors[1], c0 >>  8, c1 >>  8) <<  8)
1635               |   (mix_color(factors[2], c0 >>  0, c1 >>  0) <<  0);
1636      }
1637      for (i = 0; i < 128; i++)
1638      {
1639         m_expanded_colors[i] = colors[artifact_correction[i]];
1640      }
1641   }
1642}
1643
1644
1645
1646//-------------------------------------------------
1647//  artifacter::update
1648//-------------------------------------------------
1649
1650mc6847_base_device::pixel_t mc6847_base_device::artifacter::mix_color(double factor, UINT8 c0, UINT8 c1)
1651{
1652   return (UINT32) (UINT8) ((c0 * (1.0 - factor)) + (c1 * (0.0 + factor)) + 0.5);
1653}
1654
1655
1656
1657//**************************************************************************
1658//  VARIATIONS
1659//**************************************************************************
1660
1661const device_type MC6847_NTSC = &device_creator<mc6847_ntsc_device>;
1662const device_type MC6847_PAL = &device_creator<mc6847_pal_device>;
1663const device_type MC6847Y_NTSC = &device_creator<mc6847y_ntsc_device>;
1664const device_type MC6847Y_PAL = &device_creator<mc6847y_pal_device>;
1665const device_type MC6847T1_NTSC = &device_creator<mc6847t1_ntsc_device>;
1666const device_type MC6847T1_PAL = &device_creator<mc6847t1_pal_device>;
1667
1668
1669
1670//-------------------------------------------------
1671//  mc6847_ntsc_device
1672//-------------------------------------------------
1673
1674mc6847_ntsc_device::mc6847_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1675   : mc6847_base_device(mconfig, MC6847_NTSC, "MC6847_NTSC", tag, owner, clock, ntsc_square_fontdata8x12, 262.0)
1676{
1677}
1678
1679
1680
1681//-------------------------------------------------
1682//  mc6847_pal_device
1683//-------------------------------------------------
1684
1685mc6847_pal_device::mc6847_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1686   : mc6847_base_device(mconfig, MC6847_PAL, "MC6847_PAL", tag, owner, clock, pal_square_fontdata8x12, 262.0)
1687{
1688}
1689
1690
1691
1692//-------------------------------------------------
1693//  mc6847y_ntsc_device
1694//-------------------------------------------------
1695
1696mc6847y_ntsc_device::mc6847y_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1697   : mc6847_base_device(mconfig, MC6847Y_NTSC, "MC6847Y_NTSC", tag, owner, clock, ntsc_square_fontdata8x12, 262.5)
1698{
1699}
1700
1701
1702
1703//-------------------------------------------------
1704//  mc6847y_pal_device
1705//-------------------------------------------------
1706
1707mc6847y_pal_device::mc6847y_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1708   : mc6847_base_device(mconfig, MC6847Y_PAL, "MC6847Y_PAL", tag, owner, clock, pal_square_fontdata8x12, 262.5)
1709{
1710}
1711
1712
1713
1714//-------------------------------------------------
1715//  mc6847t1_ntsc_device
1716//-------------------------------------------------
1717
1718mc6847t1_ntsc_device::mc6847t1_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1719   : mc6847_base_device(mconfig, MC6847T1_NTSC, "MC6847T1_NTSC", tag, owner, clock, ntsc_round_fontdata8x12, 262.0)
1720{
1721}
1722
1723
1724
1725//-------------------------------------------------
1726//  mc6847t1_pal_device
1727//-------------------------------------------------
1728
1729mc6847t1_pal_device::mc6847t1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1730   : mc6847_base_device(mconfig, MC6847T1_PAL, "MC6847T1_PAL", tag, owner, clock, pal_round_fontdata8x12, 262.0)
1731{
1732}
Property changes on: trunk/src/emu/video/mc6847.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/video/hd44352.c
r0r21685
1/***************************************************************************
2
3        Hitachi HD44352 LCD controller
4
5***************************************************************************/
6
7#include "emu.h"
8#include "video/hd44352.h"
9
10#define     LCD_BYTE_INPUT          0x01
11#define     LCD_BYTE_OUTPUT         0x02
12#define     LCD_CHAR_OUTPUT         0x03
13#define     LCD_ON_OFF              0x04
14#define     LCD_CURSOR_GRAPHIC      0x06
15#define     LCD_CURSOR_CHAR         0x07
16#define     LCD_SCROLL_CHAR_WIDTH   0x08
17#define     LCD_CURSOR_STATUS       0x09
18#define     LCD_USER_CHARACTER      0x0b
19#define     LCD_CONTRAST            0x0c
20#define     LCD_IRQ_FREQUENCY       0x0d
21#define     LCD_CURSOR_POSITION     0x0e
22
23
24// devices
25const device_type HD44352 = &device_creator<hd44352_device>;
26
27//**************************************************************************
28//  live device
29//**************************************************************************
30
31//-------------------------------------------------
32//  hd44352_device - constructor
33//-------------------------------------------------
34
35hd44352_device::hd44352_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock):
36   device_t(mconfig, HD44352, "hd44352", tag, owner, clock)
37{
38}
39
40//-------------------------------------------------
41//  device_config_complete - perform any
42//  operations now that the configuration is
43//  complete
44//-------------------------------------------------
45
46void hd44352_device::device_config_complete()
47{
48   // inherit a copy of the static data
49   const hd44352_interface *intf = reinterpret_cast<const hd44352_interface *>(static_config());
50   if (intf != NULL)
51      *static_cast<hd44352_interface *>(this) = *intf;
52
53   // or initialize to defaults if none provided
54   else
55   {
56      memset(&m_on, 0, sizeof(m_on));
57   }
58}
59
60//-------------------------------------------------
61//  device_validity_check - perform validity checks
62//  on this device
63//-------------------------------------------------
64
65void hd44352_device::device_validity_check(validity_checker &valid) const
66{
67}
68//-------------------------------------------------
69//  device_start - device-specific startup
70//-------------------------------------------------
71
72void hd44352_device::device_start()
73{
74   m_on.resolve(m_on_cb, *this);
75
76   m_on_timer = timer_alloc(ON_TIMER);
77   m_on_timer->adjust(attotime::from_hz(m_clock/16384), 0, attotime::from_hz(m_clock/16384));
78
79   save_item( NAME(m_control_lines));
80   save_item( NAME(m_data_bus));
81   save_item( NAME(m_state));
82   save_item( NAME(m_offset));
83   save_item( NAME(m_char_width));
84   save_item( NAME(m_bank));
85   save_item( NAME(m_lcd_on));
86   save_item( NAME(m_scroll));
87   save_item( NAME(m_contrast));
88   save_item( NAME(m_byte_count));
89   save_item( NAME(m_cursor_status));
90   save_item( NAME(m_cursor_x));
91   save_item( NAME(m_cursor_y));
92   save_item( NAME(m_cursor_lcd));
93   save_item( NAME(m_video_ram[0]));
94   save_item( NAME(m_video_ram[1]));
95   save_item( NAME(m_par));
96   save_item( NAME(m_cursor));
97   save_item( NAME(m_custom_char[0]));
98   save_item( NAME(m_custom_char[1]));
99   save_item( NAME(m_custom_char[2]));
100   save_item( NAME(m_custom_char[3]));
101}
102
103
104//-------------------------------------------------
105//  device_reset - device-specific reset
106//-------------------------------------------------
107
108void hd44352_device::device_reset()
109{
110   memset(m_video_ram, 0x00, sizeof(m_video_ram));
111   memset(m_par, 0x00, sizeof(m_par));
112   memset(m_custom_char, 0x00, sizeof(m_custom_char));
113   memset(m_cursor, 0x00, sizeof(m_cursor));
114   m_control_lines = 0;
115   m_data_bus = 0xff;
116   m_state = 0;
117   m_bank = 0;
118   m_offset = 0;
119   m_char_width = 6;
120   m_lcd_on = 0;
121   m_scroll = 0;
122   m_byte_count = 0;
123   m_cursor_status = 0;
124   m_cursor_x = 0;
125   m_cursor_y = 0;
126   m_cursor_lcd = 0;
127   m_contrast = 0;
128}
129
130
131//-------------------------------------------------
132//  device_timer - handler timer events
133//-------------------------------------------------
134void hd44352_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
135{
136   switch(id)
137   {
138      case ON_TIMER:
139         if (m_control_lines & 0x40)
140         {
141            m_on(ASSERT_LINE);
142            m_on(CLEAR_LINE);
143         }
144         break;
145   }
146}
147
148//**************************************************************************
149//  device interface
150//**************************************************************************
151
152UINT32 hd44352_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
153{
154   UINT8 cw = m_char_width;
155
156   bitmap.fill(0, cliprect);
157
158   if (m_control_lines&0x80 && m_lcd_on)
159   {
160      for (int a=0; a<2; a++)
161         for (int py=0; py<4; py++)
162            for (int px=0; px<16; px++)
163               if (BIT(m_cursor_status, 4) && px == m_cursor_x && py == m_cursor_y && a == m_cursor_lcd)
164               {
165                  //draw the cursor
166                  for (int c=0; c<cw; c++)
167                  {
168                     UINT8 d = compute_newval((m_cursor_status>>5) & 0x07, m_video_ram[a][py*16*cw + px*cw + c + m_scroll * 48], m_cursor[c]);
169                     for (int b=0; b<8; b++)
170                     {
171                        bitmap.pix16(py*8 + b, a*cw*16 + px*cw + c) = BIT(d, 7-b);
172                     }
173                  }
174               }
175               else
176               {
177                  for (int c=0; c<cw; c++)
178                  {
179                     UINT8 d = m_video_ram[a][py*16*cw + px*cw + c + m_scroll * 48];
180                     for (int b=0; b<8; b++)
181                     {
182                        bitmap.pix16(py*8 + b, a*cw*16 + px*cw + c) = BIT(d, 7-b);
183                     }
184                  }
185               }
186   }
187
188   return 0;
189}
190
191
192void hd44352_device::control_write(UINT8 data)
193{
194   if(m_control_lines == data)
195      m_state = 0;
196
197   m_control_lines = data;
198}
199
200UINT8 hd44352_device::compute_newval(UINT8 type, UINT8 oldval, UINT8 newval)
201{
202   switch(type & 0x07)
203   {
204      case 0x00:
205         return (~oldval) & newval;
206      case 0x01:
207         return oldval ^ newval;
208      case 0x03:
209         return oldval & (~newval);
210      case 0x04:
211         return newval;
212      case 0x05:
213         return oldval | newval;
214      case 0x07:
215         return oldval;
216      case 0x02:
217      case 0x06:
218      default:
219         return 0;
220   }
221}
222
223UINT8 hd44352_device::get_char(UINT16 pos)
224{
225   switch ((UINT8)pos/8)
226   {
227      case 0xcf:
228         return m_custom_char[0][pos%8];
229      case 0xdf:
230         return m_custom_char[1][pos%8];
231      case 0xef:
232         return m_custom_char[2][pos%8];
233      case 0xff:
234         return m_custom_char[3][pos%8];
235      default:
236         return region()->u8(pos);
237   }
238}
239
240void hd44352_device::data_write(UINT8 data)
241{
242   // verify that controller is active
243   if (!(m_control_lines&0x80))
244      return;
245
246   if (m_control_lines & 0x01)
247   {
248      if (!(m_control_lines&0x02) && !(m_control_lines&0x04))
249         return;
250
251      switch (m_state)
252      {
253         case 0:     //parameter 0
254            m_par[m_state++] = data;
255            break;
256         case 1:     //parameter 1
257            m_par[m_state++] = data;
258            break;
259         case 2:     //parameter 2
260            m_par[m_state++] = data;
261            break;
262      }
263
264      switch (m_par[0] & 0x0f)
265      {
266         case LCD_BYTE_INPUT:
267         case LCD_CHAR_OUTPUT:
268            {
269               if (m_state == 1)
270                  m_bank = BIT(data, 4);
271               else if (m_state == 2)
272                  m_offset = ((data>>1)&0x3f) % 48 + (BIT(data,7) * 48);
273               else if (m_state == 3)
274                  m_offset += ((data & 0x03) * 96);
275            }
276            break;
277         case LCD_BYTE_OUTPUT:
278            {
279               if (m_state == 1)
280                  m_bank = BIT(data, 4);
281               else if (m_state == 2)
282                  m_offset = ((data>>1)&0x3f) % 48 + (BIT(data,7) * 48);
283               else if (m_state == 3)
284                  m_offset += ((data & 0x03) * 96);
285            }
286            break;
287         case LCD_ON_OFF:
288            {
289               if (m_state == 1)
290                  m_lcd_on = BIT(data, 4);
291               m_data_bus = 0xff;
292               m_state = 0;
293            }
294            break;
295         case LCD_SCROLL_CHAR_WIDTH:
296            {
297               if (m_state == 1)
298               {
299                  m_char_width = 8-((data>>4)&3);
300                  m_scroll = ((data>>6)&3);
301               }
302
303               m_data_bus = 0xff;
304               m_state = 0;
305            }
306            break;
307         case LCD_CURSOR_STATUS:
308            {
309               if (m_state == 1)
310                  m_cursor_status = data;
311               m_data_bus = 0xff;
312               m_state = 0;
313            }
314            break;
315         case LCD_CONTRAST:
316            {
317               if (m_state == 1)
318                  m_contrast = (m_contrast & 0x00ffff) | (data<<16);
319               else if (m_state == 2)
320                  m_contrast = (m_contrast & 0xff00ff) | (data<<8);
321               else if (m_state == 3)
322               {
323                  m_contrast = (m_contrast & 0xffff00) | (data<<0);
324                  m_state = 0;
325               }
326
327               m_data_bus = 0xff;
328            }
329            break;
330         case LCD_IRQ_FREQUENCY:
331            {
332               if (m_state == 1)
333               {
334                  UINT32 on_timer_rate;
335
336                  switch((data>>4) & 0x0f)
337                  {
338                     case 0x00:      on_timer_rate = 16384;      break;
339                     case 0x01:      on_timer_rate = 8;          break;
340                     case 0x02:      on_timer_rate = 16;         break;
341                     case 0x03:      on_timer_rate = 32;         break;
342                     case 0x04:      on_timer_rate = 64;         break;
343                     case 0x05:      on_timer_rate = 128;        break;
344                     case 0x06:      on_timer_rate = 256;        break;
345                     case 0x07:      on_timer_rate = 512;        break;
346                     case 0x08:      on_timer_rate = 1024;       break;
347                     case 0x09:      on_timer_rate = 2048;       break;
348                     case 0x0a:      on_timer_rate = 4096;       break;
349                     case 0x0b:      on_timer_rate = 4096;       break;
350                     default:        on_timer_rate = 8192;       break;
351                  }
352
353                  m_on_timer->adjust(attotime::from_hz(m_clock/on_timer_rate), 0, attotime::from_hz(m_clock/on_timer_rate));
354               }
355               m_data_bus = 0xff;
356               m_state = 0;
357            }
358            break;
359         case LCD_CURSOR_POSITION:
360            {
361               if (m_state == 1)
362                  m_cursor_lcd = BIT(data, 4);    //0:left lcd 1:right lcd;
363               else if (m_state == 2)
364                  m_cursor_x = ((data>>1)&0x3f) % 48 + (BIT(data,7) * 48);
365               else if (m_state == 3)
366               {
367                  m_cursor_y = data & 0x03;
368                  m_state = 0;
369               }
370
371               m_data_bus = 0xff;
372            }
373            break;
374      }
375
376      m_byte_count = 0;
377      m_data_bus = 0xff;
378   }
379   else
380   {
381      switch (m_par[0] & 0x0f)
382      {
383         case LCD_BYTE_INPUT:
384            {
385               if (((m_par[0]>>5) & 0x07) != 0x03)
386                  break;
387
388               m_offset %= 0x180;
389               m_data_bus = ((m_video_ram[m_bank][m_offset]<<4)&0xf0) | ((m_video_ram[m_bank][m_offset]>>4)&0x0f);
390               m_offset++; m_byte_count++;
391            }
392            break;
393         case LCD_BYTE_OUTPUT:
394            {
395               m_offset %= 0x180;
396               m_video_ram[m_bank][m_offset] = compute_newval((m_par[0]>>5) & 0x07, m_video_ram[m_bank][m_offset], data);
397               m_offset++; m_byte_count++;
398
399               m_data_bus = 0xff;
400            }
401            break;
402         case LCD_CHAR_OUTPUT:
403            {
404               int char_pos = data*8;
405
406               for (int i=0; i<m_char_width; i++)
407               {
408                  m_offset %= 0x180;
409                  m_video_ram[m_bank][m_offset] = compute_newval((m_par[0]>>5) & 0x07, m_video_ram[m_bank][m_offset], get_char(char_pos));
410                  m_offset++; char_pos++;
411               }
412
413               m_byte_count++;
414               m_data_bus = 0xff;
415            }
416            break;
417         case LCD_CURSOR_GRAPHIC:
418            if (m_byte_count<8)
419            {
420               m_cursor[m_byte_count] = data;
421               m_byte_count++;
422               m_data_bus = 0xff;
423            }
424            break;
425         case LCD_CURSOR_CHAR:
426            if (m_byte_count<1)
427            {
428               UINT8 char_code = ((data<<4)&0xf0) | ((data>>4)&0x0f);
429
430               for (int i=0; i<8; i++)
431                  m_cursor[i] = get_char(char_code*8 + i);
432
433               m_byte_count++;
434               m_data_bus = 0xff;
435            }
436            break;
437         case LCD_USER_CHARACTER:
438            if (m_byte_count<8)
439            {
440               m_custom_char[(m_par[1]&0x03)][m_byte_count] = data;
441               m_byte_count++;
442               m_data_bus = 0xff;
443            }
444            break;
445         default:
446            m_data_bus = 0xff;
447      }
448
449      m_state=0;
450   }
451}
452
453UINT8 hd44352_device::data_read()
454{
455   return m_data_bus;
456}
Property changes on: trunk/src/emu/video/hd44352.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/video/mc6847.h
r0r21685
1/*********************************************************************
2
3    mc6847.h
4
5    Implementation of Motorola 6847 video hardware chip
6
7***************************************************************************/
8
9#pragma once
10
11#ifndef __MC6847__
12#define __MC6847__
13
14
15//**************************************************************************
16//  MC6847 CONFIGURATION / INTERFACE
17//**************************************************************************
18
19#define MCFG_MC6847_REMOVE(_tag) \
20   MCFG_DEVICE_REMOVE(_tag)
21
22#define MCFG_MC6847_ADD(_tag, _variant, _clock, _config)        \
23   MCFG_DEVICE_ADD(_tag, _variant, _clock)                     \
24   MCFG_DEVICE_CONFIG(_config)
25
26#define MCFG_SCREEN_MC6847_NTSC_ADD(_tag, _mctag) \
27   MCFG_SCREEN_ADD(_tag, RASTER)                               \
28   MCFG_SCREEN_UPDATE_DEVICE(_mctag, mc6847_base_device, screen_update) \
29   MCFG_SCREEN_REFRESH_RATE(60)                                \
30   MCFG_SCREEN_SIZE(320, 243)                                  \
31   MCFG_SCREEN_VISIBLE_AREA(0, 320-1, 1, 241-1)                \
32   MCFG_SCREEN_VBLANK_TIME(0)
33#define MCFG_SCREEN_MC6847_PAL_ADD(_tag, _mctag) \
34   MCFG_SCREEN_ADD(_tag, RASTER)                               \
35   MCFG_SCREEN_UPDATE_DEVICE(_mctag, mc6847_base_device, screen_update) \
36   MCFG_SCREEN_REFRESH_RATE(50)                                \
37   MCFG_SCREEN_SIZE(320, 243)                                  \
38   MCFG_SCREEN_VISIBLE_AREA(0, 320-1, 1, 241-1)                \
39   MCFG_SCREEN_VBLANK_TIME(0)
40/* interface */
41struct mc6847_interface
42{
43   /* screen we are acting on */
44   const char *m_screen_tag;
45
46   /* if specified, this gets called whenever reading a byte (offs_t ~0 specifies DA* entering the tristate mode) */
47   devcb_read8                 m_input_func;
48
49   /* if specified, this gets called for every change of the HS pin (pin 38) */
50   devcb_write_line            m_out_hsync_func;
51
52   /* if specified, this gets called for every change of the FS pin (pin 37) */
53   devcb_write_line            m_out_fsync_func;
54
55   /* mode control lines input */
56   devcb_read_line             m_in_ag_func;
57   devcb_read_line             m_in_gm2_func;
58   devcb_read_line             m_in_gm1_func;
59   devcb_read_line             m_in_gm0_func;
60   devcb_read_line             m_in_css_func;
61   devcb_read_line             m_in_as_func;
62   devcb_read_line             m_in_intext_func;
63   devcb_read_line             m_in_inv_func;
64
65   /* if specified, this reads the external char rom off of the driver state */
66   UINT8 (*m_get_char_rom)(running_machine &machine, UINT8 ch, int line);
67
68   /* if true, this is black and white */
69   bool                        m_black_and_white;
70};
71
72#define ARTIFACTING_TAG     "artifacting"
73
74INPUT_PORTS_EXTERN(mc6847_artifacting);
75
76
77//**************************************************************************
78//  MC6847 CORE
79//**************************************************************************
80
81PALETTE_INIT( mc6847 );
82PALETTE_INIT( mc6847_bw );
83
84// base class so that the GIME emulation can access mc6847 stuff
85class mc6847_friend_device : public device_t
86{
87public:
88   // inlines
89   bool hs_r(void)                 { return m_horizontal_sync; }
90   bool fs_r(void)                 { return m_field_sync; }
91
92protected:
93   mc6847_friend_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock,
94      const UINT8 *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, bool supports_partial_body_scanlines);
95
96   // video mode constants
97   static const UINT8 MODE_AG      = 0x80;
98   static const UINT8 MODE_GM2     = 0x40;
99   static const UINT8 MODE_GM1     = 0x20;
100   static const UINT8 MODE_GM0     = 0x10;
101   static const UINT8 MODE_CSS     = 0x08;
102   static const UINT8 MODE_AS      = 0x04;
103   static const UINT8 MODE_INTEXT  = 0x02;
104   static const UINT8 MODE_INV     = 0x01;
105
106   // timer constants
107   static const device_timer_id TIMER_FRAME = 0;
108   static const device_timer_id TIMER_HSYNC_OFF = 1;
109   static const device_timer_id TIMER_HSYNC_ON = 2;
110   static const device_timer_id TIMER_FSYNC = 3;
111
112   // fonts
113   static const UINT8 pal_round_fontdata8x12[];
114   static const UINT8 pal_square_fontdata8x12[];
115   static const UINT8 ntsc_round_fontdata8x12[];
116   static const UINT8 ntsc_square_fontdata8x12[];
117   static const UINT8 semigraphics4_fontdata8x12[];
118   static const UINT8 semigraphics6_fontdata8x12[];
119
120   // pixel definitions
121   typedef UINT32 pixel_t;
122
123   pixel_t *bitmap_addr(bitmap_rgb32 &bitmap, int y, int x)
124   {
125      return &bitmap.pix32(y, x);
126   }
127
128   static UINT8 simplify_mode(UINT8 data, UINT8 mode)
129   {
130      // simplifies MC6847 modes to drop mode flags that are not significant
131      return mode & ~((mode & MODE_AG) ? (MODE_AS | MODE_INV) : 0);
132   }
133
134   // internal class that represents a MC6847 character map
135   class character_map
136   {
137   public:
138      // constructor that sets up the font data
139      character_map(const UINT8 *fontdata, bool is_mc6847t1);
140
141      // optimized template function that emits a single character
142      template<int xscale>
143      ATTR_FORCE_INLINE void emit_character(UINT8 mode, const UINT8 *data, int length, pixel_t *RESTRICT pixels, int y, const pixel_t *palette)
144      {
145         for (int i = 0; i < length; i++)
146         {
147            // get the character
148            UINT8 character = data[i];
149
150            // based on the mode, determine which entry to use
151            const entry *e = &m_entries[mode % (sizeof(m_entries) / sizeof(m_entries[0]))];
152
153            // identify the character in the font data
154            const UINT8 *font_character = e->m_fontdata + (character & e->m_character_mask) * 12;
155
156            // get the particular slice out
157            UINT8 font_character_slice = font_character[y % 12];
158
159            // get the two colors
160            UINT16 color_base_0 = e->m_color_base_0 + ((character >> e->m_color_shift_0) & e->m_color_mask_0);
161            UINT16 color_base_1 = e->m_color_base_1 + ((character >> e->m_color_shift_1) & e->m_color_mask_1);
162            pixel_t color_0 = palette[color_base_0];
163            pixel_t color_1 = palette[color_base_1];
164
165            // emit the bits
166            for (int j = 0; j < 8; j++)
167            {
168               for (int k = 0; k < xscale; k++)
169               {
170                  pixels[(i * 8 + j) * xscale + k] = bit_test(font_character_slice, j, color_0, color_1);
171               }
172            }
173         }
174      };
175
176   private:
177      struct entry
178      {
179         const UINT8 *m_fontdata;
180         UINT8 m_character_mask;
181         UINT8 m_color_shift_0;
182         UINT8 m_color_shift_1;
183         UINT8 m_color_mask_0;
184         UINT8 m_color_mask_1;
185         UINT16 m_color_base_0;
186         UINT16 m_color_base_1;
187      };
188
189      // lookup table for MC6847 modes to determine font data and color
190      entry m_entries[128];
191
192      // text font data calculated on startup
193      UINT8 m_text_fontdata_inverse[64*12];
194      UINT8 m_text_fontdata_lower_case[64*12];
195      UINT8 m_text_fontdata_lower_case_inverse[64*12];
196
197      // optimized function that tests a single bit
198      ATTR_FORCE_INLINE pixel_t bit_test(UINT8 data, int shift, pixel_t color_0, pixel_t color_1)
199      {
200         return data & (0x80 >> shift) ? color_1 : color_0;
201      }
202   };
203
204   // artficater internal class
205   class artifacter
206   {
207   public:
208      artifacter();
209
210      // artifacting config
211      void setup_config(device_t *device);
212      void poll_config(void) { m_artifacting = (m_config!=NULL) ? m_config->read() : 0; }
213
214      // artifacting application
215      template<int xscale>
216      ATTR_FORCE_INLINE void process_artifacts(pixel_t *pixels, UINT8 mode, const pixel_t *palette)
217      {
218         if (((mode & (MODE_AG|MODE_GM2|MODE_GM1|MODE_GM0)) == (MODE_AG|MODE_GM2|MODE_GM1|MODE_GM0))
219            && (m_artifacting != 0))
220         {
221            // identify the new colors and update
222            pixel_t c0 = palette[(mode & MODE_CSS) ? 10 : 8];
223            pixel_t c1 = palette[(mode & MODE_CSS) ? 11 : 9];
224            update_colors(c0, c1);
225
226            // generate the new line
227            pixel_t new_line[256];
228            int x, i;
229            for (x = 0; x < 256; x += 2)
230            {
231               UINT8 val = ((pixels[(x - 2) * xscale] == c1) ? 0x20 : 0x00)
232                  |   ((pixels[(x - 1) * xscale] == c1) ? 0x10 : 0x00)
233                  |   ((pixels[(x + 0) * xscale] == c1) ? 0x08 : 0x00)
234                  |   ((pixels[(x + 1) * xscale] == c1) ? 0x04 : 0x00)
235                  |   ((pixels[(x + 2) * xscale] == c1) ? 0x02 : 0x00)
236                  |   ((pixels[(x + 3) * xscale] == c1) ? 0x01 : 0x00);
237
238               new_line[x + 0] = m_expanded_colors[val * 2 + 0];
239               new_line[x + 1] = m_expanded_colors[val * 2 + 1];
240            }
241
242            // and copy it in
243            for (x = 0; x < 256; x++)
244            {
245               for (i = 0; i < xscale; i++)
246                  pixels[x * xscale + i] = new_line[x];
247            }
248         }
249      }
250
251   private:
252      ioport_port *m_config;
253      ioport_value m_artifacting;
254      ioport_value m_saved_artifacting;
255      pixel_t m_saved_c0, m_saved_c1;
256      pixel_t m_expanded_colors[128];
257
258      void update_colors(pixel_t c0, pixel_t c1);
259      static pixel_t mix_color(double factor, UINT8 c0, UINT8 c1);
260   };
261
262   enum border_color_t
263   {
264      BORDER_COLOR_BLACK,
265      BORDER_COLOR_GREEN,
266      BORDER_COLOR_WHITE,
267      BORDER_COLOR_ORANGE
268   };
269
270   // callbacks
271   devcb_resolved_write_line m_res_out_hsync_func;
272   devcb_resolved_write_line m_res_out_fsync_func;
273
274   // incidentals
275   character_map m_character_map;
276   artifacter m_artifacter;
277
278   // device-level overrides
279   virtual void device_start(void);
280   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
281   virtual void device_reset(void);
282   virtual void device_post_load(void);
283
284   // other overridables
285   virtual void new_frame(void);
286   virtual void horizontal_sync_changed(bool line);
287   virtual void field_sync_changed(bool line);
288   virtual void enter_bottom_border(void);
289   virtual void record_border_scanline(UINT16 physical_scanline);
290   virtual void record_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline) = 0;
291   virtual void record_partial_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline, INT32 start_clock, INT32 end_clock) = 0;
292
293   // miscellaneous
294   void video_flush(void);
295   const char *describe_context(void);
296
297   // setup functions
298   emu_timer *setup_timer(device_timer_id id, double offset, double period);
299
300   // converts to B&W
301   static pixel_t black_and_white(pixel_t color)
302   {
303      UINT8 average_color = (RGB_RED(color) + RGB_GREEN(color) + RGB_BLUE(color)) / 3;
304      return MAKE_RGB(average_color, average_color, average_color);
305   }
306
307   // changes the geometry
308   ATTR_FORCE_INLINE void set_geometry(UINT16 top_border_scanlines, UINT16 body_scanlines, bool wide)
309   {
310      if (UNEXPECTED((m_top_border_scanlines != top_border_scanlines)
311         || (m_body_scanlines != body_scanlines)
312         || (m_wide != wide)))
313      {
314         m_top_border_scanlines = top_border_scanlines;
315         m_body_scanlines = body_scanlines;
316         m_wide = wide;
317         update_field_sync_timer();
318      }
319   }
320
321   // calculates the border color
322   static ATTR_FORCE_INLINE border_color_t border_value(UINT8 mode, bool is_mc6847t1)
323   {
324      border_color_t result;
325
326      if (mode & MODE_AG)
327      {
328         // graphics
329         result = mode & MODE_CSS ? BORDER_COLOR_WHITE : BORDER_COLOR_GREEN;
330      }
331      else if (!is_mc6847t1 || ((mode & MODE_GM2) == 0))
332      {
333         // text, black border
334         result = BORDER_COLOR_BLACK;
335      }
336      else
337      {
338         // text, green or orange border
339         result = mode & MODE_CSS ? BORDER_COLOR_ORANGE : BORDER_COLOR_GREEN;
340      }
341      return result;
342   }
343
344   // checks to see if the video has changed
345   ATTR_FORCE_INLINE bool has_video_changed(void)
346   {
347      /* poll the artifacting config */
348      m_artifacter.poll_config();
349
350      /* if the video didn't change, indicate as much */
351      bool video_changed = m_video_changed;
352      m_video_changed = false;
353      return video_changed;
354   }
355
356   // updates a byte in the video state
357   template<class T>
358   ATTR_FORCE_INLINE bool update_value(T *ptr, T byte)
359   {
360      bool result = false;
361      if (*ptr != byte)
362      {
363         *ptr = byte;
364         m_video_changed = true;
365         result = true;
366      }
367      return result;
368   };
369
370   // template function for emitting graphics bytes
371   template<int bits_per_pixel, int xscale>
372   ATTR_FORCE_INLINE void emit_graphics(const UINT8 *data, int length, pixel_t *RESTRICT pixels, UINT16 color_base, const pixel_t *RESTRICT palette)
373   {
374      for (int i = 0; i < length; i++)
375      {
376         for (int j = 0; j < (8 / bits_per_pixel); j++)
377         {
378            for (int k = 0; k < xscale; k++)
379            {
380               UINT16 color = color_base + ((data[i] >> (8 - (j + 1) * bits_per_pixel)) & ((1 << bits_per_pixel) - 1));
381               pixels[(i * (8 / bits_per_pixel) + j) * xscale + k] = palette[color];
382            }
383         }
384      }
385   }
386
387   // template function for emitting samples
388   template<int xscale>
389   UINT32 emit_mc6847_samples(UINT8 mode, const UINT8 *data, int length, pixel_t *RESTRICT pixels, const pixel_t *RESTRICT palette,
390      UINT8 (*get_char_rom)(running_machine &machine, UINT8 ch, int line), int x, int y)
391   {
392      UINT32 result = 0;
393      if (mode & MODE_AG)
394      {
395         /* graphics */
396         switch(mode & (MODE_GM2|MODE_GM1|MODE_GM0))
397         {
398            case 0:
399               emit_graphics<2, xscale * 4>(data, length, pixels, (mode & MODE_CSS) ? 4 : 0, palette);
400               result = length * 8 * xscale * 2;
401               break;
402
403            case MODE_GM0:
404            case MODE_GM1|MODE_GM0:
405            case MODE_GM2|MODE_GM0:
406               emit_graphics<1, xscale * 2>(data, length, pixels, (mode & MODE_CSS) ? 10 : 8, palette);
407               result = length * 8 * xscale * 2;
408               break;
409
410            case MODE_GM1:
411            case MODE_GM2:
412            case MODE_GM2|MODE_GM1:
413               emit_graphics<2, xscale * 2>(data, length, pixels, (mode & MODE_CSS) ? 4 : 0, palette);
414               result = length * 8 * xscale;
415               break;
416
417            case MODE_GM2|MODE_GM1|MODE_GM0:
418               emit_graphics<1, xscale * 1>(data, length, pixels, (mode & MODE_CSS) ? 10 : 8, palette);
419               result = length * 8 * xscale;
420               break;
421
422            default:
423               /* should not get here */
424               fatalerror("Should not get here\n");
425               break;
426         }
427      }
428      else if ((get_char_rom != NULL) && ((mode & (MODE_AG|MODE_AS|MODE_INTEXT)) == MODE_INTEXT))
429      {
430         /* external ROM */
431         for (int i = 0; i < length; i++)
432         {
433            UINT8 byte = get_char_rom(machine(), data[i], y % 12) ^ (mode & MODE_INV ? 0xFF : 0x00);
434            emit_graphics<2, xscale * 2>(&byte, 1, &pixels[i * 8], (mode & MODE_CSS) ? 14 : 12, palette);
435         }
436         result = length * 8 * xscale;
437      }
438      else
439      {
440         /* text/semigraphics */
441         m_character_map.emit_character<xscale>(mode, data, length, pixels, y, palette);
442         result = length * 8 * xscale;
443      }
444      return result;
445   }
446
447private:
448   enum scanline_zone
449   {
450      SCANLINE_ZONE_TOP_BORDER,
451      SCANLINE_ZONE_BODY,
452      SCANLINE_ZONE_BOTTOM_BORDER,
453      SCANLINE_ZONE_RETRACE,
454      SCANLINE_ZONE_VBLANK,
455      SCANLINE_ZONE_FRAME_END
456   };
457
458   // timers
459   emu_timer *m_frame_timer;
460   emu_timer *m_hsync_on_timer;
461   emu_timer *m_hsync_off_timer;
462   emu_timer *m_fsync_timer;
463
464   // incidentals
465   double m_tpfs;
466   int m_field_sync_falling_edge_scanline;
467   bool m_wide;
468   bool m_video_changed;
469   UINT16 m_top_border_scanlines;
470   UINT16 m_body_scanlines;
471   bool m_recording_scanline;
472   bool m_supports_partial_body_scanlines;
473
474   // video state
475   UINT16 m_physical_scanline;
476   UINT16 m_logical_scanline;
477   UINT16 m_logical_scanline_zone;
478   bool m_horizontal_sync;
479   bool m_field_sync;
480   UINT32 m_partial_scanline_clocks;
481
482   // functions
483   void change_horizontal_sync(bool line);
484   void change_field_sync(bool line);
485   void update_field_sync_timer(void);
486   void next_scanline(void);
487   INT32 get_clocks_since_hsync();
488
489   // debugging
490   const char *scanline_zone_string(scanline_zone zone);
491};
492
493// actual base class for MC6847 family of devices
494class mc6847_base_device : public mc6847_friend_device
495{
496public:
497   /* updates the screen -- this will call begin_update(),
498      followed by update_row() reapeatedly and after all row
499      updating is complete, end_update() */
500   UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
501
502   // mode changing operations
503   DECLARE_WRITE_LINE_MEMBER( ag_w )       { change_mode(MODE_AG, state); }
504   DECLARE_WRITE_LINE_MEMBER( gm2_w )      { change_mode(MODE_GM2, state); }
505   DECLARE_WRITE_LINE_MEMBER( gm1_w )      { change_mode(MODE_GM1, state); }
506   DECLARE_WRITE_LINE_MEMBER( gm0_w )      { change_mode(MODE_GM0, state); }
507   DECLARE_WRITE_LINE_MEMBER( as_w )       { change_mode(MODE_AS, state); }
508   DECLARE_WRITE_LINE_MEMBER( css_w )      { change_mode(MODE_CSS, state); }
509   DECLARE_WRITE_LINE_MEMBER( intext_w )   { change_mode(MODE_INTEXT, state); }
510   DECLARE_WRITE_LINE_MEMBER( inv_w )      { change_mode(MODE_INV, state); }
511
512protected:
513   mc6847_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const UINT8 *fontdata, double tpfs);
514
515   // device-level overrides
516   virtual void device_start();
517   virtual void device_reset();
518   virtual ioport_constructor device_input_ports() const;
519
520   // other overrides
521   virtual void field_sync_changed(bool line);
522   virtual void record_body_scanline(UINT16 physical_scanline, UINT16 scanline);
523   virtual void record_partial_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline, INT32 start_clock, INT32 end_clock);
524
525private:
526   struct video_scanline
527   {
528      UINT8 m_sample_count;
529      UINT8 m_mode[32];
530      UINT8 m_data[32];
531   };
532
533   // palette
534   static const int PALETTE_LENGTH = 16;
535   static const UINT32 s_palette[PALETTE_LENGTH];
536
537   // callbacks
538   devcb_resolved_read8 m_res_input_func;
539   UINT8 (*m_get_char_rom)(running_machine &machine, UINT8 ch, int line);
540
541   // incidentals
542   UINT8 m_fixed_mode;
543   UINT8 m_fixed_mode_mask;
544   const pixel_t *m_palette;
545   pixel_t m_bw_palette[PALETTE_LENGTH];
546
547   // state
548   UINT8 m_mode;
549   UINT16 m_video_address;
550   bool m_dirty;
551   video_scanline m_data[192];
552
553   void change_mode(UINT8 mode, int state)
554   {
555      // sanity check, to ensure that we're not changing fixed modes
556      assert((mode & m_fixed_mode_mask) == 0);
557
558      // calculate new mode
559      UINT8 new_mode;
560      if (state)
561         new_mode = m_mode | mode;
562      else
563         new_mode = m_mode & ~mode;
564
565      // has the mode changed?
566      if (new_mode != m_mode)
567      {
568         // it has!  check dirty flag
569         video_flush();
570         if (!m_dirty)
571         {
572            m_dirty = true;
573         }
574
575         // and set the new mode
576         m_mode = new_mode;
577      }
578   }
579
580   // setup functions
581   void setup_fixed_mode(struct devcb_read_line callback, UINT8 mode);
582
583   // runtime functions
584   void record_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_pos, INT32 end_pos);
585   pixel_t border_value(UINT8 mode, const pixel_t *palette, bool is_mc6847t1);
586
587   template<int xscale>
588   void emit_samples(UINT8 mode, const UINT8 *data, int length, pixel_t *pixels, int x, int y);
589
590   // template function for doing video update collection
591   template<int sample_count, int yres>
592   void record_scanline_res(int scanline, INT32 start_pos, INT32 end_pos);
593
594   // miscellaneous
595   UINT8 input(UINT16 address);
596   INT32 scanline_position_from_clock(INT32 clocks_since_hsync);
597};
598
599
600//**************************************************************************
601//  VARIATIONS
602//**************************************************************************
603
604class mc6847_ntsc_device : public mc6847_base_device
605{
606public:
607   mc6847_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
608};
609
610class mc6847_pal_device : public mc6847_base_device
611{
612public:
613   mc6847_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
614};
615
616class mc6847y_ntsc_device : public mc6847_base_device
617{
618public:
619   mc6847y_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
620};
621
622class mc6847y_pal_device : public mc6847_base_device
623{
624public:
625   mc6847y_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
626};
627
628class mc6847t1_ntsc_device : public mc6847_base_device
629{
630public:
631   mc6847t1_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
632};
633
634class mc6847t1_pal_device : public mc6847_base_device
635{
636public:
637   mc6847t1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
638};
639
640
641extern const device_type MC6847_NTSC;
642extern const device_type MC6847_PAL;
643extern const device_type MC6847Y_NTSC;
644extern const device_type MC6847Y_PAL;
645extern const device_type MC6847T1_NTSC;
646extern const device_type MC6847T1_PAL;
647
648#endif /* __MC6847__ */
Property changes on: trunk/src/emu/video/mc6847.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/video/hd44352.h
r0r21685
1/***************************************************************************
2
3        Hitachi HD44352 LCD controller
4
5***************************************************************************/
6
7#pragma once
8
9#ifndef __hd44352_H__
10#define __hd44352_H__
11
12
13#define MCFG_HD44352_ADD( _tag, _clock, _config) \
14   MCFG_DEVICE_ADD( _tag, HD44352, _clock ) \
15   MCFG_DEVICE_CONFIG( _config )
16
17//**************************************************************************
18//  TYPE DEFINITIONS
19//**************************************************************************
20
21
22// ======================> hd44352_interface
23
24struct hd44352_interface
25{
26   devcb_write_line    m_on_cb;        // ON line
27};
28
29// ======================> hd44352_device
30
31class hd44352_device :
32                  public device_t,
33                  public hd44352_interface
34{
35public:
36   // construction/destruction
37   hd44352_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
38
39   // device interface
40   UINT8 data_read();
41   void data_write(UINT8 data);
42   void control_write(UINT8 data);
43
44   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
45
46protected:
47   // device-level overrides
48   virtual void device_start();
49   virtual void device_reset();
50   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
51   virtual void device_config_complete();
52   virtual void device_validity_check(validity_checker &valid) const;
53
54private:
55   UINT8 compute_newval(UINT8 type, UINT8 oldval, UINT8 newval);
56   UINT8 get_char(UINT16 pos);
57
58   static const device_timer_id ON_TIMER = 1;
59   emu_timer *m_on_timer;
60
61   UINT8 m_video_ram[2][0x180];
62   UINT8 m_control_lines;
63   UINT8 m_data_bus;
64   UINT8 m_par[3];
65   UINT8 m_state;
66   UINT16 m_bank;
67   UINT16 m_offset;
68   UINT8 m_char_width;
69   UINT8 m_lcd_on;
70   UINT8 m_scroll;
71   UINT32 m_contrast;
72
73   UINT8 m_custom_char[4][8];      // 4 chars * 8 bytes
74   UINT8 m_byte_count;
75   UINT8 m_cursor_status;
76   UINT8 m_cursor[8];
77   UINT8 m_cursor_x;
78   UINT8 m_cursor_y;
79   UINT8 m_cursor_lcd;
80
81   devcb_resolved_write_line m_on;         // ON line callback
82};
83
84// device type definition
85extern const device_type HD44352;
86
87#endif
Property changes on: trunk/src/emu/video/hd44352.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/video/upd7220.c
r0r21685
1/**********************************************************************
2
3    Intel 82720 Graphics Display Controller emulation
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10/*
11
12    TODO:
13
14    - implement FIFO as ring buffer
15    - commands
16        - DMAR
17        - DMAW
18    - incomplete / unimplemented FIGD / GCHRD draw modes
19        - Arc
20        - FIGD character
21        - slanted character
22        - GCHRD character (needs rewrite)
23    - read-modify-write cycle
24        - read data
25        - modify data
26        - write data
27    - QX-10 diagnostic test has positioning bugs with the bitmap display test;
28    - QX-10 diagnostic test misses the zooming factor (external pin);
29    - compis2 SAD address for bitmap is 0x20000 for whatever reason (presumably missing banking);
30    - A5105 has a FIFO bug with the RDAT, should be a lot larger when it scrolls up.
31      The problem is that DMA-ing with RDAT/WDAT shouldn't be instant;
32
33    - honor visible area
34    - wide mode (32-bit access)
35    - light pen
36
37*/
38
39#include "emu.h"
40#include "upd7220.h"
41
42
43
44//**************************************************************************
45//  MACROS / CONSTANTS
46//**************************************************************************
47
48#define VERBOSE         0
49#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
50
51
52// todo typedef
53enum
54{
55   COMMAND_INVALID = -1,
56   COMMAND_RESET,
57   COMMAND_SYNC,
58   COMMAND_VSYNC,
59   COMMAND_CCHAR,
60   COMMAND_START,
61   COMMAND_BCTRL,
62   COMMAND_ZOOM,
63   COMMAND_CURS,
64   COMMAND_PRAM,
65   COMMAND_PITCH,
66   COMMAND_WDAT,
67   COMMAND_MASK,
68   COMMAND_FIGS,
69   COMMAND_FIGD,
70   COMMAND_GCHRD,
71   COMMAND_RDAT,
72   COMMAND_CURD,
73   COMMAND_LPRD,
74   COMMAND_DMAR,
75   COMMAND_DMAW,
76   COMMAND_5A
77};
78
79enum
80{
81   FIFO_READ = 0,
82   FIFO_WRITE
83};
84
85enum
86{
87   FIFO_EMPTY = -1,
88   FIFO_PARAMETER,
89   FIFO_COMMAND
90};
91
92#define UPD7220_COMMAND_RESET           0x00
93#define UPD7220_COMMAND_SYNC            0x0e // & 0xfe
94#define UPD7220_COMMAND_VSYNC           0x6e // & 0xfe
95#define UPD7220_COMMAND_CCHAR           0x4b
96#define UPD7220_COMMAND_START           0x6b
97#define UPD7220_COMMAND_BCTRL           0x0c // & 0xfe
98#define UPD7220_COMMAND_ZOOM            0x46
99#define UPD7220_COMMAND_CURS            0x49
100#define UPD7220_COMMAND_PRAM            0x70 // & 0xf0
101#define UPD7220_COMMAND_PITCH           0x47
102#define UPD7220_COMMAND_WDAT            0x20 // & 0xe4
103#define UPD7220_COMMAND_MASK            0x4a
104#define UPD7220_COMMAND_FIGS            0x4c
105#define UPD7220_COMMAND_FIGD            0x6c
106#define UPD7220_COMMAND_GCHRD           0x68
107#define UPD7220_COMMAND_RDAT            0xa0 // & 0xe4
108#define UPD7220_COMMAND_CURD            0xe0
109#define UPD7220_COMMAND_LPRD            0xc0
110#define UPD7220_COMMAND_DMAR            0xa4 // & 0xe4
111#define UPD7220_COMMAND_DMAW            0x24 // & 0xe4
112#define UPD7220_COMMAND_5A              0x5a
113
114#define UPD7220_SR_DATA_READY           0x01
115#define UPD7220_SR_FIFO_FULL            0x02
116#define UPD7220_SR_FIFO_EMPTY           0x04
117#define UPD7220_SR_DRAWING_IN_PROGRESS  0x08
118#define UPD7220_SR_DMA_EXECUTE          0x10
119#define UPD7220_SR_VSYNC_ACTIVE         0x20
120#define UPD7220_SR_HBLANK_ACTIVE        0x40
121#define UPD7220_SR_LIGHT_PEN_DETECT     0x80
122
123#define UPD7220_MODE_S                  0x01
124#define UPD7220_MODE_REFRESH_RAM        0x04
125#define UPD7220_MODE_I                  0x08
126#define UPD7220_MODE_DRAW_ON_RETRACE    0x10
127#define UPD7220_MODE_DISPLAY_MASK       0x22
128#define UPD7220_MODE_DISPLAY_MIXED      0x00
129#define UPD7220_MODE_DISPLAY_GRAPHICS   0x02
130#define UPD7220_MODE_DISPLAY_CHARACTER  0x20
131#define UPD7220_MODE_DISPLAY_INVALID    0x22
132
133static const int x_dir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
134static const int y_dir[8] = { 1, 1, 0,-1,-1,-1, 0, 1};
135static const int x_dir_dot[8] = { 1, 1, 0,-1,-1,-1, 0, 1};
136static const int y_dir_dot[8] = { 0,-1,-1,-1, 0, 1, 1, 1};
137
138
139
140//**************************************************************************
141//  GLOBAL VARIABLES
142//**************************************************************************
143
144// devices
145const device_type UPD7220 = &device_creator<upd7220_device>;
146
147
148// default address map
149static ADDRESS_MAP_START( upd7220_vram, AS_0, 8, upd7220_device )
150   AM_RANGE(0x00000, 0x3ffff) AM_RAM
151ADDRESS_MAP_END
152
153
154// internal 128x14 control ROM
155ROM_START( upd7220 )
156   ROM_REGION( 0x100, "upd7220", 0 )
157   ROM_LOAD( "upd7220.bin", 0x000, 0x100, NO_DUMP )
158ROM_END
159
160
161//-------------------------------------------------
162//  memory_space_config - return a description of
163//  any address spaces owned by this device
164//-------------------------------------------------
165
166const address_space_config *upd7220_device::memory_space_config(address_spacenum spacenum) const
167{
168   return (spacenum == AS_0) ? &m_space_config : NULL;
169}
170
171
172//-------------------------------------------------
173//  rom_region - device-specific ROM region
174//-------------------------------------------------
175
176const rom_entry *upd7220_device::device_rom_region() const
177{
178   return ROM_NAME( upd7220 );
179}
180
181
182//-------------------------------------------------
183//  device_config_complete - perform any
184//  operations now that the configuration is
185//  complete
186//-------------------------------------------------
187
188void upd7220_device::device_config_complete()
189{
190   // inherit a copy of the static data
191   const upd7220_interface *intf = reinterpret_cast<const upd7220_interface *>(static_config());
192   if (intf != NULL)
193      *static_cast<upd7220_interface *>(this) = *intf;
194
195   // or initialize to defaults if none provided
196   else
197   {
198      memset(&m_out_drq_cb, 0, sizeof(m_out_drq_cb));
199      memset(&m_out_hsync_cb, 0, sizeof(m_out_hsync_cb));
200      memset(&m_out_vsync_cb, 0, sizeof(m_out_vsync_cb));
201      memset(&m_out_blank_cb, 0, sizeof(m_out_blank_cb));
202   }
203}
204
205
206
207//**************************************************************************
208//  INLINE HELPERS
209//**************************************************************************
210
211//-------------------------------------------------
212//  readbyte - read a byte at the given address
213//-------------------------------------------------
214
215inline UINT8 upd7220_device::readbyte(offs_t address)
216{
217   return space().read_byte(address);
218}
219
220
221//-------------------------------------------------
222//  writebyte - write a byte at the given address
223//-------------------------------------------------
224
225inline void upd7220_device::writebyte(offs_t address, UINT8 data)
226{
227   space().write_byte(address, data);
228}
229
230
231//-------------------------------------------------
232//  fifo_clear -
233//-------------------------------------------------
234
235inline void upd7220_device::fifo_clear()
236{
237   for (int i = 0; i < 16; i++)
238   {
239      m_fifo[i] = 0;
240      m_fifo_flag[i] = FIFO_EMPTY;
241   }
242
243   m_fifo_ptr = -1;
244
245   m_sr &= ~UPD7220_SR_DATA_READY;
246   m_sr |= UPD7220_SR_FIFO_EMPTY;
247   m_sr &= ~UPD7220_SR_FIFO_FULL;
248}
249
250
251//-------------------------------------------------
252//  fifo_param_count -
253//-------------------------------------------------
254
255inline int upd7220_device::fifo_param_count()
256{
257   int i;
258
259   for (i = 0; i < 16; i++)
260   {
261      if (m_fifo_flag[i] != FIFO_PARAMETER) break;
262   }
263
264   return i;
265}
266
267
268//-------------------------------------------------
269//  fifo_set_direction -
270//-------------------------------------------------
271
272inline void upd7220_device::fifo_set_direction(int dir)
273{
274   if (m_fifo_dir != dir)
275   {
276      fifo_clear();
277   }
278
279   m_fifo_dir = dir;
280}
281
282
283//-------------------------------------------------
284//  queue -
285//-------------------------------------------------
286
287inline void upd7220_device::queue(UINT8 data, int flag)
288{
289   if (m_fifo_ptr < 15)
290   {
291      m_fifo_ptr++;
292
293      m_fifo[m_fifo_ptr] = data;
294      m_fifo_flag[m_fifo_ptr] = flag;
295
296      if (m_fifo_ptr == 16)
297      {
298         m_sr |= UPD7220_SR_FIFO_FULL;
299      }
300
301      m_sr &= ~UPD7220_SR_FIFO_EMPTY;
302   }
303   else
304   {
305      // TODO what happen? somebody set us up the bomb
306      printf("FIFO?\n");
307   }
308}
309
310
311//-------------------------------------------------
312//  dequeue -
313//-------------------------------------------------
314
315inline void upd7220_device::dequeue(UINT8 *data, int *flag)
316{
317   *data = m_fifo[0];
318   *flag = m_fifo_flag[0];
319
320   if (m_fifo_ptr > -1)
321   {
322      for (int i = 0; i < 15; i++)
323      {
324         m_fifo[i] = m_fifo[i + 1];
325         m_fifo_flag[i] = m_fifo_flag[i + 1];
326      }
327
328      m_fifo[15] = 0;
329      m_fifo_flag[15] = 0;
330
331      m_fifo_ptr--;
332
333      if (m_fifo_ptr == -1)
334      {
335         m_sr &= ~UPD7220_SR_DATA_READY;
336         m_sr |= UPD7220_SR_FIFO_EMPTY;
337      }
338   }
339}
340
341
342//-------------------------------------------------
343//  update_vsync_timer -
344//-------------------------------------------------
345
346inline void upd7220_device::update_vsync_timer(int state)
347{
348   int next_y = state ? m_vs : 0;
349
350   attotime duration = m_screen->time_until_pos(next_y, 0);
351
352   m_vsync_timer->adjust(duration, !state);
353}
354
355
356//-------------------------------------------------
357//  update_hsync_timer -
358//-------------------------------------------------
359
360inline void upd7220_device::update_hsync_timer(int state)
361{
362   int y = m_screen->vpos();
363
364   int next_x = state ? m_hs : 0;
365   int next_y = state ? y : ((y + 1) % m_al);
366
367   attotime duration = m_screen->time_until_pos(next_y, next_x);
368
369   m_hsync_timer->adjust(duration, !state);
370}
371
372
373//-------------------------------------------------
374//  update_blank_timer -
375//-------------------------------------------------
376
377inline void upd7220_device::update_blank_timer(int state)
378{
379   int y = m_screen->vpos();
380
381   int next_x = state ? (m_hs + m_hbp) : (m_hs + m_hbp + (m_aw << 3));
382   int next_y = state ? ((y + 1) % (m_vs + m_vbp + m_al + m_vfp - 1)) : y;
383
384   attotime duration = m_screen->time_until_pos(next_y, next_x);
385
386   m_hsync_timer->adjust(duration, !state);
387}
388
389
390//-------------------------------------------------
391//  recompute_parameters -
392//-------------------------------------------------
393
394inline void upd7220_device::recompute_parameters()
395{
396   /* TODO: assume that the pitch also controls number of horizontal pixels in a single cell */
397   int horiz_mult = ((m_pitch == 40) ? 16 : 8);
398   int horiz_pix_total = (m_hs + m_hbp + m_aw + m_hfp) * horiz_mult;
399   int vert_pix_total = m_vs + m_vbp + m_al + m_vfp;
400
401   //printf("%d %d %d %d\n",m_hs,m_hbp,m_aw,m_hfp);
402   //printf("%d %d\n",m_aw * 8,m_pitch * 8);
403
404   if (horiz_pix_total == 0 || vert_pix_total == 0) //bail out if screen params aren't valid
405      return;
406
407   attoseconds_t refresh = HZ_TO_ATTOSECONDS(clock() * horiz_mult) * horiz_pix_total * vert_pix_total;
408
409   rectangle visarea;
410
411   visarea.min_x = 0; //(m_hs + m_hbp) * 8;
412   visarea.min_y = 0; //m_vs + m_vbp;
413   visarea.max_x = m_aw * horiz_mult - 1;//horiz_pix_total - (m_hfp * 8) - 1;
414   visarea.max_y = m_al - 1;//vert_pix_total - m_vfp - 1;
415
416   LOG(("uPD7220 '%s' Screen: %u x %u @ %f Hz\n", tag(), horiz_pix_total, vert_pix_total, 1 / ATTOSECONDS_TO_DOUBLE(refresh)));
417   LOG(("Visible Area: (%u, %u) - (%u, %u)\n", visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y));
418   LOG(("%d %d %d %d %d\n",m_hs,m_hbp,m_aw,m_hfp,m_pitch));
419   LOG(("%d %d %d %d\n",m_vs,m_vbp,m_al,m_vfp));
420
421   if (m_m)
422   {
423      m_screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh);
424
425      update_hsync_timer(0);
426      update_vsync_timer(0);
427   }
428   else
429   {
430      m_hsync_timer->enable(0);
431      m_vsync_timer->enable(0);
432   }
433
434   update_blank_timer(0);
435}
436
437
438//-------------------------------------------------
439//  reset_figs_param -
440//-------------------------------------------------
441
442inline void upd7220_device::reset_figs_param()
443{
444   m_figs.m_dc = 0x0000;
445   m_figs.m_d = 0x0008;
446   m_figs.m_d1 = 0x0008;
447   m_figs.m_d2 = 0x0000;
448   m_figs.m_dm = 0x0000;
449}
450
451
452//-------------------------------------------------
453//  advance_ead -
454//-------------------------------------------------
455
456inline void upd7220_device::advance_ead()
457{
458   #define EAD         m_ead
459   #define DAD         m_dad
460   #define P           x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch)
461   #define MSB(value)  (BIT(value, 15))
462   #define LSB(value)  (BIT(value, 0))
463   #define LR(value)   ((value << 1) | MSB(value))
464   #define RR(value)   ((LSB(value) << 15) | (value >> 1))
465
466   switch (m_draw_mode & 0x07)
467   {
468   case 0:
469      EAD += P;
470      break;
471
472   case 1:
473      EAD += P;
474      if (MSB(DAD)) EAD++;
475      DAD = LR(DAD);
476      break;
477
478   case 2:
479      if (MSB(DAD)) EAD++;
480      DAD = LR(DAD);
481      break;
482
483   case 3:
484      EAD -= P;
485      if (MSB(DAD)) EAD++;
486      DAD = LR(DAD);
487      break;
488
489   case 4:
490      EAD -= P;
491      break;
492
493   case 5:
494      EAD -= P;
495      if (LSB(DAD)) EAD--;
496      DAD = RR(DAD);
497      break;
498
499   case 6:
500      if (LSB(DAD)) EAD--;
501      DAD = RR(DAD);
502      break;
503
504   case 7:
505      EAD += P;
506      if (LSB(DAD)) EAD--;
507      DAD = RR(DAD);
508      break;
509   }
510
511   EAD &= 0x3ffff;
512}
513
514
515//-------------------------------------------------
516//  read_vram -
517//-------------------------------------------------
518
519inline void upd7220_device::read_vram(UINT8 type, UINT8 mod)
520{
521   if (type == 1)
522   {
523      LOG (("uPD7220 invalid type 1 RDAT parameter\n"));
524      return;
525   }
526
527   if (mod)
528      LOG (("uPD7220 RDAT used with mod = %02x?\n",mod));
529
530   for (int i = 0; i < m_figs.m_dc; i++)
531   {
532      switch(type)
533      {
534         case 0:
535            queue(readbyte(m_ead*2), 0);
536            queue(readbyte(m_ead*2+1), 0);
537            break;
538         case 2:
539            queue(readbyte(m_ead*2), 0);
540            break;
541         case 3:
542            queue(readbyte(m_ead*2+1), 0);
543            break;
544      }
545
546      advance_ead();
547   }
548}
549
550
551//-------------------------------------------------
552//  write_vram -
553//-------------------------------------------------
554
555inline void upd7220_device::write_vram(UINT8 type, UINT8 mod)
556{
557   UINT16 result;
558
559   if (type == 1)
560   {
561      printf("uPD7220 invalid type 1 WDAT parameter\n");
562      return;
563   }
564
565   result = 0;
566
567   switch(type)
568   {
569      case 0:
570         result = (m_pr[1] & 0xff);
571         result |= (m_pr[2] << 8);
572         result &= m_mask;
573         break;
574      case 2:
575         result = (m_pr[1] & 0xff);
576         result &= (m_mask & 0xff);
577         break;
578      case 3:
579         result = (m_pr[1] << 8);
580         result &= (m_mask & 0xff00);
581         break;
582   }
583
584   //if(result)
585   {
586      //printf("%04x %02x %02x %04x %02x %02x\n",readbyte(m_ead),m_pr[1],m_pr[2],m_mask,type,mod);
587      //printf("%04x %02x %02x\n",m_ead,m_figs.m_dir,m_pitch);
588      //printf("%04x %04x %02x %04x\n",m_ead,result,mod,m_figs.m_dc);
589   }
590
591   for(int i = 0; i < m_figs.m_dc + 1; i++)
592   {
593      switch(mod & 3)
594      {
595         case 0x00: //replace
596            if(type == 0 || type == 2)
597               writebyte(m_ead*2+0, result & 0xff);
598            if(type == 0 || type == 3)
599               writebyte(m_ead*2+1, result >> 8);
600            break;
601         case 0x01: //complement
602            if(type == 0 || type == 2)
603               writebyte(m_ead*2+0, readbyte(m_ead*2+0) ^ (result & 0xff));
604            if(type == 0 || type == 3)
605               writebyte(m_ead*2+1, readbyte(m_ead*2+1) ^ (result >> 8));
606            break;
607         case 0x02: //reset to zero
608            if(type == 0 || type == 2)
609               writebyte(m_ead*2+0, readbyte(m_ead*2+0) & ~(result & 0xff));
610            if(type == 0 || type == 3)
611               writebyte(m_ead*2+1, readbyte(m_ead*2+1) & ~(result >> 8));
612            break;
613         case 0x03: //set to one
614            if(type == 0 || type == 2)
615               writebyte(m_ead*2+0, readbyte(m_ead*2+0) | (result & 0xff));
616            if(type == 0 || type == 3)
617               writebyte(m_ead*2+1, readbyte(m_ead*2+1) | (result >> 8));
618            break;
619      }
620
621      advance_ead();
622   }
623}
624
625
626//-------------------------------------------------
627//  check_pattern -
628//-------------------------------------------------
629
630inline UINT16 upd7220_device::check_pattern(UINT16 pattern)
631{
632   UINT16 res = 0;
633
634   switch (m_bitmap_mod & 3)
635   {
636      case 0: res = pattern; break; //replace
637      case 1: res = pattern; break; //complement
638      case 2: res = 0; break; //reset to zero
639      case 3: res |= 0xffff; break; //set to one
640   }
641
642   return res;
643}
644
645
646//-------------------------------------------------
647//  get_text_partition -
648//-------------------------------------------------
649
650inline void upd7220_device::get_text_partition(int index, UINT32 *sad, UINT16 *len, int *im, int *wd)
651{
652   *sad = ((m_ra[(index * 4) + 1] & 0x1f) << 8) | m_ra[(index * 4) + 0];
653   *len = ((m_ra[(index * 4) + 3] & 0x3f) << 4) | (m_ra[(index * 4) + 2] >> 4);
654   *im = BIT(m_ra[(index * 4) + 3], 6);
655   *wd = BIT(m_ra[(index * 4) + 3], 7);
656}
657
658
659//-------------------------------------------------
660//  get_graphics_partition -
661//-------------------------------------------------
662
663inline void upd7220_device::get_graphics_partition(int index, UINT32 *sad, UINT16 *len, int *im, int *wd)
664{
665   *sad = ((m_ra[(index * 4) + 2] & 0x03) << 16) | (m_ra[(index * 4) + 1] << 8) | m_ra[(index * 4) + 0];
666   *len = ((m_ra[(index * 4) + 3] & 0x3f) << 4) | (m_ra[(index * 4) + 2] >> 4);
667   *im = BIT(m_ra[(index * 4) + 3], 6);
668   *wd = BIT(m_ra[(index * 4) + 3], 7);
669}
670
671
672
673//**************************************************************************
674//  LIVE DEVICE
675//**************************************************************************
676
677//-------------------------------------------------
678//  upd7220_device - constructor
679//-------------------------------------------------
680
681upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
682   : device_t(mconfig, UPD7220, "uPD7220", tag, owner, clock),
683      device_memory_interface(mconfig, *this),
684      m_mask(0),
685      m_pitch(0),
686      m_ead(0),
687      m_dad(0),
688      m_lad(0),
689      m_ra_addr(0),
690      m_sr(UPD7220_SR_FIFO_EMPTY),
691      m_cr(0),
692      m_param_ptr(0),
693      m_fifo_ptr(-1),
694      m_fifo_dir(0),
695      m_mode(0),
696      m_draw_mode(0),
697      m_de(0),
698      m_m(0),
699      m_aw(0),
700      m_al(0),
701      m_vs(0),
702      m_vfp(0),
703      m_vbp(0),
704      m_hs(0),
705      m_hfp(0),
706      m_hbp(0),
707      m_dc(0),
708      m_sc(0),
709      m_br(0),
710      m_ctop(0),
711      m_cbot(0),
712      m_lr(0),
713      m_disp(0),
714      m_gchr(0),
715      m_bitmap_mod(0),
716      m_space_config("videoram", ENDIANNESS_LITTLE, 8, 18, 0, NULL, *ADDRESS_MAP_NAME(upd7220_vram))
717{
718   m_shortname = "upd7220";
719   for (int i = 0; i < 16; i++)
720   {
721      m_fifo[i] = 0;
722      m_fifo_flag[i] = FIFO_EMPTY;
723
724      m_ra[i] = 0;
725   }
726
727   for (int i = 0; i < 17; i++)
728   {
729      m_pr[i] = 0;
730   }
731
732   m_figs.m_dir = 0;
733   m_figs.m_figure_type = 0;
734   m_figs.m_dc = 0;
735   m_figs.m_d = 0;
736   m_figs.m_d1 = 0;
737   m_figs.m_d2 = 0;
738   m_figs.m_dm = 0;
739}
740
741
742//-------------------------------------------------
743//  device_start - device-specific startup
744//-------------------------------------------------
745
746void upd7220_device::device_start()
747{
748   // allocate timers
749   m_vsync_timer = timer_alloc(TIMER_VSYNC);
750   m_hsync_timer = timer_alloc(TIMER_HSYNC);
751   m_blank_timer = timer_alloc(TIMER_BLANK);
752
753   // resolve callbacks
754   m_out_drq_func.resolve(m_out_drq_cb, *this);
755   m_out_hsync_func.resolve(m_out_hsync_cb, *this);
756   m_out_vsync_func.resolve(m_out_vsync_cb, *this);
757   m_out_blank_func.resolve(m_out_blank_cb, *this);
758
759   // find screen
760   m_screen = machine().device<screen_device>(m_screen_tag);
761
762   if (m_screen == NULL)
763   {
764      m_screen = owner()->subdevice<screen_device>(m_screen_tag);
765   }
766
767   assert(m_screen);
768
769   // register for state saving
770   save_item(NAME(m_ra));
771   save_item(NAME(m_sr));
772   save_item(NAME(m_mode));
773   save_item(NAME(m_de));
774   save_item(NAME(m_aw));
775   save_item(NAME(m_al));
776   save_item(NAME(m_vs));
777   save_item(NAME(m_vfp));
778   save_item(NAME(m_vbp));
779   save_item(NAME(m_hs));
780   save_item(NAME(m_hfp));
781   save_item(NAME(m_hbp));
782   save_item(NAME(m_m));
783   save_item(NAME(m_dc));
784   save_item(NAME(m_sc));
785   save_item(NAME(m_br));
786   save_item(NAME(m_lr));
787   save_item(NAME(m_ctop));
788   save_item(NAME(m_cbot));
789   save_item(NAME(m_ead));
790   save_item(NAME(m_dad));
791   save_item(NAME(m_lad));
792   save_item(NAME(m_disp));
793   save_item(NAME(m_gchr));
794   save_item(NAME(m_mask));
795   save_item(NAME(m_pitch));
796}
797
798
799//-------------------------------------------------
800//  device_reset - device-specific reset
801//-------------------------------------------------
802
803void upd7220_device::device_reset()
804{
805   m_out_drq_func(CLEAR_LINE);
806}
807
808
809//-------------------------------------------------
810//  device_timer - handler timer events
811//-------------------------------------------------
812
813void upd7220_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
814{
815   switch (id)
816   {
817   case TIMER_HSYNC:
818      if (param)
819      {
820         m_sr |= UPD7220_SR_HBLANK_ACTIVE;
821      }
822      else
823      {
824         m_sr &= ~UPD7220_SR_HBLANK_ACTIVE;
825      }
826
827      m_out_hsync_func(param);
828
829      update_hsync_timer(param);
830      break;
831
832   case TIMER_VSYNC:
833      if (param)
834      {
835         m_sr |= UPD7220_SR_VSYNC_ACTIVE;
836      }
837      else
838      {
839         m_sr &= ~UPD7220_SR_VSYNC_ACTIVE;
840      }
841
842      m_out_vsync_func(param);
843
844      update_vsync_timer(param);
845      break;
846
847   case TIMER_BLANK:
848      if (param)
849      {
850         m_sr |= UPD7220_SR_HBLANK_ACTIVE;
851      }
852      else
853      {
854         m_sr &= ~UPD7220_SR_HBLANK_ACTIVE;
855      }
856
857      m_out_blank_func(param);
858
859      update_blank_timer(param);
860      break;
861   }
862}
863
864
865//-------------------------------------------------
866//  draw_pixel -
867//-------------------------------------------------
868
869void upd7220_device::draw_pixel(int x, int y, UINT8 tile_data)
870{
871   UINT32 addr = (y * m_pitch * 2 + (x >> 3)) & 0x3ffff;
872   int dad = x & 0x7;
873   UINT8 data = readbyte(addr);
874   UINT8 new_pixel = (tile_data) & (0x80 >> (dad));
875
876   switch(m_bitmap_mod)
877   {
878      case 0: //replace
879         writebyte(addr, data & ~(0x80 >> (dad)));
880         writebyte(addr, data | new_pixel);
881         break;
882      case 1: //complement
883         writebyte(addr, data ^ (new_pixel));
884         break;
885      case 2: //reset
886         writebyte(addr, data & ((new_pixel) ? 0xff : ~(0x80 >> (dad))));
887         break;
888      case 3: //set
889         writebyte(addr, data | new_pixel);
890         break;
891   }
892}
893
894
895//-------------------------------------------------
896//  draw_line -
897//-------------------------------------------------
898
899void upd7220_device::draw_line(int x, int y)
900{
901   int line_size,i;
902   const int line_x_dir[8] = { 0, 1, 1, 0, 0,-1,-1, 0};
903   const int line_y_dir[8] = { 1, 0, 0,-1,-1, 0, 0, 1};
904   const int line_x_step[8] = { 1, 0, 0, 1,-1, 0, 0,-1 };
905   const int line_y_step[8] = { 0, 1,-1, 0, 0,-1, 1, 0 };
906   UINT16 line_pattern;
907   int line_step = 0;
908   UINT8 dot;
909
910   line_size = m_figs.m_dc + 1;
911   line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8));
912
913   for(i = 0;i<line_size;i++)
914   {
915      line_step = (m_figs.m_d1 * i);
916      line_step/= (m_figs.m_dc + 1);
917      line_step >>= 1;
918      dot = ((line_pattern >> (i & 0xf)) & 1) << 7;
919      draw_pixel(x + (line_step*line_x_step[m_figs.m_dir]),y + (line_step*line_y_step[m_figs.m_dir]),dot >> ((x + line_step*line_x_step[m_figs.m_dir]) & 0x7));
920      x += line_x_dir[m_figs.m_dir];
921      y += line_y_dir[m_figs.m_dir];
922   }
923
924   /* TODO: check me*/
925   x += (line_step*line_x_step[m_figs.m_dir]);
926   y += (line_step*line_y_step[m_figs.m_dir]);
927
928   m_ead = (x >> 4) + (y * m_pitch);
929   m_dad = x & 0x0f;
930}
931
932
933//-------------------------------------------------
934//  draw_rectangle -
935//-------------------------------------------------
936
937void upd7220_device::draw_rectangle(int x, int y)
938{
939   int i;
940   const int rect_x_dir[8] = { 0, 1, 0,-1, 1, 1,-1,-1 };
941   const int rect_y_dir[8] = { 1, 0,-1, 0, 1,-1,-1, 1 };
942   UINT8 rect_type,rect_dir;
943   UINT16 line_pattern;
944   UINT8 dot;
945
946   LOG(("uPD7220 rectangle check: %d %d %02x %08x\n",x,y,m_figs.m_dir,m_ead));
947
948   line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8));
949   rect_type = (m_figs.m_dir & 1) << 2;
950   rect_dir = rect_type | (((m_figs.m_dir >> 1) + 0) & 3);
951
952   for(i = 0;i < m_figs.m_d;i++)
953   {
954      dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
955      draw_pixel(x,y,dot >> (x & 0x7));
956      x+=rect_x_dir[rect_dir];
957      y+=rect_y_dir[rect_dir];
958   }
959
960   rect_dir = rect_type | (((m_figs.m_dir >> 1) + 1) & 3);
961
962   for(i = 0;i < m_figs.m_d2;i++)
963   {
964      dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
965      draw_pixel(x,y,dot >> (x & 0x7));
966      x+=rect_x_dir[rect_dir];
967      y+=rect_y_dir[rect_dir];
968   }
969
970   rect_dir = rect_type | (((m_figs.m_dir >> 1) + 2) & 3);
971
972   for(i = 0;i < m_figs.m_d;i++)
973   {
974      dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
975      draw_pixel(x,y,dot >> (x & 0x7));
976      x+=rect_x_dir[rect_dir];
977      y+=rect_y_dir[rect_dir];
978   }
979
980   rect_dir = rect_type | (((m_figs.m_dir >> 1) + 3) & 3);
981
982   for(i = 0;i < m_figs.m_d2;i++)
983   {
984      dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
985      draw_pixel(x,y,dot >> (x & 0x7));
986      x+=rect_x_dir[rect_dir];
987      y+=rect_y_dir[rect_dir];
988   }
989
990   m_ead = (x >> 4) + (y * m_pitch);
991   m_dad = x & 0x0f;
992
993}
994
995
996//-------------------------------------------------
997//  draw_char -
998//-------------------------------------------------
999
1000void upd7220_device::draw_char(int x, int y)
1001{
1002   int xi,yi;
1003   int xsize,ysize;
1004   UINT8 tile_data;
1005
1006   /* snippet for character checking */
1007   #if 0
1008   for(yi=0;yi<8;yi++)
1009   {
1010      for(xi=0;xi<8;xi++)
1011      {
1012         printf("%d",(m_ra[(yi & 7) | 8] >> xi) & 1);
1013      }
1014      printf("\n");
1015   }
1016   #endif
1017
1018   xsize = m_figs.m_d & 0x3ff;
1019   /* Guess: D has presumably upper bits for ysize, QX-10 relies on this (TODO: check this on any real HW) */
1020   ysize = ((m_figs.m_d & 0x400) + m_figs.m_dc) + 1;
1021
1022   /* TODO: internal direction, zooming, size stuff bigger than 8, rewrite using draw_pixel function */
1023   for(yi=0;yi<ysize;yi++)
1024   {
1025      switch(m_figs.m_dir & 7)
1026      {
1027         case 0: tile_data = BITSWAP8(m_ra[((yi) & 7) | 8],0,1,2,3,4,5,6,7); break; // TODO
1028         case 2: tile_data = BITSWAP8(m_ra[((yi) & 7) | 8],0,1,2,3,4,5,6,7); break;
1029         case 6: tile_data = BITSWAP8(m_ra[((ysize-1-yi) & 7) | 8],7,6,5,4,3,2,1,0); break;
1030         default: tile_data = BITSWAP8(m_ra[((yi) & 7) | 8],7,6,5,4,3,2,1,0);
1031                  printf("%d %d %d\n",m_figs.m_dir,xsize,ysize);
1032                  break;
1033      }
1034
1035      for(xi=0;xi<xsize;xi++)
1036      {
1037         UINT32 addr = ((y+yi) * m_pitch * 2) + ((x+xi) >> 3);
1038
1039         writebyte(addr & 0x3ffff, readbyte(addr & 0x3ffff) & ~(1 << (xi & 7)));
1040         writebyte(addr & 0x3ffff, readbyte(addr & 0x3ffff) | ((tile_data) & (1 << (xi & 7))));
1041      }
1042   }
1043
1044   m_ead = ((x+8*x_dir_dot[m_figs.m_dir]) >> 4) + ((y+8*y_dir_dot[m_figs.m_dir]) * m_pitch);
1045   m_dad = ((x+8*x_dir_dot[m_figs.m_dir]) & 0xf);
1046}
1047
1048
1049//-------------------------------------------------
1050//  translate_command -
1051//-------------------------------------------------
1052
1053int upd7220_device::translate_command(UINT8 data)
1054{
1055   int command = COMMAND_INVALID;
1056
1057   switch (data)
1058   {
1059   case UPD7220_COMMAND_RESET: command = COMMAND_RESET; break;
1060   case UPD7220_COMMAND_CCHAR: command = COMMAND_CCHAR; break;
1061   case UPD7220_COMMAND_START: command = COMMAND_START; break;
1062   case UPD7220_COMMAND_ZOOM:  command = COMMAND_ZOOM;  break;
1063   case UPD7220_COMMAND_CURS:  command = COMMAND_CURS;  break;
1064   case UPD7220_COMMAND_PITCH: command = COMMAND_PITCH; break;
1065   case UPD7220_COMMAND_MASK:  command = COMMAND_MASK;  break;
1066   case UPD7220_COMMAND_FIGS:  command = COMMAND_FIGS;  break;
1067   case UPD7220_COMMAND_FIGD:  command = COMMAND_FIGD;  break;
1068   case UPD7220_COMMAND_GCHRD: command = COMMAND_GCHRD; break;
1069   case UPD7220_COMMAND_CURD:  command = COMMAND_CURD;  break;
1070   case UPD7220_COMMAND_LPRD:  command = COMMAND_LPRD;  break;
1071   case UPD7220_COMMAND_5A:    command = COMMAND_5A;    break;
1072   default:
1073      switch (data & 0xfe)
1074      {
1075      case UPD7220_COMMAND_SYNC:  command = COMMAND_SYNC;  break;
1076      case UPD7220_COMMAND_VSYNC: command = COMMAND_VSYNC; break;
1077      case UPD7220_COMMAND_BCTRL: command = COMMAND_BCTRL; break;
1078      default:
1079         switch (data & 0xf0)
1080         {
1081         case UPD7220_COMMAND_PRAM: command = COMMAND_PRAM; break;
1082         default:
1083            switch (data & 0xe4)
1084            {
1085            case UPD7220_COMMAND_WDAT: command = COMMAND_WDAT; break;
1086            case UPD7220_COMMAND_RDAT: command = COMMAND_RDAT; break;
1087            case UPD7220_COMMAND_DMAR: command = COMMAND_DMAR; break;
1088            case UPD7220_COMMAND_DMAW: command = COMMAND_DMAW; break;
1089            }
1090         }
1091      }
1092   }
1093
1094   return command;
1095}
1096
1097
1098//-------------------------------------------------
1099//  process_fifo -
1100//-------------------------------------------------
1101
1102void upd7220_device::process_fifo()
1103{
1104   UINT8 data;
1105   int flag;
1106
1107   dequeue(&data, &flag);
1108
1109   if (flag == FIFO_COMMAND)
1110   {
1111      m_cr = data;
1112      m_param_ptr = 1;
1113   }
1114   else
1115   {
1116      m_pr[m_param_ptr] = data;
1117      m_param_ptr++;
1118   }
1119
1120   switch (translate_command(m_cr))
1121   {
1122   case COMMAND_INVALID:
1123      printf("uPD7220 '%s' Invalid Command Byte %02x\n", tag(), m_cr);
1124      break;
1125
1126   case COMMAND_5A:
1127      if (m_param_ptr == 4)
1128         printf("uPD7220 '%s' Undocumented Command 0x5A Executed %02x %02x %02x\n", tag(),m_pr[1],m_pr[2],m_pr[3] );
1129      break;
1130
1131   case COMMAND_RESET: /* reset */
1132      switch (m_param_ptr)
1133      {
1134      case 0:
1135         LOG(("uPD7220 '%s' RESET\n", tag()));
1136
1137         m_de = 0;
1138         m_ra[0] = m_ra[1] = m_ra[2] = 0;
1139         m_ra[3] = 0x19;
1140         m_ead = 0;
1141         m_dad = 0;
1142         m_mask = 0;
1143         break;
1144
1145      case 9:
1146         m_mode = m_pr[1];
1147         m_aw = m_pr[2] + 2;
1148         m_hs = (m_pr[3] & 0x1f) + 1;
1149         m_vs = ((m_pr[4] & 0x03) << 3) | (m_pr[3] >> 5);
1150         m_hfp = (m_pr[4] >> 2) + 1;
1151         m_hbp = (m_pr[5] & 0x3f) + 1;
1152         m_vfp = m_pr[6] & 0x3f;
1153         m_al = ((m_pr[8] & 0x03) << 8) | m_pr[7];
1154         m_vbp = m_pr[8] >> 2;
1155
1156         m_pitch = m_aw;
1157
1158         LOG(("uPD7220 '%s' Mode: %02x\n", tag(), m_mode));
1159         LOG(("uPD7220 '%s' AW: %u\n", tag(), m_aw));
1160         LOG(("uPD7220 '%s' HS: %u\n", tag(), m_hs));
1161         LOG(("uPD7220 '%s' VS: %u\n", tag(), m_vs));
1162         LOG(("uPD7220 '%s' HFP: %u\n", tag(), m_hfp));
1163         LOG(("uPD7220 '%s' HBP: %u\n", tag(), m_hbp));
1164         LOG(("uPD7220 '%s' VFP: %u\n", tag(), m_vfp));
1165         LOG(("uPD7220 '%s' AL: %u\n", tag(), m_al));
1166         LOG(("uPD7220 '%s' VBP: %u\n", tag(), m_vbp));
1167         LOG(("uPD7220 '%s' PITCH: %u\n", tag(), m_pitch));
1168
1169         recompute_parameters();
1170         break;
1171      }
1172      break;
1173
1174   case COMMAND_SYNC: /* sync format specify */
1175      if (m_param_ptr == 9)
1176      {
1177         m_mode = m_pr[1];
1178         m_aw = m_pr[2] + 2;
1179         m_hs = (m_pr[3] & 0x1f) + 1;
1180         m_vs = ((m_pr[4] & 0x03) << 3) | (m_pr[3] >> 5);
1181         m_hfp = (m_pr[4] >> 2) + 1;
1182         m_hbp = (m_pr[5] & 0x3f) + 1;
1183         m_vfp = m_pr[6] & 0x3f;
1184         m_al = ((m_pr[8] & 0x03) << 8) | m_pr[7];
1185         m_vbp = m_pr[8] >> 2;
1186
1187         m_pitch = m_aw;
1188
1189         LOG(("uPD7220 '%s' Mode: %02x\n", tag(), m_mode));
1190         LOG(("uPD7220 '%s' AW: %u\n", tag(), m_aw));
1191         LOG(("uPD7220 '%s' HS: %u\n", tag(), m_hs));
1192         LOG(("uPD7220 '%s' VS: %u\n", tag(), m_vs));
1193         LOG(("uPD7220 '%s' HFP: %u\n", tag(), m_hfp));
1194         LOG(("uPD7220 '%s' HBP: %u\n", tag(), m_hbp));
1195         LOG(("uPD7220 '%s' VFP: %u\n", tag(), m_vfp));
1196         LOG(("uPD7220 '%s' AL: %u\n", tag(), m_al));
1197         LOG(("uPD7220 '%s' VBP: %u\n", tag(), m_vbp));
1198         LOG(("uPD7220 '%s' PITCH: %u\n", tag(), m_pitch));
1199
1200         recompute_parameters();
1201      }
1202      break;
1203
1204   case COMMAND_VSYNC: /* vertical sync mode */
1205      m_m = m_cr & 0x01;
1206
1207      LOG(("uPD7220 '%s' M: %u\n", tag(), m_m));
1208
1209      recompute_parameters();
1210      break;
1211
1212   case COMMAND_CCHAR: /* cursor & character characteristics */
1213      if(m_param_ptr == 2)
1214      {
1215         m_lr = (m_pr[1] & 0x1f) + 1;
1216         m_dc = BIT(m_pr[1], 7);
1217
1218         LOG(("uPD7220 '%s' LR: %u\n", tag(), m_lr));
1219         LOG(("uPD7220 '%s' DC: %u\n", tag(), m_dc));
1220      }
1221
1222      if(m_param_ptr == 3)
1223      {
1224         m_ctop = m_pr[2] & 0x1f;
1225         m_sc = BIT(m_pr[2], 5);
1226         m_br = (m_pr[2] >> 6); /* guess, assume that blink rate clears upper bits (if any) */
1227
1228         LOG(("uPD7220 '%s' CTOP: %u\n", tag(), m_ctop));
1229         LOG(("uPD7220 '%s' SC: %u\n", tag(), m_sc));
1230      }
1231
1232      if(m_param_ptr == 4)
1233      {
1234         m_br = ((m_pr[3] & 0x07) << 2) | (m_pr[2] >> 6);
1235         m_cbot = m_pr[3] >> 3;
1236
1237         LOG(("uPD7220 '%s' BR: %u\n", tag(), m_br));
1238         LOG(("uPD7220 '%s' CBOT: %u\n", tag(), m_cbot));
1239      }
1240      break;
1241
1242   case COMMAND_START: /* start display & end idle mode */
1243      m_de = 1;
1244
1245      //LOG(("uPD7220 '%s' DE: 1\n", tag()));
1246      break;
1247
1248   case COMMAND_BCTRL: /* display blanking control */
1249      m_de = m_cr & 0x01;
1250
1251      //LOG(("uPD7220 '%s' DE: %u\n", tag(), m_de));
1252      break;
1253
1254   case COMMAND_ZOOM: /* zoom factors specify */
1255      if (flag == FIFO_PARAMETER)
1256      {
1257         m_gchr = m_pr[1] & 0x0f;
1258         m_disp = m_pr[1] >> 4;
1259
1260         LOG(("uPD7220 '%s' GCHR: %01x\n", tag(), m_gchr));
1261         LOG(("uPD7220 '%s' DISP: %01x\n", tag(), m_disp));
1262      }
1263      break;
1264
1265   case COMMAND_CURS: /* cursor position specify */
1266      if (m_param_ptr >= 3)
1267      {
1268         UINT8 upper_addr = (m_param_ptr == 3) ? 0 : (m_pr[3] & 0x03);
1269
1270         m_ead = (upper_addr << 16) | (m_pr[2] << 8) | m_pr[1];
1271
1272         //LOG(("uPD7220 '%s' EAD: %06x\n", tag(), m_ead));
1273
1274         if(m_param_ptr == 4)
1275         {
1276            m_dad = m_pr[3] >> 4;
1277            //LOG(("uPD7220 '%s' DAD: %01x\n", tag(), m_dad));
1278         }
1279      }
1280      break;
1281
1282   case COMMAND_PRAM: /* parameter RAM load */
1283      if (flag == FIFO_COMMAND)
1284      {
1285         m_ra_addr = m_cr & 0x0f;
1286      }
1287      else
1288      {
1289         if (m_ra_addr < 16)
1290         {
1291            LOG(("uPD7220 '%s' RA%u: %02x\n", tag(), m_ra_addr, data));
1292
1293            m_ra[m_ra_addr] = data;
1294            m_ra_addr++;
1295         }
1296
1297         m_param_ptr = 0;
1298      }
1299      break;
1300
1301   case COMMAND_PITCH: /* pitch specification */
1302      if (flag == FIFO_PARAMETER)
1303      {
1304         m_pitch = data;
1305
1306         LOG(("uPD7220 '%s' PITCH: %u\n", tag(), m_pitch));
1307      }
1308      break;
1309
1310   case COMMAND_WDAT: /* write data into display memory */
1311      m_bitmap_mod = m_cr & 3;
1312
1313      if (m_param_ptr == 3 || (m_param_ptr == 2 && m_cr & 0x10))
1314      {
1315         //printf("%02x = %02x %02x (%c) %04x\n",m_cr,m_pr[2],m_pr[1],m_pr[1],EAD);
1316         fifo_set_direction(FIFO_WRITE);
1317
1318         write_vram((m_cr & 0x18) >> 3,m_cr & 3);
1319         reset_figs_param();
1320         m_param_ptr = 1;
1321      }
1322      break;
1323
1324   case COMMAND_MASK: /* mask register load */
1325      if (m_param_ptr == 3)
1326      {
1327         m_mask = (m_pr[2] << 8) | m_pr[1];
1328
1329         LOG(("uPD7220 '%s' MASK: %04x\n", tag(), m_mask));
1330      }
1331      break;
1332
1333   case COMMAND_FIGS: /* figure drawing parameters specify */
1334      if (m_param_ptr == 2)
1335      {
1336         m_figs.m_dir = m_pr[1] & 0x7;
1337         m_figs.m_figure_type = (m_pr[1] & 0xf8) >> 3;
1338
1339         //if(m_figs.m_dir != 2)
1340         //  printf("DIR %02x\n",m_pr[1]);
1341      }
1342
1343      // the Decision Mate V during start-up test upload only 2 params before execute the
1344      // RDAT command, so I assume this is the expected behaviour, but this needs to be verified.
1345      if (m_param_ptr == 3)
1346         m_figs.m_dc = (m_pr[2]) | (m_figs.m_dc & 0x3f00);
1347
1348      if (m_param_ptr == 4)
1349         m_figs.m_dc = (m_pr[2]) | ((m_pr[3] & 0x3f) << 8);
1350
1351      if (m_param_ptr == 6)
1352         m_figs.m_d = (m_pr[4]) | ((m_pr[5] & 0x3f) << 8);
1353
1354      if (m_param_ptr == 8)
1355         m_figs.m_d2 = (m_pr[6]) | ((m_pr[7] & 0x3f) << 8);
1356
1357      if (m_param_ptr == 10)
1358         m_figs.m_d1 = (m_pr[8]) | ((m_pr[9] & 0x3f) << 8);
1359
1360      if (m_param_ptr == 12)
1361         m_figs.m_dm = (m_pr[10]) | ((m_pr[11] & 0x3f) << 8);
1362
1363      break;
1364
1365   case COMMAND_FIGD: /* figure draw start */
1366      if(m_figs.m_figure_type == 0)
1367      {
1368         UINT16 line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8));
1369         UINT8 dot = ((line_pattern >> (0 & 0xf)) & 1) << 7;
1370
1371         draw_pixel(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch),dot);
1372      }
1373      else if(m_figs.m_figure_type == 1)
1374         draw_line(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch));
1375      else if(m_figs.m_figure_type == 8)
1376         draw_rectangle(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch));
1377      else
1378         printf("uPD7220 '%s' Unimplemented command FIGD %02x\n", tag(),m_figs.m_figure_type);
1379
1380      reset_figs_param();
1381      m_sr |= UPD7220_SR_DRAWING_IN_PROGRESS;
1382      break;
1383
1384   case COMMAND_GCHRD: /* graphics character draw and area filling start */
1385      if(m_figs.m_figure_type == 2)
1386         draw_char(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch));
1387      else
1388         printf("uPD7220 '%s' Unimplemented command GCHRD %02x\n", tag(),m_figs.m_figure_type);
1389
1390      reset_figs_param();
1391      m_sr |= UPD7220_SR_DRAWING_IN_PROGRESS;
1392      break;
1393
1394   case COMMAND_RDAT: /* read data from display memory */
1395      fifo_set_direction(FIFO_READ);
1396
1397      read_vram((m_cr & 0x18) >> 3,m_cr & 3);
1398      reset_figs_param();
1399
1400      m_sr |= UPD7220_SR_DATA_READY;
1401      break;
1402
1403   case COMMAND_CURD: /* cursor address read */
1404      fifo_set_direction(FIFO_READ);
1405
1406      queue(m_ead & 0xff, 0);
1407      queue((m_ead >> 8) & 0xff, 0);
1408      queue(m_ead >> 16, 0);
1409      queue(m_dad & 0xff, 0);
1410      queue(m_dad >> 8, 0);
1411
1412      m_sr |= UPD7220_SR_DATA_READY;
1413      break;
1414
1415   case COMMAND_LPRD: /* light pen address read */
1416      fifo_set_direction(FIFO_READ);
1417
1418      queue(m_lad & 0xff, 0);
1419      queue((m_lad >> 8) & 0xff, 0);
1420      queue(m_lad >> 16, 0);
1421
1422      m_sr |= UPD7220_SR_DATA_READY;
1423      m_sr &= ~UPD7220_SR_LIGHT_PEN_DETECT;
1424      break;
1425
1426   case COMMAND_DMAR: /* DMA read request */
1427      printf("uPD7220 '%s' Unimplemented command DMAR\n", tag());
1428      break;
1429
1430   case COMMAND_DMAW: /* DMA write request */
1431      printf("uPD7220 '%s' Unimplemented command DMAW\n", tag());
1432      break;
1433   }
1434}
1435
1436
1437//-------------------------------------------------
1438//  read -
1439//-------------------------------------------------
1440
1441READ8_MEMBER( upd7220_device::read )
1442{
1443   UINT8 data;
1444
1445   if (offset & 1)
1446   {
1447      /* FIFO read */
1448      int flag;
1449      fifo_set_direction(FIFO_READ);
1450      dequeue(&data, &flag);
1451   }
1452   else
1453   {
1454      /* status register */
1455      data = m_sr;
1456
1457      /* TODO: timing of these */
1458      m_sr &= ~UPD7220_SR_DRAWING_IN_PROGRESS;
1459      m_sr &= ~UPD7220_SR_DMA_EXECUTE;
1460   }
1461
1462   return data;
1463}
1464
1465
1466//-------------------------------------------------
1467//  write -
1468//-------------------------------------------------
1469
1470WRITE8_MEMBER( upd7220_device::write )
1471{
1472   if (offset & 1)
1473   {
1474      /* command into FIFO */
1475      fifo_set_direction(FIFO_WRITE);
1476      queue(data, 1);
1477   }
1478   else
1479   {
1480      /* parameter into FIFO */
1481//      fifo_set_direction(FIFO_WRITE);
1482      queue(data, 0);
1483   }
1484
1485   process_fifo();
1486}
1487
1488
1489//-------------------------------------------------
1490//  dack_r -
1491//-------------------------------------------------
1492
1493READ8_MEMBER( upd7220_device::dack_r )
1494{
1495   return 0;
1496}
1497
1498
1499//-------------------------------------------------
1500//  dack_w -
1501//-------------------------------------------------
1502
1503WRITE8_MEMBER( upd7220_device::dack_w )
1504{
1505}
1506
1507
1508//-------------------------------------------------
1509//  ext_sync_w -
1510//-------------------------------------------------
1511
1512WRITE_LINE_MEMBER( upd7220_device::ext_sync_w )
1513{
1514   //LOG(("uPD7220 '%s' External Synchronization: %u\n", tag(), state));
1515
1516   if (state)
1517   {
1518      m_sr |= UPD7220_SR_VSYNC_ACTIVE;
1519   }
1520   else
1521   {
1522      m_sr &= ~UPD7220_SR_VSYNC_ACTIVE;
1523   }
1524}
1525
1526
1527//-------------------------------------------------
1528//  ext_sync_w -
1529//-------------------------------------------------
1530
1531WRITE_LINE_MEMBER( upd7220_device::lpen_w )
1532{
1533   /* only if 2 rising edges on the lpen input occur at the same
1534      point during successive video fields are the pulses accepted */
1535
1536   /*
1537
1538       1. compute the address of the location on the CRT
1539       2. compare with LAD
1540       3. if not equal move address to LAD
1541       4. if equal set LPEN DETECT flag to 1
1542
1543   */
1544}
1545
1546
1547//-------------------------------------------------
1548//  update_text -
1549//-------------------------------------------------
1550
1551void upd7220_device::update_text(bitmap_rgb32 &bitmap, const rectangle &cliprect)
1552{
1553   UINT32 addr, sad;
1554   UINT16 len;
1555   int im, wd;
1556   int y, sy = 0;
1557
1558   for (int area = 0; area < 4; area++)
1559   {
1560      get_text_partition(area, &sad, &len, &im, &wd);
1561
1562      for (y = sy; y < sy + len; y++)
1563      {
1564         addr = sad + (y * m_pitch);
1565
1566         if (m_draw_text_cb)
1567            m_draw_text_cb(this, bitmap, addr, y, wd, m_pitch, m_lr, m_dc, m_ead);
1568      }
1569
1570      sy = y + 1;
1571   }
1572}
1573
1574
1575//-------------------------------------------------
1576//  draw_graphics_line -
1577//-------------------------------------------------
1578
1579void upd7220_device::draw_graphics_line(bitmap_rgb32 &bitmap, UINT32 addr, int y, int wd)
1580{
1581   int sx;
1582
1583   for (sx = 0; sx < m_pitch * 2; sx++)
1584   {
1585      if((sx << 3) < m_aw * 16 && y < m_al)
1586         m_display_cb(this, bitmap, y, sx << 3, addr);
1587
1588      addr+= wd + 1;
1589   }
1590}
1591
1592
1593//-------------------------------------------------
1594//  update_graphics -
1595//-------------------------------------------------
1596
1597void upd7220_device::update_graphics(bitmap_rgb32 &bitmap, const rectangle &cliprect, int force_bitmap)
1598{
1599   UINT32 addr, sad;
1600   UINT16 len;
1601   int im, wd, area;
1602   int y = 0, tsy = 0, bsy = 0;
1603
1604   for (area = 0; area < 4; area++)
1605   {
1606      get_graphics_partition(area, &sad, &len, &im, &wd);
1607
1608      if (im || force_bitmap)
1609      {
1610         get_graphics_partition(area, &sad, &len, &im, &wd);
1611
1612         if(area >= 2) // TODO: correct?
1613            break;
1614
1615         for (y = 0; y < len; y++)
1616         {
1617            addr = ((sad << 1) & 0x3ffff) + (y * m_pitch * 2);
1618
1619            if (m_display_cb)
1620               draw_graphics_line(bitmap, addr, y + bsy, wd);
1621         }
1622      }
1623      else
1624      {
1625         get_text_partition(area, &sad, &len, &im, &wd);
1626
1627         if(m_lr)
1628         {
1629            for (y = 0; y < len; y+=m_lr)
1630            {
1631               addr = (sad & 0x3ffff) + ((y / m_lr) * m_pitch);
1632
1633               if (m_draw_text_cb)
1634                  m_draw_text_cb(this, bitmap, addr, (y + tsy) / m_lr, wd, m_pitch, m_lr, m_dc, m_ead);
1635            }
1636         }
1637      }
1638
1639      if (m_lr)
1640         tsy += y;
1641      bsy += y;
1642   }
1643}
1644
1645
1646//-------------------------------------------------
1647//  update_screen -
1648//-------------------------------------------------
1649
1650UINT32 upd7220_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
1651{
1652   if (m_de)
1653   {
1654      switch (m_mode & UPD7220_MODE_DISPLAY_MASK)
1655      {
1656      case UPD7220_MODE_DISPLAY_MIXED:
1657         update_graphics(bitmap, cliprect, 0);
1658         break;
1659
1660      case UPD7220_MODE_DISPLAY_GRAPHICS:
1661         update_graphics(bitmap, cliprect, 1);
1662         break;
1663
1664      case UPD7220_MODE_DISPLAY_CHARACTER:
1665         update_text(bitmap, cliprect);
1666         break;
1667
1668      case UPD7220_MODE_DISPLAY_INVALID:
1669         LOG(("uPD7220 '%s' Invalid Display Mode!\n", tag()));
1670      }
1671   }
1672   return 0;
1673}
Property changes on: trunk/src/emu/video/upd7220.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/video/upd7220.h
r0r21685
1/**********************************************************************
2
3    NEC uPD7220 Graphics Display Controller emulation
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************
9                            _____   _____
10                2xWCLK   1 |*    \_/     | 40  Vcc
11                 _DBIN   2 |             | 39  A17
12                 HSYNC   3 |             | 38  A16
13            V/EXT SYNC   4 |             | 37  AD15
14                 BLANK   5 |             | 36  AD14
15                   ALE   6 |             | 35  AD13
16                   DRQ   7 |             | 34  AD12
17                 _DACK   8 |             | 33  AD11
18                   _RD   9 |             | 32  AD10
19                   _WR  10 |   uPD7220   | 31  AD9
20                    A0  11 |    82720    | 30  AD8
21                   DB0  12 |             | 29  AD7
22                   DB1  13 |             | 28  AD6
23                   DB2  14 |             | 27  AD5
24                   DB3  15 |             | 26  AD4
25                   DB4  16 |             | 25  AD3
26                   DB5  17 |             | 24  AD2
27                   DB6  18 |             | 23  AD1
28                   DB7  19 |             | 22  AD0
29                   GND  20 |_____________| 21  LPEN
30
31**********************************************************************/
32
33#pragma once
34
35#ifndef __UPD7220__
36#define __UPD7220__
37
38#include "emu.h"
39
40
41
42//**************************************************************************
43//  MACROS / CONSTANTS
44//**************************************************************************
45
46
47
48
49//**************************************************************************
50//  INTERFACE CONFIGURATION MACROS
51//**************************************************************************
52
53#define MCFG_UPD7220_ADD(_tag, _clock, _config, _map) \
54   MCFG_DEVICE_ADD(_tag, UPD7220, _clock) \
55   MCFG_DEVICE_CONFIG(_config) \
56   MCFG_DEVICE_ADDRESS_MAP(AS_0, _map)
57
58#define UPD7220_INTERFACE(name) \
59   const upd7220_interface (name) =
60
61
62
63//**************************************************************************
64//  TYPE DEFINITIONS
65//**************************************************************************
66
67typedef void (*upd7220_display_pixels_func)(device_t *device, bitmap_rgb32 &bitmap, int y, int x, UINT32 address);
68#define UPD7220_DISPLAY_PIXELS(name) void name(device_t *device, bitmap_rgb32 &bitmap, int y, int x, UINT32 address)
69
70typedef void (*upd7220_draw_text_line)(device_t *device, bitmap_rgb32 &bitmap, UINT32 addr, int y, int wd, int pitch, int lr, int cursor_on, int cursor_addr);
71#define UPD7220_DRAW_TEXT_LINE(name) void name(device_t *device, bitmap_rgb32 &bitmap, UINT32 addr, int y, int wd, int pitch, int lr, int cursor_on, int cursor_addr)
72
73
74// ======================> upd7220_interface
75
76struct upd7220_interface
77{
78   const char *m_screen_tag;
79
80   upd7220_display_pixels_func m_display_cb;
81   upd7220_draw_text_line m_draw_text_cb;
82
83   devcb_write_line        m_out_drq_cb;
84   devcb_write_line        m_out_hsync_cb;
85   devcb_write_line        m_out_vsync_cb;
86   devcb_write_line        m_out_blank_cb;
87};
88
89// ======================> upd7220_device
90
91class upd7220_device :  public device_t,
92                  public device_memory_interface,
93                  public upd7220_interface
94{
95public:
96   // construction/destruction
97   upd7220_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
98
99   DECLARE_READ8_MEMBER( read );
100   DECLARE_WRITE8_MEMBER( write );
101
102   DECLARE_READ8_MEMBER( dack_r );
103   DECLARE_WRITE8_MEMBER( dack_w );
104
105   DECLARE_WRITE_LINE_MEMBER( ext_sync_w );
106   DECLARE_WRITE_LINE_MEMBER( lpen_w );
107
108   DECLARE_WRITE8_MEMBER( bank_w );
109   DECLARE_READ8_MEMBER( vram_r );
110   DECLARE_WRITE8_MEMBER( vram_w );
111
112   UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
113   virtual const rom_entry *device_rom_region() const;
114   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
115
116protected:
117   // device-level overrides
118   virtual void device_start();
119   virtual void device_reset();
120   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
121   virtual void device_config_complete();
122
123private:
124   static const device_timer_id TIMER_VSYNC = 0;
125   static const device_timer_id TIMER_HSYNC = 1;
126   static const device_timer_id TIMER_BLANK = 2;
127
128   inline UINT8 readbyte(offs_t address);
129   inline void writebyte(offs_t address, UINT8 data);
130   inline void fifo_clear();
131   inline int fifo_param_count();
132   inline void fifo_set_direction(int dir);
133   inline void queue(UINT8 data, int flag);
134   inline void dequeue(UINT8 *data, int *flag);
135   inline void update_vsync_timer(int state);
136   inline void update_hsync_timer(int state);
137   inline void update_blank_timer(int state);
138   inline void recompute_parameters();
139   inline void reset_figs_param();
140   inline void advance_ead();
141   inline void read_vram(UINT8 type, UINT8 mod);
142   inline void write_vram(UINT8 type, UINT8 mod);
143   inline UINT16 check_pattern(UINT16 pattern);
144   inline void get_text_partition(int index, UINT32 *sad, UINT16 *len, int *im, int *wd);
145   inline void get_graphics_partition(int index, UINT32 *sad, UINT16 *len, int *im, int *wd);
146
147   void draw_pixel(int x, int y, UINT8 tile_data);
148   void draw_line(int x, int y);
149   void draw_rectangle(int x, int y);
150   void draw_char(int x, int y);
151   int translate_command(UINT8 data);
152   void process_fifo();
153   void update_text(bitmap_rgb32 &bitmap, const rectangle &cliprect);
154   void draw_graphics_line(bitmap_rgb32 &bitmap, UINT32 addr, int y, int wd);
155   void update_graphics(bitmap_rgb32 &bitmap, const rectangle &cliprect, int force_bitmap);
156
157   devcb_resolved_write_line   m_out_drq_func;
158   devcb_resolved_write_line   m_out_hsync_func;
159   devcb_resolved_write_line   m_out_vsync_func;
160   devcb_resolved_write_line   m_out_blank_func;
161
162   screen_device *m_screen;
163
164   UINT16 m_mask;                  // mask register
165   UINT8 m_pitch;                  // number of word addresses in display memory in the horizontal direction
166   UINT32 m_ead;                   // execute word address
167   UINT16 m_dad;                   // dot address within the word
168   UINT32 m_lad;                   // light pen address
169
170   UINT8 m_ra[16];                 // parameter RAM
171   int m_ra_addr;                  // parameter RAM address
172
173   UINT8 m_sr;                     // status register
174   UINT8 m_cr;                     // command register
175   UINT8 m_pr[17];                 // parameter byte register
176   int m_param_ptr;                // parameter pointer
177
178   UINT8 m_fifo[16];               // FIFO data queue
179   int m_fifo_flag[16];            // FIFO flag queue
180   int m_fifo_ptr;                 // FIFO pointer
181   int m_fifo_dir;                 // FIFO direction
182
183   UINT8 m_mode;                   // mode of operation
184   UINT8 m_draw_mode;              // mode of drawing
185
186   int m_de;                       // display enabled
187   int m_m;                        // 0 = accept external vertical sync (slave mode) / 1 = generate & output vertical sync (master mode)
188   int m_aw;                       // active display words per line - 2 (must be even number with bit 0 = 0)
189   int m_al;                       // active display lines per video field
190   int m_vs;                       // vertical sync width - 1
191   int m_vfp;                      // vertical front porch width - 1
192   int m_vbp;                      // vertical back porch width - 1
193   int m_hs;                       // horizontal sync width - 1
194   int m_hfp;                      // horizontal front porch width - 1
195   int m_hbp;                      // horizontal back porch width - 1
196
197   int m_dc;                       // display cursor
198   int m_sc;                       // 0 = blinking cursor / 1 = steady cursor
199   int m_br;                       // blink rate
200   int m_ctop;                     // cursor top line number in the row
201   int m_cbot;                     // cursor bottom line number in the row (CBOT < LR)
202   int m_lr;                       // lines per character row - 1
203
204   int m_disp;                     // display zoom factor
205   int m_gchr;                     // zoom factor for graphics character writing and area filling
206
207   UINT8 m_bitmap_mod;
208
209   struct {
210      UINT8 m_dir;                // figs param 0: drawing direction
211      UINT8 m_figure_type;        // figs param 1: figure type
212      UINT16 m_dc;                // figs param 2:
213      UINT16 m_d;                 // figs param 3:
214      UINT16 m_d1;                // figs param 4:
215      UINT16 m_d2;                // figs param 5:
216      UINT16 m_dm;                // figs param 6:
217   } m_figs;
218
219   // timers
220   emu_timer *m_vsync_timer;       // vertical sync timer
221   emu_timer *m_hsync_timer;       // horizontal sync timer
222   emu_timer *m_blank_timer;       // CRT blanking timer
223
224   const address_space_config      m_space_config;
225};
226
227
228// device type definition
229extern const device_type UPD7220;
230
231
232
233#endif
Property changes on: trunk/src/emu/video/upd7220.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/video/hd44780.c
r0r21685
1/***************************************************************************
2
3        Hitachi HD44780 LCD controller
4
5        TODO:
6        - dump internal CGROM
7
8***************************************************************************/
9
10#include "emu.h"
11#include "video/hd44780.h"
12
13#define LOG          0
14
15//**************************************************************************
16//  DEVICE DEFINITIONS
17//**************************************************************************
18
19const device_type HD44780 = &device_creator<hd44780_device>;
20const device_type KS0066_F05 = &device_creator<ks0066_f05_device>;
21
22
23//-------------------------------------------------
24//  ROM( hd44780 )
25//-------------------------------------------------
26
27ROM_START( hd44780_a00 )
28   ROM_REGION( 0x1000, "cgrom", 0 )
29   ROM_LOAD( "hd44780_a00.bin",    0x0000, 0x1000,  BAD_DUMP CRC(01d108e2) SHA1(bc0cdf0c9ba895f22e183c7bd35a3f655f2ca96f)) // from page 17 of the HD44780 datasheet
30ROM_END
31
32ROM_START( ks0066_f05 )
33   ROM_REGION( 0x1000, "cgrom", 0 )
34   ROM_LOAD( "ks0066_f05.bin",    0x0000, 0x1000,  BAD_DUMP CRC(af9e7bd6) SHA1(0196e871584ee5d370856e7307c0f9d1466e3e51)) // from page 51 of the KS0066 datasheet
35ROM_END
36
37//**************************************************************************
38//  live device
39//**************************************************************************
40
41//-------------------------------------------------
42//  hd44780_device - constructor
43//-------------------------------------------------
44
45hd44780_device::hd44780_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
46   device_t(mconfig, HD44780, "HD44780 A00", tag, owner, clock),
47   m_pixel_update_func(NULL)
48{
49   m_shortname = "hd44780_a00";
50   set_charset_type(CHARSET_HD44780_A00);
51}
52
53hd44780_device::hd44780_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
54   device_t(mconfig, type, name, tag, owner, clock),
55   m_pixel_update_func(NULL)
56{
57}
58
59ks0066_f05_device::ks0066_f05_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
60   hd44780_device(mconfig, KS0066_F05, "KS0066 F05", tag, owner, clock)
61{
62   m_shortname = "ks0066_f05";
63   set_charset_type(CHARSET_KS0066_F05);
64}
65
66
67//-------------------------------------------------
68//  rom_region - device-specific ROM region
69//-------------------------------------------------
70
71const rom_entry *hd44780_device::device_rom_region() const
72{
73   switch (m_charset_type)
74   {
75      case CHARSET_HD44780_A00:   return ROM_NAME( hd44780_a00 );
76      case CHARSET_KS0066_F05:    return ROM_NAME( ks0066_f05 );
77   }
78
79   return NULL;
80}
81
82//-------------------------------------------------
83//  device_start - device-specific startup
84//-------------------------------------------------
85
86void hd44780_device::device_start()
87{
88   if (region())
89      m_cgrom = (UINT8*)(*region());
90   else
91      m_cgrom = (UINT8*)(*memregion("cgrom"));
92
93   m_busy_timer = timer_alloc(TIMER_BUSY);
94   m_blink_timer = timer_alloc(TIMER_BLINKING);
95   m_blink_timer->adjust(attotime::from_msec(409), 0, attotime::from_msec(409));
96
97   // state saving
98   save_item(NAME(m_busy_flag));
99   save_item(NAME(m_ac));
100   save_item(NAME(m_dr));
101   save_item(NAME(m_ir));
102   save_item(NAME(m_active_ram));
103   save_item(NAME(m_display_on));
104   save_item(NAME(m_cursor_on));
105   save_item(NAME(m_shift_on));
106   save_item(NAME(m_blink_on));
107   save_item(NAME(m_direction));
108   save_item(NAME(m_data_len));
109   save_item(NAME(m_num_line));
110   save_item(NAME(m_char_size));
111   save_item(NAME(m_disp_shift));
112   save_item(NAME(m_blink));
113   save_item(NAME(m_ddram));
114   save_item(NAME(m_cgram));
115   save_item(NAME(m_nibble));
116   save_item(NAME(m_rs_state));
117   save_item(NAME(m_rw_state));
118}
119
120//-------------------------------------------------
121//  device_reset - device-specific reset
122//-------------------------------------------------
123
124void hd44780_device::device_reset()
125{
126   memset(m_ddram, 0x20, sizeof(m_ddram)); // can't use 0 here as it would show CGRAM instead of blank space on a soft reset
127   memset(m_cgram, 0, sizeof(m_cgram));
128
129   m_ac         = 0;
130   m_dr         = 0;
131   m_ir         = 0;
132   m_active_ram = DDRAM;
133   m_display_on = false;
134   m_cursor_on  = false;
135   m_blink_on   = false;
136   m_shift_on   = false;
137   m_direction  = 1;
138   m_data_len   = 8;
139   m_num_line   = 1;
140   m_char_size  = 8;
141   m_disp_shift = 0;
142   m_blink      = false;
143   m_nibble     = false;
144   m_first_cmd  = true;
145   m_rs_state   = 0;
146   m_rw_state   = 0;
147
148   set_busy_flag(1520);
149}
150
151
152//-------------------------------------------------
153//  device_timer - handler timer events
154//-------------------------------------------------
155
156void hd44780_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
157{
158   switch(id)
159   {
160      case TIMER_BUSY:
161         m_busy_flag = false;
162         break;
163
164      case TIMER_BLINKING:
165         m_blink = !m_blink;
166         break;
167   }
168}
169
170
171//**************************************************************************
172//  HELPERS
173//**************************************************************************
174
175void hd44780_device::set_charset_type(int type)
176{
177   m_charset_type = type;
178}
179
180void hd44780_device::set_busy_flag(UINT16 usec)
181{
182   m_busy_flag = true;
183   m_busy_timer->adjust( attotime::from_usec( usec ) );
184}
185
186void hd44780_device::update_ac(int direction)
187{
188   if (m_active_ram == DDRAM)
189   {
190      if(direction == 1)
191      {
192         if(m_num_line == 2 && m_ac == 0x27)
193            m_ac = 0x40;
194         else if((m_num_line == 2 && m_ac == 0x67) || (m_num_line == 1 && m_ac == 0x4f))
195            m_ac = 0x00;
196         else
197            m_ac = (m_ac + direction) & 0x7f;
198      }
199      else
200      {
201         if(m_num_line == 2 && m_ac == 0x00)
202            m_ac = 0x67;
203         else if(m_num_line == 1 && m_ac == 0x00)
204            m_ac = 0x4f;
205         else if(m_num_line == 2 && m_ac == 0x40)
206            m_ac = 0x27;
207         else
208            m_ac = (m_ac + direction) & 0x7f;
209      }
210   }
211   else
212   {
213      m_ac = (m_ac + direction) & 0x3f;
214   }
215}
216
217void hd44780_device::shift_display(int direction)
218{
219   if (direction == 1)
220   {
221      if(m_disp_shift == 0x4f)
222         m_disp_shift = 0x00;
223      else
224         m_disp_shift++;
225   }
226   else
227   {
228      if(m_disp_shift == 0x00)
229         m_disp_shift = 0x4f;
230      else
231         m_disp_shift--;
232   }
233}
234
235void hd44780_device::update_nibble(int rs, int rw)
236{
237   if (m_rs_state != rs || m_rw_state != rw)
238   {
239      m_rs_state = rs;
240      m_rw_state = rw;
241      m_nibble = false;
242   }
243
244   m_nibble = !m_nibble;
245}
246
247inline void hd44780_device::pixel_update(bitmap_ind16 &bitmap, UINT8 line, UINT8 pos, UINT8 y, UINT8 x, int state)
248{
249   if (m_pixel_update_func != NULL)
250   {
251      m_pixel_update_func(*this, bitmap, line, pos, y, x, state);
252   }
253   else
254   {
255      UINT8 line_heigh = (m_char_size == 8) ? m_char_size : m_char_size + 1;
256
257      if (m_lines <= 2)
258      {
259         if (pos < m_chars)
260            bitmap.pix16(line * (line_heigh+1) + y, pos * 6 + x) = state;
261      }
262      else if (m_lines <= 4)
263      {
264         if (pos < m_chars*2)
265         {
266            if (pos >= m_chars)
267            {
268               line += 2;
269               pos -= m_chars;
270            }
271
272            if (line < m_lines)
273               bitmap.pix16(line * (line_heigh+1) + y, pos * 6 + x) = state;
274         }
275      }
276      else
277      {
278         fatalerror("%s: use a custom callback for this LCD configuration (%d x %d)\n", tag(), m_lines, m_chars);
279      }
280   }
281}
282
283
284//**************************************************************************
285//  device interface
286//**************************************************************************
287
288UINT32 hd44780_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
289{
290   bitmap.fill(0, cliprect);
291
292   if (m_display_on)
293   {
294      UINT8 line_size = 80 / m_num_line;
295
296      for (int line=0; line<m_num_line; line++)
297      {
298         for (int pos=0; pos<line_size; pos++)
299         {
300            UINT16 char_pos = line * 0x40 + ((pos + m_disp_shift) % line_size);
301
302            int char_base = 0;
303            if (m_ddram[char_pos] < 0x10)
304            {
305               // draw CGRAM characters
306               if (m_char_size == 8)
307                  char_base = (m_ddram[char_pos] & 0x07) * 8;
308               else
309                  char_base = ((m_ddram[char_pos]>>1) & 0x03) * 16;
310            }
311            else
312            {
313               // draw CGROM characters
314               char_base = m_ddram[char_pos] * 0x10;
315            }
316
317            for (int y=0; y<m_char_size; y++)
318            {
319               UINT8 * charset = (m_ddram[char_pos] < 0x10) ? m_cgram : m_cgrom;
320
321               for (int x=0; x<5; x++)
322                  pixel_update(bitmap, line, pos, y, x, BIT(charset[char_base + y], 4 - x));
323            }
324
325            // if is the correct position draw cursor and blink
326            if (char_pos == m_ac)
327            {
328               // draw the cursor
329               UINT8 cursor_pos = (m_char_size == 8) ? m_char_size : m_char_size + 1;
330               if (m_cursor_on)
331                  for (int x=0; x<5; x++)
332                     pixel_update(bitmap, line, pos, cursor_pos - 1, x, 1);
333
334               if (!m_blink && m_blink_on)
335                  for (int y=0; y<(cursor_pos - 1); y++)
336                     for (int x=0; x<5; x++)
337                        pixel_update(bitmap, line, pos, y, x, 1);
338            }
339         }
340      }
341   }
342
343   return 0;
344}
345
346READ8_MEMBER(hd44780_device::read)
347{
348   switch(offset & 0x01)
349   {
350      case 0: return control_read(space, 0);
351      case 1: return data_read(space, 0);
352   }
353
354   return 0;
355}
356
357WRITE8_MEMBER(hd44780_device::write)
358{
359   switch(offset & 0x01)
360   {
361      case 0: control_write(space, 0, data);  break;
362      case 1: data_write(space, 0, data);     break;
363   }
364}
365
366WRITE8_MEMBER(hd44780_device::control_write)
367{
368   if (m_data_len == 4)
369   {
370      update_nibble(0, 0);
371
372      if (m_nibble)
373      {
374         m_ir = data & 0xf0;
375         return;
376      }
377      else
378      {
379         m_ir |= ((data>>4) & 0x0f);
380      }
381   }
382   else
383   {
384      m_ir = data;
385   }
386
387   if (BIT(m_ir, 7))           // set DDRAM address
388   {
389      m_active_ram = DDRAM;
390      m_ac = m_ir & 0x7f;
391      set_busy_flag(37);
392
393      if (LOG) logerror("HD44780 '%s': set DDRAM address %x\n", tag(), m_ac);
394   }
395   else if (BIT(m_ir, 6))      // set CGRAM address
396   {
397      m_active_ram = CGRAM;
398      m_ac = m_ir & 0x3f;
399      set_busy_flag(37);
400
401      if (LOG) logerror("HD44780 '%s': set CGRAM address %x\n", tag(), m_ac);
402   }
403   else if (BIT(m_ir, 5))      // function set
404   {
405      if (!m_first_cmd && m_data_len == (BIT(m_ir, 4) ? 8 : 4) && (m_char_size != (BIT(m_ir, 2) ? 10 : 8) || m_num_line != (BIT(m_ir, 3) + 1)))
406      {
407         logerror("HD44780 '%s': function set cannot be executed after other instructions unless the interface data length is changed\n", tag());
408         return;
409      }
410
411      m_char_size = BIT(m_ir, 2) ? 10 : 8;
412      m_data_len  = BIT(m_ir, 4) ? 8 : 4;
413      m_num_line  = BIT(m_ir, 3) + 1;
414      set_busy_flag(37);
415
416      if (LOG) logerror("HD44780 '%s': char size 5x%d, data len %d, lines %d\n", tag(), m_char_size, m_data_len, m_num_line);
417      return;
418   }
419   else if (BIT(m_ir, 4))      // cursor or display shift
420   {
421      int direct = (BIT(m_ir, 2)) ? +1 : -1;
422
423      if (LOG) logerror("HD44780 '%s': %s shift %d\n", tag(), BIT(m_ir, 3) ? "display" : "cursor",  direct);
424
425      if (BIT(m_ir, 3))
426         shift_display(direct);
427      else
428         update_ac(direct);
429
430      set_busy_flag(37);
431   }
432   else if (BIT(m_ir, 3))      // display on/off control
433   {
434      m_display_on = BIT(m_ir, 2);
435      m_cursor_on  = BIT(m_ir, 1);
436      m_blink_on   = BIT(m_ir, 0);
437      set_busy_flag(37);
438
439      if (LOG) logerror("HD44780 '%s': display %d, cursor %d, blink %d\n", tag(), m_display_on, m_cursor_on, m_blink_on);
440   }
441   else if (BIT(m_ir, 2))      // entry mode set
442   {
443      m_direction = (BIT(m_ir, 1)) ? +1 : -1;
444      m_shift_on  = BIT(m_ir, 0);
445      set_busy_flag(37);
446
447      if (LOG) logerror("HD44780 '%s': entry mode set: direction %d, shift %d\n", tag(), m_direction, m_shift_on);
448   }
449   else if (BIT(m_ir, 1))      // return home
450   {
451      if (LOG) logerror("HD44780 '%s': return home\n", tag());
452
453      m_ac         = 0;
454      m_active_ram = DDRAM;
455      m_direction  = 1;
456      m_disp_shift = 0;
457      set_busy_flag(1520);
458   }
459   else if (BIT(m_ir, 0))      // clear display
460   {
461      if (LOG) logerror("HD44780 '%s': clear display\n", tag());
462
463      m_ac         = 0;
464      m_active_ram = DDRAM;
465      m_direction  = 1;
466      m_disp_shift = 0;
467      memset(m_ddram, 0x20, sizeof(m_ddram));
468      set_busy_flag(1520);
469   }
470
471   m_first_cmd = false;
472}
473
474READ8_MEMBER(hd44780_device::control_read)
475{
476   if (m_data_len == 4)
477   {
478      if (!space.debugger_access())
479         update_nibble(0, 1);
480
481      if (m_nibble)
482         return (m_busy_flag ? 0x80 : 0) | (m_ac & 0x70);
483      else
484         return (m_ac<<4) & 0xf0;
485   }
486   else
487   {
488      return (m_busy_flag ? 0x80 : 0) | (m_ac & 0x7f);
489   }
490}
491
492WRITE8_MEMBER(hd44780_device::data_write)
493{
494   if (m_busy_flag)
495   {
496      logerror("HD44780 '%s': Ignoring data write %02x due of busy flag\n", tag(), data);
497      return;
498   }
499
500   if (m_data_len == 4)
501   {
502      update_nibble(1, 0);
503
504      if (m_nibble)
505      {
506         m_dr = data & 0xf0;
507         return;
508      }
509      else
510      {
511         m_dr |= ((data>>4) & 0x0f);
512      }
513   }
514   else
515   {
516      m_dr = data;
517   }
518
519   if (LOG) logerror("HD44780 '%s': %sRAM write %x %x '%c'\n", tag(), m_active_ram == DDRAM ? "DD" : "CG", m_ac, m_dr, isprint(m_dr) ? m_dr : '.');
520
521   if (m_active_ram == DDRAM)
522      m_ddram[m_ac] = m_dr;
523   else
524      m_cgram[m_ac] = m_dr;
525
526   update_ac(m_direction);
527   if (m_shift_on)
528      shift_display(m_direction);
529   set_busy_flag(41);
530}
531
532READ8_MEMBER(hd44780_device::data_read)
533{
534   UINT8 data = (m_active_ram == DDRAM) ? m_ddram[m_ac] : m_cgram[m_ac];
535
536   if (LOG) logerror("HD44780 '%s': %sRAM read %x %c\n", tag(), m_active_ram == DDRAM ? "DD" : "CG", m_ac, data);
537
538   if (m_data_len == 4)
539   {
540      if (!space.debugger_access())
541         update_nibble(1, 1);
542
543      if (m_nibble)
544         return data & 0xf0;
545      else
546         data = (data<<4) & 0xf0;
547   }
548
549   if (!space.debugger_access())
550   {
551      update_ac(m_direction);
552      set_busy_flag(41);
553   }
554
555   return data;
556}
Property changes on: trunk/src/emu/video/hd44780.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/video/hd44780.h
r0r21685
1/***************************************************************************
2
3        Hitachi HD44780 LCD controller
4
5***************************************************************************/
6
7#pragma once
8
9#ifndef __HD44780_H__
10#define __HD44780_H__
11
12
13#define MCFG_HD44780_ADD( _tag ) \
14   MCFG_DEVICE_ADD( _tag, HD44780, 0 )
15
16#define MCFG_KS0066_F05_ADD( _tag ) \
17   MCFG_DEVICE_ADD( _tag, KS0066_F05, 0 )
18
19#define MCFG_HD44780_LCD_SIZE(_lines, _chars) \
20   hd44780_device::static_set_lcd_size(*device, _lines, _chars);
21
22#define MCFG_HD44780_PIXEL_UPDATE_CB(_cb) \
23   hd44780_device::static_set_pixel_update_cb(*device, _cb);
24
25//**************************************************************************
26//  TYPE DEFINITIONS
27//**************************************************************************
28
29typedef void (*hd44780_pixel_update_func)(device_t &device, bitmap_ind16 &bitmap, UINT8 line, UINT8 pos, UINT8 y, UINT8 x, int state);
30#define HD44780_PIXEL_UPDATE(name) void name(device_t &device, bitmap_ind16 &bitmap, UINT8 line, UINT8 pos, UINT8 y, UINT8 x, int state)
31
32
33// ======================> hd44780_device
34
35class hd44780_device :  public device_t
36{
37public:
38   // construction/destruction
39   hd44780_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
40   hd44780_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
41
42   // static configuration helpers
43   static void static_set_lcd_size(device_t &device, int _lines, int _chars) { hd44780_device &dev=downcast<hd44780_device &>(device); dev.m_lines = _lines; dev.m_chars = _chars; }
44   static void static_set_pixel_update_cb(device_t &device, hd44780_pixel_update_func _cb) { downcast<hd44780_device &>(device).m_pixel_update_func = _cb; }
45
46   // device interface
47   virtual DECLARE_WRITE8_MEMBER(write);
48   virtual DECLARE_READ8_MEMBER(read);
49   virtual DECLARE_WRITE8_MEMBER(control_write);
50   virtual DECLARE_READ8_MEMBER(control_read);
51   virtual DECLARE_WRITE8_MEMBER(data_write);
52   virtual DECLARE_READ8_MEMBER(data_read);
53   virtual UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
54
55protected:
56   // device-level overrides
57   virtual void device_start();
58   virtual void device_reset();
59   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
60
61   // optional information overrides
62   virtual const rom_entry *device_rom_region() const;
63
64   // charset
65   enum
66   {
67      CHARSET_HD44780_A00,
68      CHARSET_KS0066_F05,
69      /*
70      CHARSET_HD44780_A01,
71      CHARSET_HD44780_A02,
72      CHARSET_KS0066_F00,
73      CHARSET_KS0066_F03,
74      CHARSET_KS0066_F04,
75      CHARSET_KS0066_F06,
76      CHARSET_KS0066_F59,
77      */
78   };
79
80   void set_charset_type(int type);
81
82private:
83   // internal helper
84   void set_busy_flag(UINT16 usec);
85   void update_ac(int direction);
86   void update_nibble(int rs, int rw);
87   void shift_display(int direction);
88   void pixel_update(bitmap_ind16 &bitmap, UINT8 line, UINT8 pos, UINT8 y, UINT8 x, int state);
89
90   // internal state
91   static const device_timer_id TIMER_BUSY = 0;
92   static const device_timer_id TIMER_BLINKING = 1;
93
94   emu_timer * m_blink_timer;
95   emu_timer * m_busy_timer;
96
97   UINT8       m_lines;          // number of lines
98   UINT8       m_chars;          // chars for line
99   hd44780_pixel_update_func m_pixel_update_func; // pixel update callback
100
101   bool        m_busy_flag;      // busy flag
102   UINT8       m_ddram[0x80];    // internal display data RAM
103   UINT8       m_cgram[0x40];    // internal chargen RAM
104   UINT8 *     m_cgrom;          // internal chargen ROM
105   INT8        m_ac;             // address counter
106   UINT8       m_dr;             // data register
107   UINT8       m_ir;             // instruction register
108   UINT8       m_active_ram;     // DDRAM or CGRAM
109   bool        m_display_on;     // display on/off
110   bool        m_cursor_on;      // cursor on/off
111   bool        m_blink_on;       // blink on/off
112   bool        m_shift_on;       // shift on/off
113   UINT8       m_disp_shift;     // display shift
114   INT8        m_direction;      // auto increment/decrement
115   UINT8       m_data_len;       // interface data length 4 or 8 bit
116   UINT8       m_num_line;       // number of lines
117   UINT8       m_char_size;      // char size 5x8 or 5x10
118   bool        m_blink;
119   bool        m_first_cmd;
120   int         m_rs_state;
121   int         m_rw_state;
122   bool        m_nibble;
123   int         m_charset_type;
124
125   enum        { DDRAM, CGRAM };
126};
127
128// ======================> ks0066_f05_device
129
130class ks0066_f05_device :  public hd44780_device
131{
132public:
133   // construction/destruction
134   ks0066_f05_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
135};
136
137// device type definition
138extern const device_type HD44780;
139extern const device_type KS0066_F05;
140
141#endif
Property changes on: trunk/src/emu/video/hd44780.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/mess/includes/c64_legacy.h
r21684r21685
1/*****************************************************************************
2 *
3 * includes/c64.h
4 *
5 * Commodore C64 Home Computer
6 *
7 * peter.trauner@jk.uni-linz.ac.at
8 *
9 * Documentation: www.funet.fi
10 *
11 ****************************************************************************/
12
13#ifndef C64_H_
14#define C64_H_
15
16#include "machine/6526cia.h"
17#include "machine/cbmiec.h"
18#include "imagedev/cartslot.h"
19
20#define C64_MAX_ROMBANK 64 // .crt files contain multiple 'CHIPs', i.e. rom banks (of variable size) with headers. Known carts have at most 64 'CHIPs'.
21
22struct C64_ROM {
23   int addr, size, index, start;
24};
25
26struct c64_cart_t {
27   C64_ROM     bank[C64_MAX_ROMBANK];
28   INT8        game;
29   INT8        exrom;
30   UINT8       mapper;
31   UINT8       n_banks;
32};
33
34class legacy_c64_state : public driver_device
35{
36public:
37   legacy_c64_state(const machine_config &mconfig, device_type type, const char *tag)
38      : driver_device(mconfig, type, tag),
39         m_iec(*this, CBM_IEC_TAG),
40         m_colorram(*this, "colorram"),
41         m_basic(*this, "basic"),
42         m_chargen(*this, "chargen"),
43         m_kernal(*this, "kernal"),
44         m_roml_writable(0)
45   { }
46
47   optional_device<cbm_iec_device> m_iec;
48
49   required_shared_ptr<UINT8> m_colorram;
50   required_shared_ptr<UINT8> m_basic;
51   required_shared_ptr<UINT8> m_chargen;
52   required_shared_ptr<UINT8> m_kernal;
53
54   DECLARE_READ8_MEMBER( c64_lightpen_x_cb );
55   DECLARE_READ8_MEMBER( c64_lightpen_y_cb );
56   DECLARE_READ8_MEMBER( c64_lightpen_button_cb );
57   DECLARE_READ8_MEMBER( c64_dma_read );
58   DECLARE_READ8_MEMBER( c64_dma_read_ultimax );
59   DECLARE_READ8_MEMBER( c64_dma_read_color );
60   DECLARE_WRITE_LINE_MEMBER( c64_vic_interrupt );
61   DECLARE_READ8_MEMBER( c64_rdy_cb );
62
63   int m_old_level;
64   int m_old_data;
65   int m_old_exrom;
66   int m_old_game;
67   UINT8 m_vicirq;
68   emu_timer *m_datasette_timer;
69   emu_timer *m_cartridge_timer;
70   UINT8 *m_memory;
71   int m_pal;
72   int m_tape_on;
73   UINT8 *m_c64_roml;
74   UINT8 *m_c64_romh;
75   UINT8 *m_vicaddr;
76   UINT8 *m_c128_vicaddr;
77   UINT8 m_game;
78   UINT8 m_exrom;
79   UINT8 *m_io_mirror;
80   UINT8 m_port_data;
81   UINT8 *m_roml;
82   UINT8 *m_romh;
83   int m_roml_writable;
84   int m_ultimax;
85   int m_cia1_on;
86   int m_io_enabled;
87   int m_is_sx64;
88   UINT8 *m_io_ram_w_ptr;
89   UINT8 *m_io_ram_r_ptr;
90   c64_cart_t m_cart;
91   int m_nmilevel;
92   void c64_legacy_driver_init();
93   DECLARE_DEVICE_IMAGE_LOAD_MEMBER( c64_cart );
94   DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER( c64_cart );
95};
96
97
98/*----------- defined in machine/c64.c -----------*/
99
100
101DECLARE_READ8_HANDLER ( c64_colorram_read );
102DECLARE_WRITE8_HANDLER ( c64_colorram_write );
103int c64_paddle_read (device_t *device, address_space &space, int which);
104MACHINE_CONFIG_EXTERN( c64_cartslot );
105#endif /* C64_H_ */
trunk/src/mess/includes/c65.h
r21684r21685
77#ifndef C65_H_
88#define C65_H_
99
10#include "includes/c64_legacy.h"
1110#include "machine/6526cia.h"
11#include "machine/cbmiec.h"
12#include "imagedev/cartslot.h"
1213
14#define C64_MAX_ROMBANK 64 // .crt files contain multiple 'CHIPs', i.e. rom banks (of variable size) with headers. Known carts have at most 64 'CHIPs'.
15
16struct C64_ROM {
17   int addr, size, index, start;
18};
19
20struct c64_cart_t {
21   C64_ROM     bank[C64_MAX_ROMBANK];
22   INT8        game;
23   INT8        exrom;
24   UINT8       mapper;
25   UINT8       n_banks;
26};
27
1328struct dma_t
1429{
1530   int version;
r21684r21685
3752   UINT8 reg;
3853};
3954
40class c65_state : public legacy_c64_state
55class c65_state : public driver_device
4156{
4257public:
4358   c65_state(const machine_config &mconfig, device_type type, const char *tag)
44      : legacy_c64_state(mconfig, type, tag),
59      : driver_device(mconfig, type, tag),
60         m_iec(*this, CBM_IEC_TAG),
61         m_colorram(*this, "colorram"),
62         m_basic(*this, "basic"),
63         m_chargen(*this, "chargen"),
64         m_kernal(*this, "kernal"),
4565         m_c65_chargen(*this, "c65_chargen"),
46         m_interface(*this, "interface")
66         m_interface(*this, "interface"),
67         m_roml_writable(0)
4768   { }
4869
70   optional_device<cbm_iec_device> m_iec;
71
72   required_shared_ptr<UINT8> m_colorram;
73   required_shared_ptr<UINT8> m_basic;
74   required_shared_ptr<UINT8> m_chargen;
75   required_shared_ptr<UINT8> m_kernal;
4976   required_shared_ptr<UINT8> m_c65_chargen;
5077   required_shared_ptr<UINT8> m_interface;
51   int m_charset_select;
78   int m_old_level;
79   int m_old_data;
80   int m_old_exrom;
81   int m_old_game;
82   UINT8 m_vicirq;
83   emu_timer *m_datasette_timer;
84   emu_timer *m_cartridge_timer;
85   UINT8 *m_memory;
86   int m_pal;
87   int m_tape_on;
88   UINT8 *m_c64_roml;
89   UINT8 *m_c64_romh;
90   UINT8 *m_vicaddr;
91   UINT8 *m_c128_vicaddr;
92   UINT8 m_game;
93   UINT8 m_exrom;
94   UINT8 *m_io_mirror;
95   UINT8 m_port_data;
96   UINT8 *m_roml;
97   UINT8 *m_romh;
98   int m_roml_writable;
99   int m_ultimax;
100   int m_cia1_on;
101   int m_io_enabled;
102   int m_is_sx64;
103   UINT8 *m_io_ram_w_ptr;
104   UINT8 *m_io_ram_r_ptr;
105   c64_cart_t m_cart;
106   int m_nmilevel;   int m_charset_select;
52107   int m_c64mode;
53108   UINT8 m_6511_port;
54109   UINT8 m_keyline;
55110   int m_old_value;
56   int m_nmilevel;
57111   dma_t m_dma;
58112   int m_dump_dma;
59113   fdc_t m_fdc;
r21684r21685
63117   DECLARE_DRIVER_INIT(c65);
64118   DECLARE_DRIVER_INIT(c65pal);
65119
120   DECLARE_READ8_MEMBER( c64_lightpen_x_cb );
121   DECLARE_READ8_MEMBER( c64_lightpen_y_cb );
122   DECLARE_READ8_MEMBER( c64_lightpen_button_cb );
123   DECLARE_READ8_MEMBER( c64_dma_read );
124   DECLARE_READ8_MEMBER( c64_dma_read_ultimax );
125   DECLARE_READ8_MEMBER( c64_dma_read_color );
126   DECLARE_WRITE_LINE_MEMBER( c64_vic_interrupt );
127   DECLARE_READ8_MEMBER( c64_rdy_cb );
66128   DECLARE_READ8_MEMBER( sid_potx_r );
67129   DECLARE_READ8_MEMBER( sid_poty_r );
68130   DECLARE_MACHINE_START(c65);
r21684r21685
76138   DECLARE_READ8_MEMBER(c65_cia1_port_a_r);
77139   DECLARE_WRITE8_MEMBER(c65_cia1_port_a_w);
78140   DECLARE_WRITE_LINE_MEMBER(c65_cia1_interrupt);
141   void c64_legacy_driver_init();
142   DECLARE_DEVICE_IMAGE_LOAD_MEMBER( c64_cart );
143   DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER( c64_cart );
79144};
80145
81146
r21684r21685
99164extern const legacy_mos6526_interface c65_cia0;
100165extern const legacy_mos6526_interface c65_cia1;
101166
167DECLARE_READ8_HANDLER ( c64_colorram_read );
168DECLARE_WRITE8_HANDLER ( c64_colorram_write );
169MACHINE_CONFIG_EXTERN( c64_cartslot );
170
102171#endif /* C65_H_ */
trunk/src/mess/video/dl1416.c
r21684r21685
1/*****************************************************************************
2 *
3 * video/dl1416.c
4 *
5 * DL1416
6 *
7 * 4-Digit 16-Segment Alphanumeric Intelligent Display
8 * with Memory/Decoder/Driver
9 *
10 * Notes:
11 *   - Currently supports the DL1416T and by virtue of it being nearly the same, the DL1414.
12 *   - Partial support for DL1416B is available, it just needs the right
13 *     character set and MAME core support for its display.
14 *   - Cursor support is implemented but not tested, as the AIM65 does not
15 *     seem to use it.
16 *
17 * Todo:
18 *   - Is the DL1416A identical to the DL1416T? If not, we need to add
19 *     support for it.
20 *   - Add proper support for DL1414 (pretty much DL1416T without the cursor)
21 *
22 * Changes:
23 *   - 2007-07-30: Initial version.  [Dirk Best]
24 *   - 2008-02-25: Converted to the new device interface.  [Dirk Best]
25 *   - 2008-12-18: Cleanups.  [Dirk Best]
26 *   - 2011-10-08: Changed the ram to store character rather than segment data. [Lord Nightmare]
27 *
28 *
29 * We use the following order for the segments:
30 *
31 *   000 111
32 *  7D  A  E2
33 *  7 D A E 2
34 *  7  DAE  2
35 *   888 999
36 *  6  CBF  3
37 *  6 C B F 3
38 *  6C  B  F3
39 *   555 444
40 *
41 ****************************************************************************/
42
43#include "emu.h"
44#include "dl1416.h"
45
46
47/***************************************************************************
48    CONSTANTS
49***************************************************************************/
50
51#define SEG_UNDEF  (-2)
52#define SEG_BLANK  (0)
53#define SEG_CURSOR (0xffff)
54#define CURSOR_ON  (1)
55#define CURSOR_OFF (0)
56
57/* character set DL1416T */
58static const int dl1416t_segments[128] = {
59   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
60   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
61   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
62   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
63   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
64   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
65   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
66   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
67   0x0000,    0x2421,    0x0480,    0x0f3c,    /*   ! " # */
68   0x0fbb,    0x5f99,    0xa579,    0x4000,    /* $ % & ' */
69   0xc000,    0x3000,    0xff00,    0x0f00,    /* ( ) * + */
70   0x1000,    0x0300,    0x0020,    0x5000,    /* , - . / */
71   0x0ce1,    0x0c00,    0x0561,    0x0d21,    /* 0 1 2 3 */
72   0x0d80,    0x09a1,    0x09e1,    0x0c01,    /* 4 5 6 7 */
73   0x0de1,    0x0da1,    0x0021,    0x1001,    /* 8 9 : ; */
74   0x5030,    0x0330,    0xa030,    0x0a07,    /* < = > ? */
75   0x097f,    0x03cf,    0x0e3f,    0x00f3,    /* @ A B C */
76   0x0c3f,    0x01f3,    0x01c3,    0x02fb,    /* D E F G */
77   0x03cc,    0x0c33,    0x0c63,    0xc1c0,    /* H I J K */
78   0x00f0,    0x60cc,    0xa0cc,    0x00ff,    /* L M N O */
79   0x03c7,    0x80ff,    0x83c7,    0x03bb,    /* P Q R S */
80   0x0c03,    0x00fc,    0x50c0,    0x90cc,    /* T U V W */
81   0xf000,    0x6800,    0x5033,    0x00e1,    /* X Y Z [ */
82   0xa000,    0x001e,    0x9000,    0x0030,    /* \ ] ^ _ */
83   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
84   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
85   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
86   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
87   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
88   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
89   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, /* undefined */
90   SEG_UNDEF, SEG_UNDEF, SEG_UNDEF, SEG_UNDEF  /* undefined */
91};
92
93
94/***************************************************************************
95    TYPE DEFINITIONS
96***************************************************************************/
97
98struct dl1416_state
99{
100   int write_enable;
101   int chip_enable;
102   int cursor_enable;
103
104   UINT16 digit_ram[4]; // holds the digit code for each position
105   UINT8 cursor_state[4]; // holds the cursor state for each position, 0=off, 1=on
106};
107
108
109/*****************************************************************************
110    INLINE FUNCTIONS
111*****************************************************************************/
112
113INLINE dl1416_state *get_safe_token(device_t *device)
114{
115   assert(device != NULL);
116   assert(device->type() == DL1416B || device->type() == DL1416T);
117
118   return (dl1416_state *)downcast<dl1416_device *>(device)->token();
119}
120
121
122/*****************************************************************************
123    DEVICE INTERFACE
124*****************************************************************************/
125
126static DEVICE_START( dl1416 )
127{
128   dl1416_state *dl1416 = get_safe_token(device);
129
130   /* register for state saving */
131   state_save_register_item(device->machine(), "dl1416", device->tag(), 0, dl1416->chip_enable);
132   state_save_register_item(device->machine(), "dl1416", device->tag(), 0, dl1416->cursor_enable);
133   state_save_register_item(device->machine(), "dl1416", device->tag(), 0, dl1416->write_enable);
134   state_save_register_item_array(device->machine(), "dl1416", device->tag(), 0, dl1416->digit_ram);
135}
136
137
138static DEVICE_RESET( dl1416 )
139{
140   int i, pattern;
141   dl1416_state *chip = get_safe_token(device);
142   const dl1416_interface *intf = (const dl1416_interface *)device->static_config();
143   /* disable all lines */
144   chip->chip_enable = FALSE;
145   chip->write_enable = FALSE;
146   chip->cursor_enable = FALSE;
147
148   /* randomize digit and cursor memory */
149   for (i = 0; i < 4; i++)
150   {
151      chip->digit_ram[i] = device->machine().rand()&0x3F;
152      // TODO: only enable the following line if the device actually has a cursor (DL1416T and DL1416B), if DL1414 then cursor is always 0!
153      //chip->cursor_state[i] = ((device->machine().rand()&0xFF) >= 0x80) ? CURSOR_ON : CURSOR_OFF;
154      chip->cursor_state[i] = CURSOR_OFF;
155      pattern = dl1416t_segments[chip->digit_ram[i]];
156
157      /* If cursor for this digit position is enabled and segment is not */
158      /* undefined, replace digit with cursor */
159      if ((chip->cursor_state[i] == CURSOR_ON) && (pattern != SEG_UNDEF))
160         pattern = SEG_CURSOR;
161
162      /* Undefined characters are replaced by blanks */
163      if (pattern == SEG_UNDEF)
164         pattern = SEG_BLANK;
165
166      /* Call update function */
167      if (intf->update)
168         intf->update(device, i, pattern);
169   }
170}
171
172
173/*****************************************************************************
174    IMPLEMENTATION
175*****************************************************************************/
176
177/* write enable, active low */
178WRITE_LINE_DEVICE_HANDLER( dl1416_wr_w )
179{
180   dl1416_state *chip = get_safe_token(device);
181   chip->write_enable = !state;
182}
183
184/* chip enable, active low */
185WRITE_LINE_DEVICE_HANDLER( dl1416_ce_w )
186{
187   dl1416_state *chip = get_safe_token(device);
188   chip->chip_enable = !state;
189}
190
191/* cursor enable, active low */
192WRITE_LINE_DEVICE_HANDLER( dl1416_cu_w )
193{
194   dl1416_state *chip = get_safe_token(device);
195   chip->cursor_enable = !state;
196}
197
198/* data */
199WRITE8_DEVICE_HANDLER( dl1416_data_w )
200{
201   dl1416_state *chip = get_safe_token(device);
202   const dl1416_interface *intf = (const dl1416_interface *)device->static_config();
203
204   offset &= 0x03; /* A0-A1 */
205   data &= 0x7f;   /* D0-D6 */
206
207   /* Only try to update the data if we are enabled and write is enabled */
208   if (chip->chip_enable && chip->write_enable)
209   {
210      /* fprintf(stderr,"DL1416 Write: Cursor: %d, Offset: %d, Data: %02X\n (%c)", chip->cursor_enable, offset, data, data); */
211      int i, pattern, previous_state;
212
213      if (chip->cursor_enable) /* cursor enable is set */
214      {
215         if (device->type() == DL1416B)
216         {
217            /* DL1416B uses offset to decide cursor pos to change and D0 to hold new state */
218
219            /* The cursor will be set if D0 is high and the original */
220            /* character restored otherwise */
221            previous_state = chip->cursor_state[offset];
222            chip->cursor_state[offset] = data & 1 ? CURSOR_ON : CURSOR_OFF;
223
224            if (previous_state != chip->cursor_state[offset])
225            {
226               pattern = dl1416t_segments[chip->digit_ram[offset]];
227
228               /* If cursor for this digit position is enabled and segment is not */
229               /* undefined, replace digit with cursor */
230               if ((chip->cursor_state[offset] == CURSOR_ON) && (pattern != SEG_UNDEF))
231                  pattern = SEG_CURSOR;
232
233               /* Undefined characters are replaced by blanks */
234               if (pattern == SEG_UNDEF)
235                  pattern = SEG_BLANK;
236
237               /* Call update function */
238               if (intf->update)
239                  intf->update(device, offset, pattern);
240            }
241         }
242         else {
243         /* DL1416T uses a bitmap of 4 data bits D0,D1,D2,D3 to decide cursor pos to change and new state */
244
245            for (i = 0; i < 4; i++)
246            {
247               /* The cursor will be set if D0-D3 is high and the original */
248               /* character at the appropriate position restored otherwise */
249               previous_state = chip->cursor_state[i];
250               chip->cursor_state[i] = data & (1<<i) ? CURSOR_ON : CURSOR_OFF;
251
252               if (previous_state != chip->cursor_state[i])
253               {
254                  pattern = dl1416t_segments[chip->digit_ram[i]];
255
256                  /* If cursor for this digit position is enabled and segment is not */
257                  /* undefined, replace digit with cursor */
258                  if ((chip->cursor_state[i] == CURSOR_ON) && (pattern != SEG_UNDEF))
259                     pattern = SEG_CURSOR;
260
261                  /* Undefined characters are replaced by blanks */
262                  if (pattern == SEG_UNDEF)
263                     pattern = SEG_BLANK;
264
265                  /* Call update function */
266                  if (intf->update)
267                     intf->update(device, i, pattern);
268               }
269            }
270         }
271      }
272      else /* cursor enable is not set, so standard write */
273      {
274         /* Save written value */
275         chip->digit_ram[offset] = data&0x3f;
276
277         /* Load segment pattern from ROM */
278         pattern = dl1416t_segments[data]; /** TODO: handle DL1416T vs DL1416B vs DL1414 here */
279
280         /* If cursor for this digit position is enabled and segment is not */
281         /* undefined, replace digit with cursor */
282         if ((chip->cursor_state[offset] == CURSOR_ON) && (pattern != SEG_UNDEF))
283            pattern = SEG_CURSOR;
284
285         /* Undefined characters are replaced by blanks */
286         if (pattern == SEG_UNDEF)
287            pattern = SEG_BLANK;
288
289         /* Call update function */
290         if (intf->update)
291            intf->update(device, offset, pattern);
292      }
293   }
294}
295
296dl1416_device::dl1416_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
297   : device_t(mconfig, type, name, tag, owner, clock)
298{
299   m_token = global_alloc_clear(dl1416_state);
300}
301
302//-------------------------------------------------
303//  device_config_complete - perform any
304//  operations now that the configuration is
305//  complete
306//-------------------------------------------------
307
308void dl1416_device::device_config_complete()
309{
310}
311
312//-------------------------------------------------
313//  device_start - device-specific startup
314//-------------------------------------------------
315
316void dl1416_device::device_start()
317{
318   DEVICE_START_NAME( dl1416 )(this);
319}
320
321//-------------------------------------------------
322//  device_reset - device-specific reset
323//-------------------------------------------------
324
325void dl1416_device::device_reset()
326{
327   DEVICE_RESET_NAME( dl1416 )(this);
328}
329
330
331const device_type DL1416B = &device_creator<dl1416b_device>;
332
333dl1416b_device::dl1416b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
334   : dl1416_device(mconfig, DL1416B, "DL1416B", tag, owner, clock)
335{
336}
337
338
339const device_type DL1416T = &device_creator<dl1416t_device>;
340
341dl1416t_device::dl1416t_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
342   : dl1416_device(mconfig, DL1416T, "DL1416T", tag, owner, clock)
343{
344}
trunk/src/mess/video/dl1416.h
r21684r21685
1/*****************************************************************************
2 *
3 * video/dl1416.h
4 *
5 * DL1416
6 *
7 * 4-Digit 16-Segment Alphanumeric Intelligent Display
8 * with Memory/Decoder/Driver
9 *
10 * See video/dl1416.c for more info
11 *
12 ****************************************************************************/
13
14#ifndef DL1416_H_
15#define DL1416_H_
16
17#include "devcb.h"
18
19/***************************************************************************
20    TYPE DEFINITIONS
21***************************************************************************/
22
23typedef void (*dl1416_update_func)(device_t *device, int digit, int data);
24
25struct dl1416_interface
26{
27   dl1416_update_func update;
28};
29
30
31/***************************************************************************
32    DEVICE CONFIGURATION MACROS
33***************************************************************************/
34
35#define MCFG_DL1416B_ADD(_tag, _config) \
36   MCFG_DEVICE_ADD(_tag, DL1416B, 0) \
37   MCFG_DEVICE_CONFIG(_config)
38
39#define MCFG_DL1416T_ADD(_tag, _config) \
40   MCFG_DEVICE_ADD(_tag, DL1416T, 0) \
41   MCFG_DEVICE_CONFIG(_config)
42
43
44/***************************************************************************
45    FUNCTION PROTOTYPES
46***************************************************************************/
47
48/* inputs */
49WRITE_LINE_DEVICE_HANDLER( dl1416_wr_w ); /* write enable */
50WRITE_LINE_DEVICE_HANDLER( dl1416_ce_w ); /* chip enable */
51WRITE_LINE_DEVICE_HANDLER( dl1416_cu_w ); /* cursor enable */
52DECLARE_WRITE8_DEVICE_HANDLER( dl1416_data_w );
53
54/* device get info callback */
55class dl1416_device : public device_t
56{
57public:
58   dl1416_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
59   ~dl1416_device() { global_free(m_token); }
60
61   // access to legacy token
62   void *token() const { assert(m_token != NULL); return m_token; }
63protected:
64   // device-level overrides
65   virtual void device_config_complete();
66   virtual void device_start();
67   virtual void device_reset();
68private:
69   // internal state
70   void *m_token;
71};
72
73class dl1416b_device : public dl1416_device
74{
75public:
76   dl1416b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
77};
78
79extern const device_type DL1416B;
80
81class dl1416t_device : public dl1416_device
82{
83public:
84   dl1416t_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
85};
86
87extern const device_type DL1416T;
88
89
90#endif /* DL1416_H_ */
trunk/src/mess/video/upd7220.c
r21684r21685
1/**********************************************************************
2
3    Intel 82720 Graphics Display Controller emulation
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10/*
11
12    TODO:
13
14    - implement FIFO as ring buffer
15    - commands
16        - DMAR
17        - DMAW
18    - incomplete / unimplemented FIGD / GCHRD draw modes
19        - Arc
20        - FIGD character
21        - slanted character
22        - GCHRD character (needs rewrite)
23    - read-modify-write cycle
24        - read data
25        - modify data
26        - write data
27    - QX-10 diagnostic test has positioning bugs with the bitmap display test;
28    - QX-10 diagnostic test misses the zooming factor (external pin);
29    - compis2 SAD address for bitmap is 0x20000 for whatever reason (presumably missing banking);
30    - A5105 has a FIFO bug with the RDAT, should be a lot larger when it scrolls up.
31      The problem is that DMA-ing with RDAT/WDAT shouldn't be instant;
32
33    - honor visible area
34    - wide mode (32-bit access)
35    - light pen
36
37*/
38
39#include "emu.h"
40#include "upd7220.h"
41
42
43
44//**************************************************************************
45//  MACROS / CONSTANTS
46//**************************************************************************
47
48#define VERBOSE         0
49#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
50
51
52// todo typedef
53enum
54{
55   COMMAND_INVALID = -1,
56   COMMAND_RESET,
57   COMMAND_SYNC,
58   COMMAND_VSYNC,
59   COMMAND_CCHAR,
60   COMMAND_START,
61   COMMAND_BCTRL,
62   COMMAND_ZOOM,
63   COMMAND_CURS,
64   COMMAND_PRAM,
65   COMMAND_PITCH,
66   COMMAND_WDAT,
67   COMMAND_MASK,
68   COMMAND_FIGS,
69   COMMAND_FIGD,
70   COMMAND_GCHRD,
71   COMMAND_RDAT,
72   COMMAND_CURD,
73   COMMAND_LPRD,
74   COMMAND_DMAR,
75   COMMAND_DMAW,
76   COMMAND_5A
77};
78
79enum
80{
81   FIFO_READ = 0,
82   FIFO_WRITE
83};
84
85enum
86{
87   FIFO_EMPTY = -1,
88   FIFO_PARAMETER,
89   FIFO_COMMAND
90};
91
92#define UPD7220_COMMAND_RESET           0x00
93#define UPD7220_COMMAND_SYNC            0x0e // & 0xfe
94#define UPD7220_COMMAND_VSYNC           0x6e // & 0xfe
95#define UPD7220_COMMAND_CCHAR           0x4b
96#define UPD7220_COMMAND_START           0x6b
97#define UPD7220_COMMAND_BCTRL           0x0c // & 0xfe
98#define UPD7220_COMMAND_ZOOM            0x46
99#define UPD7220_COMMAND_CURS            0x49
100#define UPD7220_COMMAND_PRAM            0x70 // & 0xf0
101#define UPD7220_COMMAND_PITCH           0x47
102#define UPD7220_COMMAND_WDAT            0x20 // & 0xe4
103#define UPD7220_COMMAND_MASK            0x4a
104#define UPD7220_COMMAND_FIGS            0x4c
105#define UPD7220_COMMAND_FIGD            0x6c
106#define UPD7220_COMMAND_GCHRD           0x68
107#define UPD7220_COMMAND_RDAT            0xa0 // & 0xe4
108#define UPD7220_COMMAND_CURD            0xe0
109#define UPD7220_COMMAND_LPRD            0xc0
110#define UPD7220_COMMAND_DMAR            0xa4 // & 0xe4
111#define UPD7220_COMMAND_DMAW            0x24 // & 0xe4
112#define UPD7220_COMMAND_5A              0x5a
113
114#define UPD7220_SR_DATA_READY           0x01
115#define UPD7220_SR_FIFO_FULL            0x02
116#define UPD7220_SR_FIFO_EMPTY           0x04
117#define UPD7220_SR_DRAWING_IN_PROGRESS  0x08
118#define UPD7220_SR_DMA_EXECUTE          0x10
119#define UPD7220_SR_VSYNC_ACTIVE         0x20
120#define UPD7220_SR_HBLANK_ACTIVE        0x40
121#define UPD7220_SR_LIGHT_PEN_DETECT     0x80
122
123#define UPD7220_MODE_S                  0x01
124#define UPD7220_MODE_REFRESH_RAM        0x04
125#define UPD7220_MODE_I                  0x08
126#define UPD7220_MODE_DRAW_ON_RETRACE    0x10
127#define UPD7220_MODE_DISPLAY_MASK       0x22
128#define UPD7220_MODE_DISPLAY_MIXED      0x00
129#define UPD7220_MODE_DISPLAY_GRAPHICS   0x02
130#define UPD7220_MODE_DISPLAY_CHARACTER  0x20
131#define UPD7220_MODE_DISPLAY_INVALID    0x22
132
133static const int x_dir[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
134static const int y_dir[8] = { 1, 1, 0,-1,-1,-1, 0, 1};
135static const int x_dir_dot[8] = { 1, 1, 0,-1,-1,-1, 0, 1};
136static const int y_dir_dot[8] = { 0,-1,-1,-1, 0, 1, 1, 1};
137
138
139
140//**************************************************************************
141//  GLOBAL VARIABLES
142//**************************************************************************
143
144// devices
145const device_type UPD7220 = &device_creator<upd7220_device>;
146
147
148// default address map
149static ADDRESS_MAP_START( upd7220_vram, AS_0, 8, upd7220_device )
150   AM_RANGE(0x00000, 0x3ffff) AM_RAM
151ADDRESS_MAP_END
152
153
154// internal 128x14 control ROM
155ROM_START( upd7220 )
156   ROM_REGION( 0x100, "upd7220", 0 )
157   ROM_LOAD( "upd7220.bin", 0x000, 0x100, NO_DUMP )
158ROM_END
159
160
161//-------------------------------------------------
162//  memory_space_config - return a description of
163//  any address spaces owned by this device
164//-------------------------------------------------
165
166const address_space_config *upd7220_device::memory_space_config(address_spacenum spacenum) const
167{
168   return (spacenum == AS_0) ? &m_space_config : NULL;
169}
170
171
172//-------------------------------------------------
173//  rom_region - device-specific ROM region
174//-------------------------------------------------
175
176const rom_entry *upd7220_device::device_rom_region() const
177{
178   return ROM_NAME( upd7220 );
179}
180
181
182//-------------------------------------------------
183//  device_config_complete - perform any
184//  operations now that the configuration is
185//  complete
186//-------------------------------------------------
187
188void upd7220_device::device_config_complete()
189{
190   // inherit a copy of the static data
191   const upd7220_interface *intf = reinterpret_cast<const upd7220_interface *>(static_config());
192   if (intf != NULL)
193      *static_cast<upd7220_interface *>(this) = *intf;
194
195   // or initialize to defaults if none provided
196   else
197   {
198      memset(&m_out_drq_cb, 0, sizeof(m_out_drq_cb));
199      memset(&m_out_hsync_cb, 0, sizeof(m_out_hsync_cb));
200      memset(&m_out_vsync_cb, 0, sizeof(m_out_vsync_cb));
201      memset(&m_out_blank_cb, 0, sizeof(m_out_blank_cb));
202   }
203}
204
205
206
207//**************************************************************************
208//  INLINE HELPERS
209//**************************************************************************
210
211//-------------------------------------------------
212//  readbyte - read a byte at the given address
213//-------------------------------------------------
214
215inline UINT8 upd7220_device::readbyte(offs_t address)
216{
217   return space().read_byte(address);
218}
219
220
221//-------------------------------------------------
222//  writebyte - write a byte at the given address
223//-------------------------------------------------
224
225inline void upd7220_device::writebyte(offs_t address, UINT8 data)
226{
227   space().write_byte(address, data);
228}
229
230
231//-------------------------------------------------
232//  fifo_clear -
233//-------------------------------------------------
234
235inline void upd7220_device::fifo_clear()
236{
237   for (int i = 0; i < 16; i++)
238   {
239      m_fifo[i] = 0;
240      m_fifo_flag[i] = FIFO_EMPTY;
241   }
242
243   m_fifo_ptr = -1;
244
245   m_sr &= ~UPD7220_SR_DATA_READY;
246   m_sr |= UPD7220_SR_FIFO_EMPTY;
247   m_sr &= ~UPD7220_SR_FIFO_FULL;
248}
249
250
251//-------------------------------------------------
252//  fifo_param_count -
253//-------------------------------------------------
254
255inline int upd7220_device::fifo_param_count()
256{
257   int i;
258
259   for (i = 0; i < 16; i++)
260   {
261      if (m_fifo_flag[i] != FIFO_PARAMETER) break;
262   }
263
264   return i;
265}
266
267
268//-------------------------------------------------
269//  fifo_set_direction -
270//-------------------------------------------------
271
272inline void upd7220_device::fifo_set_direction(int dir)
273{
274   if (m_fifo_dir != dir)
275   {
276      fifo_clear();
277   }
278
279   m_fifo_dir = dir;
280}
281
282
283//-------------------------------------------------
284//  queue -
285//-------------------------------------------------
286
287inline void upd7220_device::queue(UINT8 data, int flag)
288{
289   if (m_fifo_ptr < 15)
290   {
291      m_fifo_ptr++;
292
293      m_fifo[m_fifo_ptr] = data;
294      m_fifo_flag[m_fifo_ptr] = flag;
295
296      if (m_fifo_ptr == 16)
297      {
298         m_sr |= UPD7220_SR_FIFO_FULL;
299      }
300
301      m_sr &= ~UPD7220_SR_FIFO_EMPTY;
302   }
303   else
304   {
305      // TODO what happen? somebody set us up the bomb
306      printf("FIFO?\n");
307   }
308}
309
310
311//-------------------------------------------------
312//  dequeue -
313//-------------------------------------------------
314
315inline void upd7220_device::dequeue(UINT8 *data, int *flag)
316{
317   *data = m_fifo[0];
318   *flag = m_fifo_flag[0];
319
320   if (m_fifo_ptr > -1)
321   {
322      for (int i = 0; i < 15; i++)
323      {
324         m_fifo[i] = m_fifo[i + 1];
325         m_fifo_flag[i] = m_fifo_flag[i + 1];
326      }
327
328      m_fifo[15] = 0;
329      m_fifo_flag[15] = 0;
330
331      m_fifo_ptr--;
332
333      if (m_fifo_ptr == -1)
334      {
335         m_sr &= ~UPD7220_SR_DATA_READY;
336         m_sr |= UPD7220_SR_FIFO_EMPTY;
337      }
338   }
339}
340
341
342//-------------------------------------------------
343//  update_vsync_timer -
344//-------------------------------------------------
345
346inline void upd7220_device::update_vsync_timer(int state)
347{
348   int next_y = state ? m_vs : 0;
349
350   attotime duration = m_screen->time_until_pos(next_y, 0);
351
352   m_vsync_timer->adjust(duration, !state);
353}
354
355
356//-------------------------------------------------
357//  update_hsync_timer -
358//-------------------------------------------------
359
360inline void upd7220_device::update_hsync_timer(int state)
361{
362   int y = m_screen->vpos();
363
364   int next_x = state ? m_hs : 0;
365   int next_y = state ? y : ((y + 1) % m_al);
366
367   attotime duration = m_screen->time_until_pos(next_y, next_x);
368
369   m_hsync_timer->adjust(duration, !state);
370}
371
372
373//-------------------------------------------------
374//  update_blank_timer -
375//-------------------------------------------------
376
377inline void upd7220_device::update_blank_timer(int state)
378{
379   int y = m_screen->vpos();
380
381   int next_x = state ? (m_hs + m_hbp) : (m_hs + m_hbp + (m_aw << 3));
382   int next_y = state ? ((y + 1) % (m_vs + m_vbp + m_al + m_vfp - 1)) : y;
383
384   attotime duration = m_screen->time_until_pos(next_y, next_x);
385
386   m_hsync_timer->adjust(duration, !state);
387}
388
389
390//-------------------------------------------------
391//  recompute_parameters -
392//-------------------------------------------------
393
394inline void upd7220_device::recompute_parameters()
395{
396   /* TODO: assume that the pitch also controls number of horizontal pixels in a single cell */
397   int horiz_mult = ((m_pitch == 40) ? 16 : 8);
398   int horiz_pix_total = (m_hs + m_hbp + m_aw + m_hfp) * horiz_mult;
399   int vert_pix_total = m_vs + m_vbp + m_al + m_vfp;
400
401   //printf("%d %d %d %d\n",m_hs,m_hbp,m_aw,m_hfp);
402   //printf("%d %d\n",m_aw * 8,m_pitch * 8);
403
404   if (horiz_pix_total == 0 || vert_pix_total == 0) //bail out if screen params aren't valid
405      return;
406
407   attoseconds_t refresh = HZ_TO_ATTOSECONDS(clock() * horiz_mult) * horiz_pix_total * vert_pix_total;
408
409   rectangle visarea;
410
411   visarea.min_x = 0; //(m_hs + m_hbp) * 8;
412   visarea.min_y = 0; //m_vs + m_vbp;
413   visarea.max_x = m_aw * horiz_mult - 1;//horiz_pix_total - (m_hfp * 8) - 1;
414   visarea.max_y = m_al - 1;//vert_pix_total - m_vfp - 1;
415
416   LOG(("uPD7220 '%s' Screen: %u x %u @ %f Hz\n", tag(), horiz_pix_total, vert_pix_total, 1 / ATTOSECONDS_TO_DOUBLE(refresh)));
417   LOG(("Visible Area: (%u, %u) - (%u, %u)\n", visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y));
418   LOG(("%d %d %d %d %d\n",m_hs,m_hbp,m_aw,m_hfp,m_pitch));
419   LOG(("%d %d %d %d\n",m_vs,m_vbp,m_al,m_vfp));
420
421   if (m_m)
422   {
423      m_screen->configure(horiz_pix_total, vert_pix_total, visarea, refresh);
424
425      update_hsync_timer(0);
426      update_vsync_timer(0);
427   }
428   else
429   {
430      m_hsync_timer->enable(0);
431      m_vsync_timer->enable(0);
432   }
433
434   update_blank_timer(0);
435}
436
437
438//-------------------------------------------------
439//  reset_figs_param -
440//-------------------------------------------------
441
442inline void upd7220_device::reset_figs_param()
443{
444   m_figs.m_dc = 0x0000;
445   m_figs.m_d = 0x0008;
446   m_figs.m_d1 = 0x0008;
447   m_figs.m_d2 = 0x0000;
448   m_figs.m_dm = 0x0000;
449}
450
451
452//-------------------------------------------------
453//  advance_ead -
454//-------------------------------------------------
455
456inline void upd7220_device::advance_ead()
457{
458   #define EAD         m_ead
459   #define DAD         m_dad
460   #define P           x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch)
461   #define MSB(value)  (BIT(value, 15))
462   #define LSB(value)  (BIT(value, 0))
463   #define LR(value)   ((value << 1) | MSB(value))
464   #define RR(value)   ((LSB(value) << 15) | (value >> 1))
465
466   switch (m_draw_mode & 0x07)
467   {
468   case 0:
469      EAD += P;
470      break;
471
472   case 1:
473      EAD += P;
474      if (MSB(DAD)) EAD++;
475      DAD = LR(DAD);
476      break;
477
478   case 2:
479      if (MSB(DAD)) EAD++;
480      DAD = LR(DAD);
481      break;
482
483   case 3:
484      EAD -= P;
485      if (MSB(DAD)) EAD++;
486      DAD = LR(DAD);
487      break;
488
489   case 4:
490      EAD -= P;
491      break;
492
493   case 5:
494      EAD -= P;
495      if (LSB(DAD)) EAD--;
496      DAD = RR(DAD);
497      break;
498
499   case 6:
500      if (LSB(DAD)) EAD--;
501      DAD = RR(DAD);
502      break;
503
504   case 7:
505      EAD += P;
506      if (LSB(DAD)) EAD--;
507      DAD = RR(DAD);
508      break;
509   }
510
511   EAD &= 0x3ffff;
512}
513
514
515//-------------------------------------------------
516//  read_vram -
517//-------------------------------------------------
518
519inline void upd7220_device::read_vram(UINT8 type, UINT8 mod)
520{
521   if (type == 1)
522   {
523      LOG (("uPD7220 invalid type 1 RDAT parameter\n"));
524      return;
525   }
526
527   if (mod)
528      LOG (("uPD7220 RDAT used with mod = %02x?\n",mod));
529
530   for (int i = 0; i < m_figs.m_dc; i++)
531   {
532      switch(type)
533      {
534         case 0:
535            queue(readbyte(m_ead*2), 0);
536            queue(readbyte(m_ead*2+1), 0);
537            break;
538         case 2:
539            queue(readbyte(m_ead*2), 0);
540            break;
541         case 3:
542            queue(readbyte(m_ead*2+1), 0);
543            break;
544      }
545
546      advance_ead();
547   }
548}
549
550
551//-------------------------------------------------
552//  write_vram -
553//-------------------------------------------------
554
555inline void upd7220_device::write_vram(UINT8 type, UINT8 mod)
556{
557   UINT16 result;
558
559   if (type == 1)
560   {
561      printf("uPD7220 invalid type 1 WDAT parameter\n");
562      return;
563   }
564
565   result = 0;
566
567   switch(type)
568   {
569      case 0:
570         result = (m_pr[1] & 0xff);
571         result |= (m_pr[2] << 8);
572         result &= m_mask;
573         break;
574      case 2:
575         result = (m_pr[1] & 0xff);
576         result &= (m_mask & 0xff);
577         break;
578      case 3:
579         result = (m_pr[1] << 8);
580         result &= (m_mask & 0xff00);
581         break;
582   }
583
584   //if(result)
585   {
586      //printf("%04x %02x %02x %04x %02x %02x\n",readbyte(m_ead),m_pr[1],m_pr[2],m_mask,type,mod);
587      //printf("%04x %02x %02x\n",m_ead,m_figs.m_dir,m_pitch);
588      //printf("%04x %04x %02x %04x\n",m_ead,result,mod,m_figs.m_dc);
589   }
590
591   for(int i = 0; i < m_figs.m_dc + 1; i++)
592   {
593      switch(mod & 3)
594      {
595         case 0x00: //replace
596            if(type == 0 || type == 2)
597               writebyte(m_ead*2+0, result & 0xff);
598            if(type == 0 || type == 3)
599               writebyte(m_ead*2+1, result >> 8);
600            break;
601         case 0x01: //complement
602            if(type == 0 || type == 2)
603               writebyte(m_ead*2+0, readbyte(m_ead*2+0) ^ (result & 0xff));
604            if(type == 0 || type == 3)
605               writebyte(m_ead*2+1, readbyte(m_ead*2+1) ^ (result >> 8));
606            break;
607         case 0x02: //reset to zero
608            if(type == 0 || type == 2)
609               writebyte(m_ead*2+0, readbyte(m_ead*2+0) & ~(result & 0xff));
610            if(type == 0 || type == 3)
611               writebyte(m_ead*2+1, readbyte(m_ead*2+1) & ~(result >> 8));
612            break;
613         case 0x03: //set to one
614            if(type == 0 || type == 2)
615               writebyte(m_ead*2+0, readbyte(m_ead*2+0) | (result & 0xff));
616            if(type == 0 || type == 3)
617               writebyte(m_ead*2+1, readbyte(m_ead*2+1) | (result >> 8));
618            break;
619      }
620
621      advance_ead();
622   }
623}
624
625
626//-------------------------------------------------
627//  check_pattern -
628//-------------------------------------------------
629
630inline UINT16 upd7220_device::check_pattern(UINT16 pattern)
631{
632   UINT16 res = 0;
633
634   switch (m_bitmap_mod & 3)
635   {
636      case 0: res = pattern; break; //replace
637      case 1: res = pattern; break; //complement
638      case 2: res = 0; break; //reset to zero
639      case 3: res |= 0xffff; break; //set to one
640   }
641
642   return res;
643}
644
645
646//-------------------------------------------------
647//  get_text_partition -
648//-------------------------------------------------
649
650inline void upd7220_device::get_text_partition(int index, UINT32 *sad, UINT16 *len, int *im, int *wd)
651{
652   *sad = ((m_ra[(index * 4) + 1] & 0x1f) << 8) | m_ra[(index * 4) + 0];
653   *len = ((m_ra[(index * 4) + 3] & 0x3f) << 4) | (m_ra[(index * 4) + 2] >> 4);
654   *im = BIT(m_ra[(index * 4) + 3], 6);
655   *wd = BIT(m_ra[(index * 4) + 3], 7);
656}
657
658
659//-------------------------------------------------
660//  get_graphics_partition -
661//-------------------------------------------------
662
663inline void upd7220_device::get_graphics_partition(int index, UINT32 *sad, UINT16 *len, int *im, int *wd)
664{
665   *sad = ((m_ra[(index * 4) + 2] & 0x03) << 16) | (m_ra[(index * 4) + 1] << 8) | m_ra[(index * 4) + 0];
666   *len = ((m_ra[(index * 4) + 3] & 0x3f) << 4) | (m_ra[(index * 4) + 2] >> 4);
667   *im = BIT(m_ra[(index * 4) + 3], 6);
668   *wd = BIT(m_ra[(index * 4) + 3], 7);
669}
670
671
672
673//**************************************************************************
674//  LIVE DEVICE
675//**************************************************************************
676
677//-------------------------------------------------
678//  upd7220_device - constructor
679//-------------------------------------------------
680
681upd7220_device::upd7220_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
682   : device_t(mconfig, UPD7220, "uPD7220", tag, owner, clock),
683      device_memory_interface(mconfig, *this),
684      m_mask(0),
685      m_pitch(0),
686      m_ead(0),
687      m_dad(0),
688      m_lad(0),
689      m_ra_addr(0),
690      m_sr(UPD7220_SR_FIFO_EMPTY),
691      m_cr(0),
692      m_param_ptr(0),
693      m_fifo_ptr(-1),
694      m_fifo_dir(0),
695      m_mode(0),
696      m_draw_mode(0),
697      m_de(0),
698      m_m(0),
699      m_aw(0),
700      m_al(0),
701      m_vs(0),
702      m_vfp(0),
703      m_vbp(0),
704      m_hs(0),
705      m_hfp(0),
706      m_hbp(0),
707      m_dc(0),
708      m_sc(0),
709      m_br(0),
710      m_ctop(0),
711      m_cbot(0),
712      m_lr(0),
713      m_disp(0),
714      m_gchr(0),
715      m_bitmap_mod(0),
716      m_space_config("videoram", ENDIANNESS_LITTLE, 8, 18, 0, NULL, *ADDRESS_MAP_NAME(upd7220_vram))
717{
718   m_shortname = "upd7220";
719   for (int i = 0; i < 16; i++)
720   {
721      m_fifo[i] = 0;
722      m_fifo_flag[i] = FIFO_EMPTY;
723
724      m_ra[i] = 0;
725   }
726
727   for (int i = 0; i < 17; i++)
728   {
729      m_pr[i] = 0;
730   }
731
732   m_figs.m_dir = 0;
733   m_figs.m_figure_type = 0;
734   m_figs.m_dc = 0;
735   m_figs.m_d = 0;
736   m_figs.m_d1 = 0;
737   m_figs.m_d2 = 0;
738   m_figs.m_dm = 0;
739}
740
741
742//-------------------------------------------------
743//  device_start - device-specific startup
744//-------------------------------------------------
745
746void upd7220_device::device_start()
747{
748   // allocate timers
749   m_vsync_timer = timer_alloc(TIMER_VSYNC);
750   m_hsync_timer = timer_alloc(TIMER_HSYNC);
751   m_blank_timer = timer_alloc(TIMER_BLANK);
752
753   // resolve callbacks
754   m_out_drq_func.resolve(m_out_drq_cb, *this);
755   m_out_hsync_func.resolve(m_out_hsync_cb, *this);
756   m_out_vsync_func.resolve(m_out_vsync_cb, *this);
757   m_out_blank_func.resolve(m_out_blank_cb, *this);
758
759   // find screen
760   m_screen = machine().device<screen_device>(m_screen_tag);
761
762   if (m_screen == NULL)
763   {
764      m_screen = owner()->subdevice<screen_device>(m_screen_tag);
765   }
766
767   assert(m_screen);
768
769   // register for state saving
770   save_item(NAME(m_ra));
771   save_item(NAME(m_sr));
772   save_item(NAME(m_mode));
773   save_item(NAME(m_de));
774   save_item(NAME(m_aw));
775   save_item(NAME(m_al));
776   save_item(NAME(m_vs));
777   save_item(NAME(m_vfp));
778   save_item(NAME(m_vbp));
779   save_item(NAME(m_hs));
780   save_item(NAME(m_hfp));
781   save_item(NAME(m_hbp));
782   save_item(NAME(m_m));
783   save_item(NAME(m_dc));
784   save_item(NAME(m_sc));
785   save_item(NAME(m_br));
786   save_item(NAME(m_lr));
787   save_item(NAME(m_ctop));
788   save_item(NAME(m_cbot));
789   save_item(NAME(m_ead));
790   save_item(NAME(m_dad));
791   save_item(NAME(m_lad));
792   save_item(NAME(m_disp));
793   save_item(NAME(m_gchr));
794   save_item(NAME(m_mask));
795   save_item(NAME(m_pitch));
796}
797
798
799//-------------------------------------------------
800//  device_reset - device-specific reset
801//-------------------------------------------------
802
803void upd7220_device::device_reset()
804{
805   m_out_drq_func(CLEAR_LINE);
806}
807
808
809//-------------------------------------------------
810//  device_timer - handler timer events
811//-------------------------------------------------
812
813void upd7220_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
814{
815   switch (id)
816   {
817   case TIMER_HSYNC:
818      if (param)
819      {
820         m_sr |= UPD7220_SR_HBLANK_ACTIVE;
821      }
822      else
823      {
824         m_sr &= ~UPD7220_SR_HBLANK_ACTIVE;
825      }
826
827      m_out_hsync_func(param);
828
829      update_hsync_timer(param);
830      break;
831
832   case TIMER_VSYNC:
833      if (param)
834      {
835         m_sr |= UPD7220_SR_VSYNC_ACTIVE;
836      }
837      else
838      {
839         m_sr &= ~UPD7220_SR_VSYNC_ACTIVE;
840      }
841
842      m_out_vsync_func(param);
843
844      update_vsync_timer(param);
845      break;
846
847   case TIMER_BLANK:
848      if (param)
849      {
850         m_sr |= UPD7220_SR_HBLANK_ACTIVE;
851      }
852      else
853      {
854         m_sr &= ~UPD7220_SR_HBLANK_ACTIVE;
855      }
856
857      m_out_blank_func(param);
858
859      update_blank_timer(param);
860      break;
861   }
862}
863
864
865//-------------------------------------------------
866//  draw_pixel -
867//-------------------------------------------------
868
869void upd7220_device::draw_pixel(int x, int y, UINT8 tile_data)
870{
871   UINT32 addr = (y * m_pitch * 2 + (x >> 3)) & 0x3ffff;
872   int dad = x & 0x7;
873   UINT8 data = readbyte(addr);
874   UINT8 new_pixel = (tile_data) & (0x80 >> (dad));
875
876   switch(m_bitmap_mod)
877   {
878      case 0: //replace
879         writebyte(addr, data & ~(0x80 >> (dad)));
880         writebyte(addr, data | new_pixel);
881         break;
882      case 1: //complement
883         writebyte(addr, data ^ (new_pixel));
884         break;
885      case 2: //reset
886         writebyte(addr, data & ((new_pixel) ? 0xff : ~(0x80 >> (dad))));
887         break;
888      case 3: //set
889         writebyte(addr, data | new_pixel);
890         break;
891   }
892}
893
894
895//-------------------------------------------------
896//  draw_line -
897//-------------------------------------------------
898
899void upd7220_device::draw_line(int x, int y)
900{
901   int line_size,i;
902   const int line_x_dir[8] = { 0, 1, 1, 0, 0,-1,-1, 0};
903   const int line_y_dir[8] = { 1, 0, 0,-1,-1, 0, 0, 1};
904   const int line_x_step[8] = { 1, 0, 0, 1,-1, 0, 0,-1 };
905   const int line_y_step[8] = { 0, 1,-1, 0, 0,-1, 1, 0 };
906   UINT16 line_pattern;
907   int line_step = 0;
908   UINT8 dot;
909
910   line_size = m_figs.m_dc + 1;
911   line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8));
912
913   for(i = 0;i<line_size;i++)
914   {
915      line_step = (m_figs.m_d1 * i);
916      line_step/= (m_figs.m_dc + 1);
917      line_step >>= 1;
918      dot = ((line_pattern >> (i & 0xf)) & 1) << 7;
919      draw_pixel(x + (line_step*line_x_step[m_figs.m_dir]),y + (line_step*line_y_step[m_figs.m_dir]),dot >> ((x + line_step*line_x_step[m_figs.m_dir]) & 0x7));
920      x += line_x_dir[m_figs.m_dir];
921      y += line_y_dir[m_figs.m_dir];
922   }
923
924   /* TODO: check me*/
925   x += (line_step*line_x_step[m_figs.m_dir]);
926   y += (line_step*line_y_step[m_figs.m_dir]);
927
928   m_ead = (x >> 4) + (y * m_pitch);
929   m_dad = x & 0x0f;
930}
931
932
933//-------------------------------------------------
934//  draw_rectangle -
935//-------------------------------------------------
936
937void upd7220_device::draw_rectangle(int x, int y)
938{
939   int i;
940   const int rect_x_dir[8] = { 0, 1, 0,-1, 1, 1,-1,-1 };
941   const int rect_y_dir[8] = { 1, 0,-1, 0, 1,-1,-1, 1 };
942   UINT8 rect_type,rect_dir;
943   UINT16 line_pattern;
944   UINT8 dot;
945
946   LOG(("uPD7220 rectangle check: %d %d %02x %08x\n",x,y,m_figs.m_dir,m_ead));
947
948   line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8));
949   rect_type = (m_figs.m_dir & 1) << 2;
950   rect_dir = rect_type | (((m_figs.m_dir >> 1) + 0) & 3);
951
952   for(i = 0;i < m_figs.m_d;i++)
953   {
954      dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
955      draw_pixel(x,y,dot >> (x & 0x7));
956      x+=rect_x_dir[rect_dir];
957      y+=rect_y_dir[rect_dir];
958   }
959
960   rect_dir = rect_type | (((m_figs.m_dir >> 1) + 1) & 3);
961
962   for(i = 0;i < m_figs.m_d2;i++)
963   {
964      dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
965      draw_pixel(x,y,dot >> (x & 0x7));
966      x+=rect_x_dir[rect_dir];
967      y+=rect_y_dir[rect_dir];
968   }
969
970   rect_dir = rect_type | (((m_figs.m_dir >> 1) + 2) & 3);
971
972   for(i = 0;i < m_figs.m_d;i++)
973   {
974      dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
975      draw_pixel(x,y,dot >> (x & 0x7));
976      x+=rect_x_dir[rect_dir];
977      y+=rect_y_dir[rect_dir];
978   }
979
980   rect_dir = rect_type | (((m_figs.m_dir >> 1) + 3) & 3);
981
982   for(i = 0;i < m_figs.m_d2;i++)
983   {
984      dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7;
985      draw_pixel(x,y,dot >> (x & 0x7));
986      x+=rect_x_dir[rect_dir];
987      y+=rect_y_dir[rect_dir];
988   }
989
990   m_ead = (x >> 4) + (y * m_pitch);
991   m_dad = x & 0x0f;
992
993}
994
995
996//-------------------------------------------------
997//  draw_char -
998//-------------------------------------------------
999
1000void upd7220_device::draw_char(int x, int y)
1001{
1002   int xi,yi;
1003   int xsize,ysize;
1004   UINT8 tile_data;
1005
1006   /* snippet for character checking */
1007   #if 0
1008   for(yi=0;yi<8;yi++)
1009   {
1010      for(xi=0;xi<8;xi++)
1011      {
1012         printf("%d",(m_ra[(yi & 7) | 8] >> xi) & 1);
1013      }
1014      printf("\n");
1015   }
1016   #endif
1017
1018   xsize = m_figs.m_d & 0x3ff;
1019   /* Guess: D has presumably upper bits for ysize, QX-10 relies on this (TODO: check this on any real HW) */
1020   ysize = ((m_figs.m_d & 0x400) + m_figs.m_dc) + 1;
1021
1022   /* TODO: internal direction, zooming, size stuff bigger than 8, rewrite using draw_pixel function */
1023   for(yi=0;yi<ysize;yi++)
1024   {
1025      switch(m_figs.m_dir & 7)
1026      {
1027         case 0: tile_data = BITSWAP8(m_ra[((yi) & 7) | 8],0,1,2,3,4,5,6,7); break; // TODO
1028         case 2: tile_data = BITSWAP8(m_ra[((yi) & 7) | 8],0,1,2,3,4,5,6,7); break;
1029         case 6: tile_data = BITSWAP8(m_ra[((ysize-1-yi) & 7) | 8],7,6,5,4,3,2,1,0); break;
1030         default: tile_data = BITSWAP8(m_ra[((yi) & 7) | 8],7,6,5,4,3,2,1,0);
1031                  printf("%d %d %d\n",m_figs.m_dir,xsize,ysize);
1032                  break;
1033      }
1034
1035      for(xi=0;xi<xsize;xi++)
1036      {
1037         UINT32 addr = ((y+yi) * m_pitch * 2) + ((x+xi) >> 3);
1038
1039         writebyte(addr & 0x3ffff, readbyte(addr & 0x3ffff) & ~(1 << (xi & 7)));
1040         writebyte(addr & 0x3ffff, readbyte(addr & 0x3ffff) | ((tile_data) & (1 << (xi & 7))));
1041      }
1042   }
1043
1044   m_ead = ((x+8*x_dir_dot[m_figs.m_dir]) >> 4) + ((y+8*y_dir_dot[m_figs.m_dir]) * m_pitch);
1045   m_dad = ((x+8*x_dir_dot[m_figs.m_dir]) & 0xf);
1046}
1047
1048
1049//-------------------------------------------------
1050//  translate_command -
1051//-------------------------------------------------
1052
1053int upd7220_device::translate_command(UINT8 data)
1054{
1055   int command = COMMAND_INVALID;
1056
1057   switch (data)
1058   {
1059   case UPD7220_COMMAND_RESET: command = COMMAND_RESET; break;
1060   case UPD7220_COMMAND_CCHAR: command = COMMAND_CCHAR; break;
1061   case UPD7220_COMMAND_START: command = COMMAND_START; break;
1062   case UPD7220_COMMAND_ZOOM:  command = COMMAND_ZOOM;  break;
1063   case UPD7220_COMMAND_CURS:  command = COMMAND_CURS;  break;
1064   case UPD7220_COMMAND_PITCH: command = COMMAND_PITCH; break;
1065   case UPD7220_COMMAND_MASK:  command = COMMAND_MASK;  break;
1066   case UPD7220_COMMAND_FIGS:  command = COMMAND_FIGS;  break;
1067   case UPD7220_COMMAND_FIGD:  command = COMMAND_FIGD;  break;
1068   case UPD7220_COMMAND_GCHRD: command = COMMAND_GCHRD; break;
1069   case UPD7220_COMMAND_CURD:  command = COMMAND_CURD;  break;
1070   case UPD7220_COMMAND_LPRD:  command = COMMAND_LPRD;  break;
1071   case UPD7220_COMMAND_5A:    command = COMMAND_5A;    break;
1072   default:
1073      switch (data & 0xfe)
1074      {
1075      case UPD7220_COMMAND_SYNC:  command = COMMAND_SYNC;  break;
1076      case UPD7220_COMMAND_VSYNC: command = COMMAND_VSYNC; break;
1077      case UPD7220_COMMAND_BCTRL: command = COMMAND_BCTRL; break;
1078      default:
1079         switch (data & 0xf0)
1080         {
1081         case UPD7220_COMMAND_PRAM: command = COMMAND_PRAM; break;
1082         default:
1083            switch (data & 0xe4)
1084            {
1085            case UPD7220_COMMAND_WDAT: command = COMMAND_WDAT; break;
1086            case UPD7220_COMMAND_RDAT: command = COMMAND_RDAT; break;
1087            case UPD7220_COMMAND_DMAR: command = COMMAND_DMAR; break;
1088            case UPD7220_COMMAND_DMAW: command = COMMAND_DMAW; break;
1089            }
1090         }
1091      }
1092   }
1093
1094   return command;
1095}
1096
1097
1098//-------------------------------------------------
1099//  process_fifo -
1100//-------------------------------------------------
1101
1102void upd7220_device::process_fifo()
1103{
1104   UINT8 data;
1105   int flag;
1106
1107   dequeue(&data, &flag);
1108
1109   if (flag == FIFO_COMMAND)
1110   {
1111      m_cr = data;
1112      m_param_ptr = 1;
1113   }
1114   else
1115   {
1116      m_pr[m_param_ptr] = data;
1117      m_param_ptr++;
1118   }
1119
1120   switch (translate_command(m_cr))
1121   {
1122   case COMMAND_INVALID:
1123      printf("uPD7220 '%s' Invalid Command Byte %02x\n", tag(), m_cr);
1124      break;
1125
1126   case COMMAND_5A:
1127      if (m_param_ptr == 4)
1128         printf("uPD7220 '%s' Undocumented Command 0x5A Executed %02x %02x %02x\n", tag(),m_pr[1],m_pr[2],m_pr[3] );
1129      break;
1130
1131   case COMMAND_RESET: /* reset */
1132      switch (m_param_ptr)
1133      {
1134      case 0:
1135         LOG(("uPD7220 '%s' RESET\n", tag()));
1136
1137         m_de = 0;
1138         m_ra[0] = m_ra[1] = m_ra[2] = 0;
1139         m_ra[3] = 0x19;
1140         m_ead = 0;
1141         m_dad = 0;
1142         m_mask = 0;
1143         break;
1144
1145      case 9:
1146         m_mode = m_pr[1];
1147         m_aw = m_pr[2] + 2;
1148         m_hs = (m_pr[3] & 0x1f) + 1;
1149         m_vs = ((m_pr[4] & 0x03) << 3) | (m_pr[3] >> 5);
1150         m_hfp = (m_pr[4] >> 2) + 1;
1151         m_hbp = (m_pr[5] & 0x3f) + 1;
1152         m_vfp = m_pr[6] & 0x3f;
1153         m_al = ((m_pr[8] & 0x03) << 8) | m_pr[7];
1154         m_vbp = m_pr[8] >> 2;
1155
1156         m_pitch = m_aw;
1157
1158         LOG(("uPD7220 '%s' Mode: %02x\n", tag(), m_mode));
1159         LOG(("uPD7220 '%s' AW: %u\n", tag(), m_aw));
1160         LOG(("uPD7220 '%s' HS: %u\n", tag(), m_hs));
1161         LOG(("uPD7220 '%s' VS: %u\n", tag(), m_vs));
1162         LOG(("uPD7220 '%s' HFP: %u\n", tag(), m_hfp));
1163         LOG(("uPD7220 '%s' HBP: %u\n", tag(), m_hbp));
1164         LOG(("uPD7220 '%s' VFP: %u\n", tag(), m_vfp));
1165         LOG(("uPD7220 '%s' AL: %u\n", tag(), m_al));
1166         LOG(("uPD7220 '%s' VBP: %u\n", tag(), m_vbp));
1167         LOG(("uPD7220 '%s' PITCH: %u\n", tag(), m_pitch));
1168
1169         recompute_parameters();
1170         break;
1171      }
1172      break;
1173
1174   case COMMAND_SYNC: /* sync format specify */
1175      if (m_param_ptr == 9)
1176      {
1177         m_mode = m_pr[1];
1178         m_aw = m_pr[2] + 2;
1179         m_hs = (m_pr[3] & 0x1f) + 1;
1180         m_vs = ((m_pr[4] & 0x03) << 3) | (m_pr[3] >> 5);
1181         m_hfp = (m_pr[4] >> 2) + 1;
1182         m_hbp = (m_pr[5] & 0x3f) + 1;
1183         m_vfp = m_pr[6] & 0x3f;
1184         m_al = ((m_pr[8] & 0x03) << 8) | m_pr[7];
1185         m_vbp = m_pr[8] >> 2;
1186
1187         m_pitch = m_aw;
1188
1189         LOG(("uPD7220 '%s' Mode: %02x\n", tag(), m_mode));
1190         LOG(("uPD7220 '%s' AW: %u\n", tag(), m_aw));
1191         LOG(("uPD7220 '%s' HS: %u\n", tag(), m_hs));
1192         LOG(("uPD7220 '%s' VS: %u\n", tag(), m_vs));
1193         LOG(("uPD7220 '%s' HFP: %u\n", tag(), m_hfp));
1194         LOG(("uPD7220 '%s' HBP: %u\n", tag(), m_hbp));
1195         LOG(("uPD7220 '%s' VFP: %u\n", tag(), m_vfp));
1196         LOG(("uPD7220 '%s' AL: %u\n", tag(), m_al));
1197         LOG(("uPD7220 '%s' VBP: %u\n", tag(), m_vbp));
1198         LOG(("uPD7220 '%s' PITCH: %u\n", tag(), m_pitch));
1199
1200         recompute_parameters();
1201      }
1202      break;
1203
1204   case COMMAND_VSYNC: /* vertical sync mode */
1205      m_m = m_cr & 0x01;
1206
1207      LOG(("uPD7220 '%s' M: %u\n", tag(), m_m));
1208
1209      recompute_parameters();
1210      break;
1211
1212   case COMMAND_CCHAR: /* cursor & character characteristics */
1213      if(m_param_ptr == 2)
1214      {
1215         m_lr = (m_pr[1] & 0x1f) + 1;
1216         m_dc = BIT(m_pr[1], 7);
1217
1218         LOG(("uPD7220 '%s' LR: %u\n", tag(), m_lr));
1219         LOG(("uPD7220 '%s' DC: %u\n", tag(), m_dc));
1220      }
1221
1222      if(m_param_ptr == 3)
1223      {
1224         m_ctop = m_pr[2] & 0x1f;
1225         m_sc = BIT(m_pr[2], 5);
1226         m_br = (m_pr[2] >> 6); /* guess, assume that blink rate clears upper bits (if any) */
1227
1228         LOG(("uPD7220 '%s' CTOP: %u\n", tag(), m_ctop));
1229         LOG(("uPD7220 '%s' SC: %u\n", tag(), m_sc));
1230      }
1231
1232      if(m_param_ptr == 4)
1233      {
1234         m_br = ((m_pr[3] & 0x07) << 2) | (m_pr[2] >> 6);
1235         m_cbot = m_pr[3] >> 3;
1236
1237         LOG(("uPD7220 '%s' BR: %u\n", tag(), m_br));
1238         LOG(("uPD7220 '%s' CBOT: %u\n", tag(), m_cbot));
1239      }
1240      break;
1241
1242   case COMMAND_START: /* start display & end idle mode */
1243      m_de = 1;
1244
1245      //LOG(("uPD7220 '%s' DE: 1\n", tag()));
1246      break;
1247
1248   case COMMAND_BCTRL: /* display blanking control */
1249      m_de = m_cr & 0x01;
1250
1251      //LOG(("uPD7220 '%s' DE: %u\n", tag(), m_de));
1252      break;
1253
1254   case COMMAND_ZOOM: /* zoom factors specify */
1255      if (flag == FIFO_PARAMETER)
1256      {
1257         m_gchr = m_pr[1] & 0x0f;
1258         m_disp = m_pr[1] >> 4;
1259
1260         LOG(("uPD7220 '%s' GCHR: %01x\n", tag(), m_gchr));
1261         LOG(("uPD7220 '%s' DISP: %01x\n", tag(), m_disp));
1262      }
1263      break;
1264
1265   case COMMAND_CURS: /* cursor position specify */
1266      if (m_param_ptr >= 3)
1267      {
1268         UINT8 upper_addr = (m_param_ptr == 3) ? 0 : (m_pr[3] & 0x03);
1269
1270         m_ead = (upper_addr << 16) | (m_pr[2] << 8) | m_pr[1];
1271
1272         //LOG(("uPD7220 '%s' EAD: %06x\n", tag(), m_ead));
1273
1274         if(m_param_ptr == 4)
1275         {
1276            m_dad = m_pr[3] >> 4;
1277            //LOG(("uPD7220 '%s' DAD: %01x\n", tag(), m_dad));
1278         }
1279      }
1280      break;
1281
1282   case COMMAND_PRAM: /* parameter RAM load */
1283      if (flag == FIFO_COMMAND)
1284      {
1285         m_ra_addr = m_cr & 0x0f;
1286      }
1287      else
1288      {
1289         if (m_ra_addr < 16)
1290         {
1291            LOG(("uPD7220 '%s' RA%u: %02x\n", tag(), m_ra_addr, data));
1292
1293            m_ra[m_ra_addr] = data;
1294            m_ra_addr++;
1295         }
1296
1297         m_param_ptr = 0;
1298      }
1299      break;
1300
1301   case COMMAND_PITCH: /* pitch specification */
1302      if (flag == FIFO_PARAMETER)
1303      {
1304         m_pitch = data;
1305
1306         LOG(("uPD7220 '%s' PITCH: %u\n", tag(), m_pitch));
1307      }
1308      break;
1309
1310   case COMMAND_WDAT: /* write data into display memory */
1311      m_bitmap_mod = m_cr & 3;
1312
1313      if (m_param_ptr == 3 || (m_param_ptr == 2 && m_cr & 0x10))
1314      {
1315         //printf("%02x = %02x %02x (%c) %04x\n",m_cr,m_pr[2],m_pr[1],m_pr[1],EAD);
1316         fifo_set_direction(FIFO_WRITE);
1317
1318         write_vram((m_cr & 0x18) >> 3,m_cr & 3);
1319         reset_figs_param();
1320         m_param_ptr = 1;
1321      }
1322      break;
1323
1324   case COMMAND_MASK: /* mask register load */
1325      if (m_param_ptr == 3)
1326      {
1327         m_mask = (m_pr[2] << 8) | m_pr[1];
1328
1329         LOG(("uPD7220 '%s' MASK: %04x\n", tag(), m_mask));
1330      }
1331      break;
1332
1333   case COMMAND_FIGS: /* figure drawing parameters specify */
1334      if (m_param_ptr == 2)
1335      {
1336         m_figs.m_dir = m_pr[1] & 0x7;
1337         m_figs.m_figure_type = (m_pr[1] & 0xf8) >> 3;
1338
1339         //if(m_figs.m_dir != 2)
1340         //  printf("DIR %02x\n",m_pr[1]);
1341      }
1342
1343      // the Decision Mate V during start-up test upload only 2 params before execute the
1344      // RDAT command, so I assume this is the expected behaviour, but this needs to be verified.
1345      if (m_param_ptr == 3)
1346         m_figs.m_dc = (m_pr[2]) | (m_figs.m_dc & 0x3f00);
1347
1348      if (m_param_ptr == 4)
1349         m_figs.m_dc = (m_pr[2]) | ((m_pr[3] & 0x3f) << 8);
1350
1351      if (m_param_ptr == 6)
1352         m_figs.m_d = (m_pr[4]) | ((m_pr[5] & 0x3f) << 8);
1353
1354      if (m_param_ptr == 8)
1355         m_figs.m_d2 = (m_pr[6]) | ((m_pr[7] & 0x3f) << 8);
1356
1357      if (m_param_ptr == 10)
1358         m_figs.m_d1 = (m_pr[8]) | ((m_pr[9] & 0x3f) << 8);
1359
1360      if (m_param_ptr == 12)
1361         m_figs.m_dm = (m_pr[10]) | ((m_pr[11] & 0x3f) << 8);
1362
1363      break;
1364
1365   case COMMAND_FIGD: /* figure draw start */
1366      if(m_figs.m_figure_type == 0)
1367      {
1368         UINT16 line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8));
1369         UINT8 dot = ((line_pattern >> (0 & 0xf)) & 1) << 7;
1370
1371         draw_pixel(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch),dot);
1372      }
1373      else if(m_figs.m_figure_type == 1)
1374         draw_line(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch));
1375      else if(m_figs.m_figure_type == 8)
1376         draw_rectangle(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch));
1377      else
1378         printf("uPD7220 '%s' Unimplemented command FIGD %02x\n", tag(),m_figs.m_figure_type);
1379
1380      reset_figs_param();
1381      m_sr |= UPD7220_SR_DRAWING_IN_PROGRESS;
1382      break;
1383
1384   case COMMAND_GCHRD: /* graphics character draw and area filling start */
1385      if(m_figs.m_figure_type == 2)
1386         draw_char(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch));
1387      else
1388         printf("uPD7220 '%s' Unimplemented command GCHRD %02x\n", tag(),m_figs.m_figure_type);
1389
1390      reset_figs_param();
1391      m_sr |= UPD7220_SR_DRAWING_IN_PROGRESS;
1392      break;
1393
1394   case COMMAND_RDAT: /* read data from display memory */
1395      fifo_set_direction(FIFO_READ);
1396
1397      read_vram((m_cr & 0x18) >> 3,m_cr & 3);
1398      reset_figs_param();
1399
1400      m_sr |= UPD7220_SR_DATA_READY;
1401      break;
1402
1403   case COMMAND_CURD: /* cursor address read */
1404      fifo_set_direction(FIFO_READ);
1405
1406      queue(m_ead & 0xff, 0);
1407      queue((m_ead >> 8) & 0xff, 0);
1408      queue(m_ead >> 16, 0);
1409      queue(m_dad & 0xff, 0);
1410      queue(m_dad >> 8, 0);
1411
1412      m_sr |= UPD7220_SR_DATA_READY;
1413      break;
1414
1415   case COMMAND_LPRD: /* light pen address read */
1416      fifo_set_direction(FIFO_READ);
1417
1418      queue(m_lad & 0xff, 0);
1419      queue((m_lad >> 8) & 0xff, 0);
1420      queue(m_lad >> 16, 0);
1421
1422      m_sr |= UPD7220_SR_DATA_READY;
1423      m_sr &= ~UPD7220_SR_LIGHT_PEN_DETECT;
1424      break;
1425
1426   case COMMAND_DMAR: /* DMA read request */
1427      printf("uPD7220 '%s' Unimplemented command DMAR\n", tag());
1428      break;
1429
1430   case COMMAND_DMAW: /* DMA write request */
1431      printf("uPD7220 '%s' Unimplemented command DMAW\n", tag());
1432      break;
1433   }
1434}
1435
1436
1437//-------------------------------------------------
1438//  read -
1439//-------------------------------------------------
1440
1441READ8_MEMBER( upd7220_device::read )
1442{
1443   UINT8 data;
1444
1445   if (offset & 1)
1446   {
1447      /* FIFO read */
1448      int flag;
1449      fifo_set_direction(FIFO_READ);
1450      dequeue(&data, &flag);
1451   }
1452   else
1453   {
1454      /* status register */
1455      data = m_sr;
1456
1457      /* TODO: timing of these */
1458      m_sr &= ~UPD7220_SR_DRAWING_IN_PROGRESS;
1459      m_sr &= ~UPD7220_SR_DMA_EXECUTE;
1460   }
1461
1462   return data;
1463}
1464
1465
1466//-------------------------------------------------
1467//  write -
1468//-------------------------------------------------
1469
1470WRITE8_MEMBER( upd7220_device::write )
1471{
1472   if (offset & 1)
1473   {
1474      /* command into FIFO */
1475      fifo_set_direction(FIFO_WRITE);
1476      queue(data, 1);
1477   }
1478   else
1479   {
1480      /* parameter into FIFO */
1481//      fifo_set_direction(FIFO_WRITE);
1482      queue(data, 0);
1483   }
1484
1485   process_fifo();
1486}
1487
1488
1489//-------------------------------------------------
1490//  dack_r -
1491//-------------------------------------------------
1492
1493READ8_MEMBER( upd7220_device::dack_r )
1494{
1495   return 0;
1496}
1497
1498
1499//-------------------------------------------------
1500//  dack_w -
1501//-------------------------------------------------
1502
1503WRITE8_MEMBER( upd7220_device::dack_w )
1504{
1505}
1506
1507
1508//-------------------------------------------------
1509//  ext_sync_w -
1510//-------------------------------------------------
1511
1512WRITE_LINE_MEMBER( upd7220_device::ext_sync_w )
1513{
1514   //LOG(("uPD7220 '%s' External Synchronization: %u\n", tag(), state));
1515
1516   if (state)
1517   {
1518      m_sr |= UPD7220_SR_VSYNC_ACTIVE;
1519   }
1520   else
1521   {
1522      m_sr &= ~UPD7220_SR_VSYNC_ACTIVE;
1523   }
1524}
1525
1526
1527//-------------------------------------------------
1528//  ext_sync_w -
1529//-------------------------------------------------
1530
1531WRITE_LINE_MEMBER( upd7220_device::lpen_w )
1532{
1533   /* only if 2 rising edges on the lpen input occur at the same
1534      point during successive video fields are the pulses accepted */
1535
1536   /*
1537
1538       1. compute the address of the location on the CRT
1539       2. compare with LAD
1540       3. if not equal move address to LAD
1541       4. if equal set LPEN DETECT flag to 1
1542
1543   */
1544}
1545
1546
1547//-------------------------------------------------
1548//  update_text -
1549//-------------------------------------------------
1550
1551void upd7220_device::update_text(bitmap_rgb32 &bitmap, const rectangle &cliprect)
1552{
1553   UINT32 addr, sad;
1554   UINT16 len;
1555   int im, wd;
1556   int y, sy = 0;
1557
1558   for (int area = 0; area < 4; area++)
1559   {
1560      get_text_partition(area, &sad, &len, &im, &wd);
1561
1562      for (y = sy; y < sy + len; y++)
1563      {
1564         addr = sad + (y * m_pitch);
1565
1566         if (m_draw_text_cb)
1567            m_draw_text_cb(this, bitmap, addr, y, wd, m_pitch, m_lr, m_dc, m_ead);
1568      }
1569
1570      sy = y + 1;
1571   }
1572}
1573
1574
1575//-------------------------------------------------
1576//  draw_graphics_line -
1577//-------------------------------------------------
1578
1579void upd7220_device::draw_graphics_line(bitmap_rgb32 &bitmap, UINT32 addr, int y, int wd)
1580{
1581   int sx;
1582
1583   for (sx = 0; sx < m_pitch * 2; sx++)
1584   {
1585      if((sx << 3) < m_aw * 16 && y < m_al)
1586         m_display_cb(this, bitmap, y, sx << 3, addr);
1587
1588      addr+= wd + 1;
1589   }
1590}
1591
1592
1593//-------------------------------------------------
1594//  update_graphics -
1595//-------------------------------------------------
1596
1597void upd7220_device::update_graphics(bitmap_rgb32 &bitmap, const rectangle &cliprect, int force_bitmap)
1598{
1599   UINT32 addr, sad;
1600   UINT16 len;
1601   int im, wd, area;
1602   int y = 0, tsy = 0, bsy = 0;
1603
1604   for (area = 0; area < 4; area++)
1605   {
1606      get_graphics_partition(area, &sad, &len, &im, &wd);
1607
1608      if (im || force_bitmap)
1609      {
1610         get_graphics_partition(area, &sad, &len, &im, &wd);
1611
1612         if(area >= 2) // TODO: correct?
1613            break;
1614
1615         for (y = 0; y < len; y++)
1616         {
1617            addr = ((sad << 1) & 0x3ffff) + (y * m_pitch * 2);
1618
1619            if (m_display_cb)
1620               draw_graphics_line(bitmap, addr, y + bsy, wd);
1621         }
1622      }
1623      else
1624      {
1625         get_text_partition(area, &sad, &len, &im, &wd);
1626
1627         if(m_lr)
1628         {
1629            for (y = 0; y < len; y+=m_lr)
1630            {
1631               addr = (sad & 0x3ffff) + ((y / m_lr) * m_pitch);
1632
1633               if (m_draw_text_cb)
1634                  m_draw_text_cb(this, bitmap, addr, (y + tsy) / m_lr, wd, m_pitch, m_lr, m_dc, m_ead);
1635            }
1636         }
1637      }
1638
1639      if (m_lr)
1640         tsy += y;
1641      bsy += y;
1642   }
1643}
1644
1645
1646//-------------------------------------------------
1647//  update_screen -
1648//-------------------------------------------------
1649
1650UINT32 upd7220_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
1651{
1652   if (m_de)
1653   {
1654      switch (m_mode & UPD7220_MODE_DISPLAY_MASK)
1655      {
1656      case UPD7220_MODE_DISPLAY_MIXED:
1657         update_graphics(bitmap, cliprect, 0);
1658         break;
1659
1660      case UPD7220_MODE_DISPLAY_GRAPHICS:
1661         update_graphics(bitmap, cliprect, 1);
1662         break;
1663
1664      case UPD7220_MODE_DISPLAY_CHARACTER:
1665         update_text(bitmap, cliprect);
1666         break;
1667
1668      case UPD7220_MODE_DISPLAY_INVALID:
1669         LOG(("uPD7220 '%s' Invalid Display Mode!\n", tag()));
1670      }
1671   }
1672   return 0;
1673}
trunk/src/mess/video/upd7220.h
r21684r21685
1/**********************************************************************
2
3    NEC uPD7220 Graphics Display Controller emulation
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************
9                            _____   _____
10                2xWCLK   1 |*    \_/     | 40  Vcc
11                 _DBIN   2 |             | 39  A17
12                 HSYNC   3 |             | 38  A16
13            V/EXT SYNC   4 |             | 37  AD15
14                 BLANK   5 |             | 36  AD14
15                   ALE   6 |             | 35  AD13
16                   DRQ   7 |             | 34  AD12
17                 _DACK   8 |             | 33  AD11
18                   _RD   9 |             | 32  AD10
19                   _WR  10 |   uPD7220   | 31  AD9
20                    A0  11 |    82720    | 30  AD8
21                   DB0  12 |             | 29  AD7
22                   DB1  13 |             | 28  AD6
23                   DB2  14 |             | 27  AD5
24                   DB3  15 |             | 26  AD4
25                   DB4  16 |             | 25  AD3
26                   DB5  17 |             | 24  AD2
27                   DB6  18 |             | 23  AD1
28                   DB7  19 |             | 22  AD0
29                   GND  20 |_____________| 21  LPEN
30
31**********************************************************************/
32
33#pragma once
34
35#ifndef __UPD7220__
36#define __UPD7220__
37
38#include "emu.h"
39
40
41
42//**************************************************************************
43//  MACROS / CONSTANTS
44//**************************************************************************
45
46
47
48
49//**************************************************************************
50//  INTERFACE CONFIGURATION MACROS
51//**************************************************************************
52
53#define MCFG_UPD7220_ADD(_tag, _clock, _config, _map) \
54   MCFG_DEVICE_ADD(_tag, UPD7220, _clock) \
55   MCFG_DEVICE_CONFIG(_config) \
56   MCFG_DEVICE_ADDRESS_MAP(AS_0, _map)
57
58#define UPD7220_INTERFACE(name) \
59   const upd7220_interface (name) =
60
61
62
63//**************************************************************************
64//  TYPE DEFINITIONS
65//**************************************************************************
66
67typedef void (*upd7220_display_pixels_func)(device_t *device, bitmap_rgb32 &bitmap, int y, int x, UINT32 address);
68#define UPD7220_DISPLAY_PIXELS(name) void name(device_t *device, bitmap_rgb32 &bitmap, int y, int x, UINT32 address)
69
70typedef void (*upd7220_draw_text_line)(device_t *device, bitmap_rgb32 &bitmap, UINT32 addr, int y, int wd, int pitch, int lr, int cursor_on, int cursor_addr);
71#define UPD7220_DRAW_TEXT_LINE(name) void name(device_t *device, bitmap_rgb32 &bitmap, UINT32 addr, int y, int wd, int pitch, int lr, int cursor_on, int cursor_addr)
72
73
74// ======================> upd7220_interface
75
76struct upd7220_interface
77{
78   const char *m_screen_tag;
79
80   upd7220_display_pixels_func m_display_cb;
81   upd7220_draw_text_line m_draw_text_cb;
82
83   devcb_write_line        m_out_drq_cb;
84   devcb_write_line        m_out_hsync_cb;
85   devcb_write_line        m_out_vsync_cb;
86   devcb_write_line        m_out_blank_cb;
87};
88
89// ======================> upd7220_device
90
91class upd7220_device :  public device_t,
92                  public device_memory_interface,
93                  public upd7220_interface
94{
95public:
96   // construction/destruction
97   upd7220_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
98
99   DECLARE_READ8_MEMBER( read );
100   DECLARE_WRITE8_MEMBER( write );
101
102   DECLARE_READ8_MEMBER( dack_r );
103   DECLARE_WRITE8_MEMBER( dack_w );
104
105   DECLARE_WRITE_LINE_MEMBER( ext_sync_w );
106   DECLARE_WRITE_LINE_MEMBER( lpen_w );
107
108   DECLARE_WRITE8_MEMBER( bank_w );
109   DECLARE_READ8_MEMBER( vram_r );
110   DECLARE_WRITE8_MEMBER( vram_w );
111
112   UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
113   virtual const rom_entry *device_rom_region() const;
114   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
115
116protected:
117   // device-level overrides
118   virtual void device_start();
119   virtual void device_reset();
120   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
121   virtual void device_config_complete();
122
123private:
124   static const device_timer_id TIMER_VSYNC = 0;
125   static const device_timer_id TIMER_HSYNC = 1;
126   static const device_timer_id TIMER_BLANK = 2;
127
128   inline UINT8 readbyte(offs_t address);
129   inline void writebyte(offs_t address, UINT8 data);
130   inline void fifo_clear();
131   inline int fifo_param_count();
132   inline void fifo_set_direction(int dir);
133   inline void queue(UINT8 data, int flag);
134   inline void dequeue(UINT8 *data, int *flag);
135   inline void update_vsync_timer(int state);
136   inline void update_hsync_timer(int state);
137   inline void update_blank_timer(int state);
138   inline void recompute_parameters();
139   inline void reset_figs_param();
140   inline void advance_ead();
141   inline void read_vram(UINT8 type, UINT8 mod);
142   inline void write_vram(UINT8 type, UINT8 mod);
143   inline UINT16 check_pattern(UINT16 pattern);
144   inline void get_text_partition(int index, UINT32 *sad, UINT16 *len, int *im, int *wd);
145   inline void get_graphics_partition(int index, UINT32 *sad, UINT16 *len, int *im, int *wd);
146
147   void draw_pixel(int x, int y, UINT8 tile_data);
148   void draw_line(int x, int y);
149   void draw_rectangle(int x, int y);
150   void draw_char(int x, int y);
151   int translate_command(UINT8 data);
152   void process_fifo();
153   void update_text(bitmap_rgb32 &bitmap, const rectangle &cliprect);
154   void draw_graphics_line(bitmap_rgb32 &bitmap, UINT32 addr, int y, int wd);
155   void update_graphics(bitmap_rgb32 &bitmap, const rectangle &cliprect, int force_bitmap);
156
157   devcb_resolved_write_line   m_out_drq_func;
158   devcb_resolved_write_line   m_out_hsync_func;
159   devcb_resolved_write_line   m_out_vsync_func;
160   devcb_resolved_write_line   m_out_blank_func;
161
162   screen_device *m_screen;
163
164   UINT16 m_mask;                  // mask register
165   UINT8 m_pitch;                  // number of word addresses in display memory in the horizontal direction
166   UINT32 m_ead;                   // execute word address
167   UINT16 m_dad;                   // dot address within the word
168   UINT32 m_lad;                   // light pen address
169
170   UINT8 m_ra[16];                 // parameter RAM
171   int m_ra_addr;                  // parameter RAM address
172
173   UINT8 m_sr;                     // status register
174   UINT8 m_cr;                     // command register
175   UINT8 m_pr[17];                 // parameter byte register
176   int m_param_ptr;                // parameter pointer
177
178   UINT8 m_fifo[16];               // FIFO data queue
179   int m_fifo_flag[16];            // FIFO flag queue
180   int m_fifo_ptr;                 // FIFO pointer
181   int m_fifo_dir;                 // FIFO direction
182
183   UINT8 m_mode;                   // mode of operation
184   UINT8 m_draw_mode;              // mode of drawing
185
186   int m_de;                       // display enabled
187   int m_m;                        // 0 = accept external vertical sync (slave mode) / 1 = generate & output vertical sync (master mode)
188   int m_aw;                       // active display words per line - 2 (must be even number with bit 0 = 0)
189   int m_al;                       // active display lines per video field
190   int m_vs;                       // vertical sync width - 1
191   int m_vfp;                      // vertical front porch width - 1
192   int m_vbp;                      // vertical back porch width - 1
193   int m_hs;                       // horizontal sync width - 1
194   int m_hfp;                      // horizontal front porch width - 1
195   int m_hbp;                      // horizontal back porch width - 1
196
197   int m_dc;                       // display cursor
198   int m_sc;                       // 0 = blinking cursor / 1 = steady cursor
199   int m_br;                       // blink rate
200   int m_ctop;                     // cursor top line number in the row
201   int m_cbot;                     // cursor bottom line number in the row (CBOT < LR)
202   int m_lr;                       // lines per character row - 1
203
204   int m_disp;                     // display zoom factor
205   int m_gchr;                     // zoom factor for graphics character writing and area filling
206
207   UINT8 m_bitmap_mod;
208
209   struct {
210      UINT8 m_dir;                // figs param 0: drawing direction
211      UINT8 m_figure_type;        // figs param 1: figure type
212      UINT16 m_dc;                // figs param 2:
213      UINT16 m_d;                 // figs param 3:
214      UINT16 m_d1;                // figs param 4:
215      UINT16 m_d2;                // figs param 5:
216      UINT16 m_dm;                // figs param 6:
217   } m_figs;
218
219   // timers
220   emu_timer *m_vsync_timer;       // vertical sync timer
221   emu_timer *m_hsync_timer;       // horizontal sync timer
222   emu_timer *m_blank_timer;       // CRT blanking timer
223
224   const address_space_config      m_space_config;
225};
226
227
228// device type definition
229extern const device_type UPD7220;
230
231
232
233#endif
trunk/src/mess/video/hd44780.c
r21684r21685
1/***************************************************************************
2
3        Hitachi HD44780 LCD controller
4
5        TODO:
6        - dump internal CGROM
7
8***************************************************************************/
9
10#include "emu.h"
11#include "video/hd44780.h"
12
13#define LOG          0
14
15//**************************************************************************
16//  DEVICE DEFINITIONS
17//**************************************************************************
18
19const device_type HD44780 = &device_creator<hd44780_device>;
20const device_type KS0066_F05 = &device_creator<ks0066_f05_device>;
21
22
23//-------------------------------------------------
24//  ROM( hd44780 )
25//-------------------------------------------------
26
27ROM_START( hd44780_a00 )
28   ROM_REGION( 0x1000, "cgrom", 0 )
29   ROM_LOAD( "hd44780_a00.bin",    0x0000, 0x1000,  BAD_DUMP CRC(01d108e2) SHA1(bc0cdf0c9ba895f22e183c7bd35a3f655f2ca96f)) // from page 17 of the HD44780 datasheet
30ROM_END
31
32ROM_START( ks0066_f05 )
33   ROM_REGION( 0x1000, "cgrom", 0 )
34   ROM_LOAD( "ks0066_f05.bin",    0x0000, 0x1000,  BAD_DUMP CRC(af9e7bd6) SHA1(0196e871584ee5d370856e7307c0f9d1466e3e51)) // from page 51 of the KS0066 datasheet
35ROM_END
36
37//**************************************************************************
38//  live device
39//**************************************************************************
40
41//-------------------------------------------------
42//  hd44780_device - constructor
43//-------------------------------------------------
44
45hd44780_device::hd44780_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
46   device_t(mconfig, HD44780, "HD44780 A00", tag, owner, clock),
47   m_pixel_update_func(NULL)
48{
49   m_shortname = "hd44780_a00";
50   set_charset_type(CHARSET_HD44780_A00);
51}
52
53hd44780_device::hd44780_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
54   device_t(mconfig, type, name, tag, owner, clock),
55   m_pixel_update_func(NULL)
56{
57}
58
59ks0066_f05_device::ks0066_f05_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
60   hd44780_device(mconfig, KS0066_F05, "KS0066 F05", tag, owner, clock)
61{
62   m_shortname = "ks0066_f05";
63   set_charset_type(CHARSET_KS0066_F05);
64}
65
66
67//-------------------------------------------------
68//  rom_region - device-specific ROM region
69//-------------------------------------------------
70
71const rom_entry *hd44780_device::device_rom_region() const
72{
73   switch (m_charset_type)
74   {
75      case CHARSET_HD44780_A00:   return ROM_NAME( hd44780_a00 );
76      case CHARSET_KS0066_F05:    return ROM_NAME( ks0066_f05 );
77   }
78
79   return NULL;
80}
81
82//-------------------------------------------------
83//  device_start - device-specific startup
84//-------------------------------------------------
85
86void hd44780_device::device_start()
87{
88   if (region())
89      m_cgrom = (UINT8*)(*region());
90   else
91      m_cgrom = (UINT8*)(*memregion("cgrom"));
92
93   m_busy_timer = timer_alloc(TIMER_BUSY);
94   m_blink_timer = timer_alloc(TIMER_BLINKING);
95   m_blink_timer->adjust(attotime::from_msec(409), 0, attotime::from_msec(409));
96
97   // state saving
98   save_item(NAME(m_busy_flag));
99   save_item(NAME(m_ac));
100   save_item(NAME(m_dr));
101   save_item(NAME(m_ir));
102   save_item(NAME(m_active_ram));
103   save_item(NAME(m_display_on));
104   save_item(NAME(m_cursor_on));
105   save_item(NAME(m_shift_on));
106   save_item(NAME(m_blink_on));
107   save_item(NAME(m_direction));
108   save_item(NAME(m_data_len));
109   save_item(NAME(m_num_line));
110   save_item(NAME(m_char_size));
111   save_item(NAME(m_disp_shift));
112   save_item(NAME(m_blink));
113   save_item(NAME(m_ddram));
114   save_item(NAME(m_cgram));
115   save_item(NAME(m_nibble));
116   save_item(NAME(m_rs_state));
117   save_item(NAME(m_rw_state));
118}
119
120//-------------------------------------------------
121//  device_reset - device-specific reset
122//-------------------------------------------------
123
124void hd44780_device::device_reset()
125{
126   memset(m_ddram, 0x20, sizeof(m_ddram)); // can't use 0 here as it would show CGRAM instead of blank space on a soft reset
127   memset(m_cgram, 0, sizeof(m_cgram));
128
129   m_ac         = 0;
130   m_dr         = 0;
131   m_ir         = 0;
132   m_active_ram = DDRAM;
133   m_display_on = false;
134   m_cursor_on  = false;
135   m_blink_on   = false;
136   m_shift_on   = false;
137   m_direction  = 1;
138   m_data_len   = 8;
139   m_num_line   = 1;
140   m_char_size  = 8;
141   m_disp_shift = 0;
142   m_blink      = false;
143   m_nibble     = false;
144   m_first_cmd  = true;
145   m_rs_state   = 0;
146   m_rw_state   = 0;
147
148   set_busy_flag(1520);
149}
150
151
152//-------------------------------------------------
153//  device_timer - handler timer events
154//-------------------------------------------------
155
156void hd44780_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
157{
158   switch(id)
159   {
160      case TIMER_BUSY:
161         m_busy_flag = false;
162         break;
163
164      case TIMER_BLINKING:
165         m_blink = !m_blink;
166         break;
167   }
168}
169
170
171//**************************************************************************
172//  HELPERS
173//**************************************************************************
174
175void hd44780_device::set_charset_type(int type)
176{
177   m_charset_type = type;
178}
179
180void hd44780_device::set_busy_flag(UINT16 usec)
181{
182   m_busy_flag = true;
183   m_busy_timer->adjust( attotime::from_usec( usec ) );
184}
185
186void hd44780_device::update_ac(int direction)
187{
188   if (m_active_ram == DDRAM)
189   {
190      if(direction == 1)
191      {
192         if(m_num_line == 2 && m_ac == 0x27)
193            m_ac = 0x40;
194         else if((m_num_line == 2 && m_ac == 0x67) || (m_num_line == 1 && m_ac == 0x4f))
195            m_ac = 0x00;
196         else
197            m_ac = (m_ac + direction) & 0x7f;
198      }
199      else
200      {
201         if(m_num_line == 2 && m_ac == 0x00)
202            m_ac = 0x67;
203         else if(m_num_line == 1 && m_ac == 0x00)
204            m_ac = 0x4f;
205         else if(m_num_line == 2 && m_ac == 0x40)
206            m_ac = 0x27;
207         else
208            m_ac = (m_ac + direction) & 0x7f;
209      }
210   }
211   else
212   {
213      m_ac = (m_ac + direction) & 0x3f;
214   }
215}
216
217void hd44780_device::shift_display(int direction)
218{
219   if (direction == 1)
220   {
221      if(m_disp_shift == 0x4f)
222         m_disp_shift = 0x00;
223      else
224         m_disp_shift++;
225   }
226   else
227   {
228      if(m_disp_shift == 0x00)
229         m_disp_shift = 0x4f;
230      else
231         m_disp_shift--;
232   }
233}
234
235void hd44780_device::update_nibble(int rs, int rw)
236{
237   if (m_rs_state != rs || m_rw_state != rw)
238   {
239      m_rs_state = rs;
240      m_rw_state = rw;
241      m_nibble = false;
242   }
243
244   m_nibble = !m_nibble;
245}
246
247inline void hd44780_device::pixel_update(bitmap_ind16 &bitmap, UINT8 line, UINT8 pos, UINT8 y, UINT8 x, int state)
248{
249   if (m_pixel_update_func != NULL)
250   {
251      m_pixel_update_func(*this, bitmap, line, pos, y, x, state);
252   }
253   else
254   {
255      UINT8 line_heigh = (m_char_size == 8) ? m_char_size : m_char_size + 1;
256
257      if (m_lines <= 2)
258      {
259         if (pos < m_chars)
260            bitmap.pix16(line * (line_heigh+1) + y, pos * 6 + x) = state;
261      }
262      else if (m_lines <= 4)
263      {
264         if (pos < m_chars*2)
265         {
266            if (pos >= m_chars)
267            {
268               line += 2;
269               pos -= m_chars;
270            }
271
272            if (line < m_lines)
273               bitmap.pix16(line * (line_heigh+1) + y, pos * 6 + x) = state;
274         }
275      }
276      else
277      {
278         fatalerror("%s: use a custom callback for this LCD configuration (%d x %d)\n", tag(), m_lines, m_chars);
279      }
280   }
281}
282
283
284//**************************************************************************
285//  device interface
286//**************************************************************************
287
288UINT32 hd44780_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
289{
290   bitmap.fill(0, cliprect);
291
292   if (m_display_on)
293   {
294      UINT8 line_size = 80 / m_num_line;
295
296      for (int line=0; line<m_num_line; line++)
297      {
298         for (int pos=0; pos<line_size; pos++)
299         {
300            UINT16 char_pos = line * 0x40 + ((pos + m_disp_shift) % line_size);
301
302            int char_base = 0;
303            if (m_ddram[char_pos] < 0x10)
304            {
305               // draw CGRAM characters
306               if (m_char_size == 8)
307                  char_base = (m_ddram[char_pos] & 0x07) * 8;
308               else
309                  char_base = ((m_ddram[char_pos]>>1) & 0x03) * 16;
310            }
311            else
312            {
313               // draw CGROM characters
314               char_base = m_ddram[char_pos] * 0x10;
315            }
316
317            for (int y=0; y<m_char_size; y++)
318            {
319               UINT8 * charset = (m_ddram[char_pos] < 0x10) ? m_cgram : m_cgrom;
320
321               for (int x=0; x<5; x++)
322                  pixel_update(bitmap, line, pos, y, x, BIT(charset[char_base + y], 4 - x));
323            }
324
325            // if is the correct position draw cursor and blink
326            if (char_pos == m_ac)
327            {
328               // draw the cursor
329               UINT8 cursor_pos = (m_char_size == 8) ? m_char_size : m_char_size + 1;
330               if (m_cursor_on)
331                  for (int x=0; x<5; x++)
332                     pixel_update(bitmap, line, pos, cursor_pos - 1, x, 1);
333
334               if (!m_blink && m_blink_on)
335                  for (int y=0; y<(cursor_pos - 1); y++)
336                     for (int x=0; x<5; x++)
337                        pixel_update(bitmap, line, pos, y, x, 1);
338            }
339         }
340      }
341   }
342
343   return 0;
344}
345
346READ8_MEMBER(hd44780_device::read)
347{
348   switch(offset & 0x01)
349   {
350      case 0: return control_read(space, 0);
351      case 1: return data_read(space, 0);
352   }
353
354   return 0;
355}
356
357WRITE8_MEMBER(hd44780_device::write)
358{
359   switch(offset & 0x01)
360   {
361      case 0: control_write(space, 0, data);  break;
362      case 1: data_write(space, 0, data);     break;
363   }
364}
365
366WRITE8_MEMBER(hd44780_device::control_write)
367{
368   if (m_data_len == 4)
369   {
370      update_nibble(0, 0);
371
372      if (m_nibble)
373      {
374         m_ir = data & 0xf0;
375         return;
376      }
377      else
378      {
379         m_ir |= ((data>>4) & 0x0f);
380      }
381   }
382   else
383   {
384      m_ir = data;
385   }
386
387   if (BIT(m_ir, 7))           // set DDRAM address
388   {
389      m_active_ram = DDRAM;
390      m_ac = m_ir & 0x7f;
391      set_busy_flag(37);
392
393      if (LOG) logerror("HD44780 '%s': set DDRAM address %x\n", tag(), m_ac);
394   }
395   else if (BIT(m_ir, 6))      // set CGRAM address
396   {
397      m_active_ram = CGRAM;
398      m_ac = m_ir & 0x3f;
399      set_busy_flag(37);
400
401      if (LOG) logerror("HD44780 '%s': set CGRAM address %x\n", tag(), m_ac);
402   }
403   else if (BIT(m_ir, 5))      // function set
404   {
405      if (!m_first_cmd && m_data_len == (BIT(m_ir, 4) ? 8 : 4) && (m_char_size != (BIT(m_ir, 2) ? 10 : 8) || m_num_line != (BIT(m_ir, 3) + 1)))
406      {
407         logerror("HD44780 '%s': function set cannot be executed after other instructions unless the interface data length is changed\n", tag());
408         return;
409      }
410
411      m_char_size = BIT(m_ir, 2) ? 10 : 8;
412      m_data_len  = BIT(m_ir, 4) ? 8 : 4;
413      m_num_line  = BIT(m_ir, 3) + 1;
414      set_busy_flag(37);
415
416      if (LOG) logerror("HD44780 '%s': char size 5x%d, data len %d, lines %d\n", tag(), m_char_size, m_data_len, m_num_line);
417      return;
418   }
419   else if (BIT(m_ir, 4))      // cursor or display shift
420   {
421      int direct = (BIT(m_ir, 2)) ? +1 : -1;
422
423      if (LOG) logerror("HD44780 '%s': %s shift %d\n", tag(), BIT(m_ir, 3) ? "display" : "cursor",  direct);
424
425      if (BIT(m_ir, 3))
426         shift_display(direct);
427      else
428         update_ac(direct);
429
430      set_busy_flag(37);
431   }
432   else if (BIT(m_ir, 3))      // display on/off control
433   {
434      m_display_on = BIT(m_ir, 2);
435      m_cursor_on  = BIT(m_ir, 1);
436      m_blink_on   = BIT(m_ir, 0);
437      set_busy_flag(37);
438
439      if (LOG) logerror("HD44780 '%s': display %d, cursor %d, blink %d\n", tag(), m_display_on, m_cursor_on, m_blink_on);
440   }
441   else if (BIT(m_ir, 2))      // entry mode set
442   {
443      m_direction = (BIT(m_ir, 1)) ? +1 : -1;
444      m_shift_on  = BIT(m_ir, 0);
445      set_busy_flag(37);
446
447      if (LOG) logerror("HD44780 '%s': entry mode set: direction %d, shift %d\n", tag(), m_direction, m_shift_on);
448   }
449   else if (BIT(m_ir, 1))      // return home
450   {
451      if (LOG) logerror("HD44780 '%s': return home\n", tag());
452
453      m_ac         = 0;
454      m_active_ram = DDRAM;
455      m_direction  = 1;
456      m_disp_shift = 0;
457      set_busy_flag(1520);
458   }
459   else if (BIT(m_ir, 0))      // clear display
460   {
461      if (LOG) logerror("HD44780 '%s': clear display\n", tag());
462
463      m_ac         = 0;
464      m_active_ram = DDRAM;
465      m_direction  = 1;
466      m_disp_shift = 0;
467      memset(m_ddram, 0x20, sizeof(m_ddram));
468      set_busy_flag(1520);
469   }
470
471   m_first_cmd = false;
472}
473
474READ8_MEMBER(hd44780_device::control_read)
475{
476   if (m_data_len == 4)
477   {
478      if (!space.debugger_access())
479         update_nibble(0, 1);
480
481      if (m_nibble)
482         return (m_busy_flag ? 0x80 : 0) | (m_ac & 0x70);
483      else
484         return (m_ac<<4) & 0xf0;
485   }
486   else
487   {
488      return (m_busy_flag ? 0x80 : 0) | (m_ac & 0x7f);
489   }
490}
491
492WRITE8_MEMBER(hd44780_device::data_write)
493{
494   if (m_busy_flag)
495   {
496      logerror("HD44780 '%s': Ignoring data write %02x due of busy flag\n", tag(), data);
497      return;
498   }
499
500   if (m_data_len == 4)
501   {
502      update_nibble(1, 0);
503
504      if (m_nibble)
505      {
506         m_dr = data & 0xf0;
507         return;
508      }
509      else
510      {
511         m_dr |= ((data>>4) & 0x0f);
512      }
513   }
514   else
515   {
516      m_dr = data;
517   }
518
519   if (LOG) logerror("HD44780 '%s': %sRAM write %x %x '%c'\n", tag(), m_active_ram == DDRAM ? "DD" : "CG", m_ac, m_dr, isprint(m_dr) ? m_dr : '.');
520
521   if (m_active_ram == DDRAM)
522      m_ddram[m_ac] = m_dr;
523   else
524      m_cgram[m_ac] = m_dr;
525
526   update_ac(m_direction);
527   if (m_shift_on)
528      shift_display(m_direction);
529   set_busy_flag(41);
530}
531
532READ8_MEMBER(hd44780_device::data_read)
533{
534   UINT8 data = (m_active_ram == DDRAM) ? m_ddram[m_ac] : m_cgram[m_ac];
535
536   if (LOG) logerror("HD44780 '%s': %sRAM read %x %c\n", tag(), m_active_ram == DDRAM ? "DD" : "CG", m_ac, data);
537
538   if (m_data_len == 4)
539   {
540      if (!space.debugger_access())
541         update_nibble(1, 1);
542
543      if (m_nibble)
544         return data & 0xf0;
545      else
546         data = (data<<4) & 0xf0;
547   }
548
549   if (!space.debugger_access())
550   {
551      update_ac(m_direction);
552      set_busy_flag(41);
553   }
554
555   return data;
556}
trunk/src/mess/video/hd44780.h
r21684r21685
1/***************************************************************************
2
3        Hitachi HD44780 LCD controller
4
5***************************************************************************/
6
7#pragma once
8
9#ifndef __HD44780_H__
10#define __HD44780_H__
11
12
13#define MCFG_HD44780_ADD( _tag ) \
14   MCFG_DEVICE_ADD( _tag, HD44780, 0 )
15
16#define MCFG_KS0066_F05_ADD( _tag ) \
17   MCFG_DEVICE_ADD( _tag, KS0066_F05, 0 )
18
19#define MCFG_HD44780_LCD_SIZE(_lines, _chars) \
20   hd44780_device::static_set_lcd_size(*device, _lines, _chars);
21
22#define MCFG_HD44780_PIXEL_UPDATE_CB(_cb) \
23   hd44780_device::static_set_pixel_update_cb(*device, _cb);
24
25//**************************************************************************
26//  TYPE DEFINITIONS
27//**************************************************************************
28
29typedef void (*hd44780_pixel_update_func)(device_t &device, bitmap_ind16 &bitmap, UINT8 line, UINT8 pos, UINT8 y, UINT8 x, int state);
30#define HD44780_PIXEL_UPDATE(name) void name(device_t &device, bitmap_ind16 &bitmap, UINT8 line, UINT8 pos, UINT8 y, UINT8 x, int state)
31
32
33// ======================> hd44780_device
34
35class hd44780_device :  public device_t
36{
37public:
38   // construction/destruction
39   hd44780_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
40   hd44780_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
41
42   // static configuration helpers
43   static void static_set_lcd_size(device_t &device, int _lines, int _chars) { hd44780_device &dev=downcast<hd44780_device &>(device); dev.m_lines = _lines; dev.m_chars = _chars; }
44   static void static_set_pixel_update_cb(device_t &device, hd44780_pixel_update_func _cb) { downcast<hd44780_device &>(device).m_pixel_update_func = _cb; }
45
46   // device interface
47   virtual DECLARE_WRITE8_MEMBER(write);
48   virtual DECLARE_READ8_MEMBER(read);
49   virtual DECLARE_WRITE8_MEMBER(control_write);
50   virtual DECLARE_READ8_MEMBER(control_read);
51   virtual DECLARE_WRITE8_MEMBER(data_write);
52   virtual DECLARE_READ8_MEMBER(data_read);
53   virtual UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
54
55protected:
56   // device-level overrides
57   virtual void device_start();
58   virtual void device_reset();
59   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
60
61   // optional information overrides
62   virtual const rom_entry *device_rom_region() const;
63
64   // charset
65   enum
66   {
67      CHARSET_HD44780_A00,
68      CHARSET_KS0066_F05,
69      /*
70      CHARSET_HD44780_A01,
71      CHARSET_HD44780_A02,
72      CHARSET_KS0066_F00,
73      CHARSET_KS0066_F03,
74      CHARSET_KS0066_F04,
75      CHARSET_KS0066_F06,
76      CHARSET_KS0066_F59,
77      */
78   };
79
80   void set_charset_type(int type);
81
82private:
83   // internal helper
84   void set_busy_flag(UINT16 usec);
85   void update_ac(int direction);
86   void update_nibble(int rs, int rw);
87   void shift_display(int direction);
88   void pixel_update(bitmap_ind16 &bitmap, UINT8 line, UINT8 pos, UINT8 y, UINT8 x, int state);
89
90   // internal state
91   static const device_timer_id TIMER_BUSY = 0;
92   static const device_timer_id TIMER_BLINKING = 1;
93
94   emu_timer * m_blink_timer;
95   emu_timer * m_busy_timer;
96
97   UINT8       m_lines;          // number of lines
98   UINT8       m_chars;          // chars for line
99   hd44780_pixel_update_func m_pixel_update_func; // pixel update callback
100
101   bool        m_busy_flag;      // busy flag
102   UINT8       m_ddram[0x80];    // internal display data RAM
103   UINT8       m_cgram[0x40];    // internal chargen RAM
104   UINT8 *     m_cgrom;          // internal chargen ROM
105   INT8        m_ac;             // address counter
106   UINT8       m_dr;             // data register
107   UINT8       m_ir;             // instruction register
108   UINT8       m_active_ram;     // DDRAM or CGRAM
109   bool        m_display_on;     // display on/off
110   bool        m_cursor_on;      // cursor on/off
111   bool        m_blink_on;       // blink on/off
112   bool        m_shift_on;       // shift on/off
113   UINT8       m_disp_shift;     // display shift
114   INT8        m_direction;      // auto increment/decrement
115   UINT8       m_data_len;       // interface data length 4 or 8 bit
116   UINT8       m_num_line;       // number of lines
117   UINT8       m_char_size;      // char size 5x8 or 5x10
118   bool        m_blink;
119   bool        m_first_cmd;
120   int         m_rs_state;
121   int         m_rw_state;
122   bool        m_nibble;
123   int         m_charset_type;
124
125   enum        { DDRAM, CGRAM };
126};
127
128// ======================> ks0066_f05_device
129
130class ks0066_f05_device :  public hd44780_device
131{
132public:
133   // construction/destruction
134   ks0066_f05_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
135};
136
137// device type definition
138extern const device_type HD44780;
139extern const device_type KS0066_F05;
140
141#endif
trunk/src/mess/video/tms3556.c
r21684r21685
1/*
2    tms3556 emulation
3
4    TODO:
5    * implement remaining flags in control registers
6    * test the whole thing
7    * find the bloody tms3556 manual.  I mean the register and VRAM interfaces
8      are mostly guesswork full of hacks, and I'd like to compare it with
9      documentation.
10
11    Raphael Nabet, 2004
12*/
13
14#include "emu.h"
15#include "tms3556.h"
16
17//**************************************************************************
18//  MACROS / CONSTANTS
19//**************************************************************************
20
21#define LOG 0
22
23//**************************************************************************
24//  GLOBAL VARIABLES
25//**************************************************************************
26
27// devices
28const device_type TMS3556 = &device_creator<tms3556_device>;
29
30
31// default address map
32static ADDRESS_MAP_START( tms3556, AS_0, 8, tms3556_device )
33   AM_RANGE(0x0000, 0xffff) AM_RAM
34ADDRESS_MAP_END
35
36//-------------------------------------------------
37//  memory_space_config - return a description of
38//  any address spaces owned by this device
39//-------------------------------------------------
40
41const address_space_config *tms3556_device::memory_space_config(address_spacenum spacenum) const
42{
43   return (spacenum == AS_0) ? &m_space_config : NULL;
44}
45
46
47//**************************************************************************
48//  INLINE HELPERS
49//**************************************************************************
50
51//-------------------------------------------------
52//  readbyte - read a byte at the given address
53//-------------------------------------------------
54
55inline UINT8 tms3556_device::readbyte(offs_t address)
56{
57   return space().read_byte(address);
58}
59
60
61//-------------------------------------------------
62//  writebyte - write a byte at the given address
63//-------------------------------------------------
64
65inline void tms3556_device::writebyte(offs_t address, UINT8 data)
66{
67   space().write_byte(address, data);
68}
69
70
71//**************************************************************************
72//  LIVE DEVICE
73//**************************************************************************
74
75//-------------------------------------------------
76//  tms3556_device - constructor
77//-------------------------------------------------
78
79tms3556_device::tms3556_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
80   : device_t(mconfig, TMS3556, "Texas Instruments VDP TMS3556", tag, owner, clock),
81      device_memory_interface(mconfig, *this),
82      m_space_config("videoram", ENDIANNESS_LITTLE, 8, 17, 0, NULL, *ADDRESS_MAP_NAME(tms3556)),
83      m_write_ptr(0),
84      m_reg_ptr(0),
85      m_reg_access_phase(0),
86      m_magical_mystery_flag(0),
87      m_scanline(0),
88      m_blink(0),
89      m_blink_count(0)
90{
91   for (int i = 0; i < 8; i++)
92   {
93      m_control_regs[i] = 0;
94      m_address_regs[i] = 0;
95   }
96}
97
98
99//-------------------------------------------------
100//  device_start - device-specific startup
101//-------------------------------------------------
102
103void tms3556_device::device_start()
104{
105   // register for state saving
106   save_item(NAME(m_control_regs));
107   save_item(NAME(m_address_regs));
108   save_item(NAME(m_write_ptr));
109   save_item(NAME(m_reg_ptr));
110   save_item(NAME(m_reg_access_phase));
111   save_item(NAME(m_magical_mystery_flag));
112   save_item(NAME(m_scanline));
113   save_item(NAME(m_blink));
114   save_item(NAME(m_blink_count));
115   save_item(NAME(m_bg_color));
116   save_item(NAME(m_name_offset));
117   save_item(NAME(m_cg_flag));
118   save_item(NAME(m_char_line_counter));
119   save_item(NAME(m_dbl_h_phase));
120
121   machine().primary_screen->register_screen_bitmap(m_bitmap);
122}
123
124
125/*static const char *const tms3556_mode_names[] = { "DISPLAY OFF", "TEXT", "GRAPHIC", "MIXED" };*/
126
127
128UINT32 tms3556_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
129{
130   copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
131   return 0;
132}
133
134
135//-------------------------------------------------
136//  vram_r - VRAM read
137//-------------------------------------------------
138
139READ8_MEMBER( tms3556_device::vram_r )
140{
141   if (LOG) logerror("TMS3556 VRAM Read: %06x\n", offset);
142
143   if (m_magical_mystery_flag)
144   {
145      m_write_ptr = ((m_control_regs[2] << 8) | m_control_regs[1]) + 1;
146      m_magical_mystery_flag = 0;
147   }
148
149   return readbyte(m_address_regs[1]++);
150}
151
152//-------------------------------------------------
153//  vram_w - VRAM write
154//-------------------------------------------------
155
156WRITE8_MEMBER( tms3556_device::vram_w )
157{
158   if (LOG) logerror("TMS3556 VRAM Write: %06x = %02x\n", offset, data);
159
160   if (m_magical_mystery_flag)
161   {
162      m_write_ptr = (m_control_regs[2] << 8) | m_control_regs[1];
163      m_magical_mystery_flag = 0;
164   }
165
166   writebyte(m_write_ptr++, data);
167}
168
169
170//-------------------------------------------------
171//  reg_r - read from register port
172//-------------------------------------------------
173
174READ8_MEMBER( tms3556_device::reg_r )
175{
176   if (LOG) logerror("TMS3556 Reg Read: %06x\n", offset);
177
178   int reply = 0;
179
180   if (m_reg_ptr < 8)
181   {
182      reply = m_control_regs[m_reg_ptr];
183      m_reg_access_phase = 0;
184   }
185   else
186   {
187      // ???
188   }
189
190   return reply;
191}
192
193//-------------------------------------------------
194//  reg_w - write to register port
195//-------------------------------------------------
196
197WRITE8_MEMBER( tms3556_device::reg_w )
198{
199   if (LOG) logerror("TMS3556 Reg Write: %06x = %02x\n", offset, data);
200
201   if ((m_reg_access_phase == 3) && (data))
202      m_reg_access_phase = 0; /* ???????????? */
203
204   switch (m_reg_access_phase)
205   {
206   case 0:
207      m_reg_ptr = data & 0x0f;
208      m_reg_access_phase = 1;
209      break;
210
211   case 1:
212      if (m_reg_ptr < 8)
213      {
214         m_control_regs[m_reg_ptr] = data;
215         m_reg_access_phase = 0;
216         if (m_reg_ptr == 2)
217            m_magical_mystery_flag = 1;
218      }
219      else if (m_reg_ptr == 9)
220      {   /* I don't understand what is going on, but it is the only way to
221            get this to work */
222         m_address_regs[m_reg_ptr - 8] = ((m_control_regs[2] << 8) | m_control_regs[1]) + 1;
223         m_reg_access_phase = 0;
224         m_magical_mystery_flag = 0;
225      }
226      else
227      {
228         m_address_regs[m_reg_ptr - 8] = (m_control_regs[m_reg_ptr - 8] & 0xff00) | m_control_regs[1];
229         m_reg_access_phase = 2;
230         m_magical_mystery_flag = 0;
231      }
232      break;
233
234   case 2:
235      m_address_regs[m_reg_ptr - 8] = (m_control_regs[m_reg_ptr - 8] & 0x00ff) | (m_control_regs[2] << 8);
236      if ((m_reg_ptr <= 10) || (m_reg_ptr == 15))
237         m_address_regs[m_reg_ptr - 8]++;
238      else
239         m_address_regs[m_reg_ptr - 8] += 2;
240      m_reg_access_phase = 3;
241      break;
242
243   case 3:
244      m_reg_access_phase = 0;
245      break;
246   }
247}
248
249
250//-------------------------------------------------
251//  redraw code
252//-------------------------------------------------
253
254
255//-------------------------------------------------
256//  draw_line_empty - draw an empty line (used for
257//  top and bottom borders, and screen off mode)
258//-------------------------------------------------
259
260void tms3556_device::draw_line_empty(UINT16 *ln)
261{
262   int i;
263
264   for (i = 0; i < TMS3556_TOTAL_WIDTH; i++)
265#if TMS3556_DOUBLE_WIDTH
266      *ln++ = m_bg_color;
267#endif
268      *ln++ = m_bg_color;
269}
270
271
272//-------------------------------------------------
273//  draw_line_text_common - draw a line of text
274//  (called by draw_line_text and draw_line_mixed)
275//-------------------------------------------------
276
277void tms3556_device::draw_line_text_common(UINT16 *ln)
278{
279   int pattern, x, xx, i, name_offset;
280   UINT16 fg, bg;
281   offs_t nametbl_base;
282   offs_t patterntbl_base[4];
283   int name_hi, name_lo;
284   int pattern_ix;
285   int alphanumeric_mode, dbl_w, dbl_h, dbl_w_phase = 0;
286
287   nametbl_base = m_address_regs[2];
288   for (i = 0; i < 4; i++)
289      patterntbl_base[i] = m_address_regs[i + 3];
290
291   for (xx = 0; xx < TMS3556_LEFT_BORDER; xx++)
292#if TMS3556_DOUBLE_WIDTH
293      *ln++ = m_bg_color;
294#endif
295      *ln++ = m_bg_color;
296
297   name_offset = m_name_offset;
298
299   for (x = 0; x < 40; x++)
300   {
301      name_hi = readbyte(nametbl_base + name_offset);
302      name_lo = readbyte(nametbl_base + name_offset + 1);
303      pattern_ix = ((name_hi >> 2) & 2) | ((name_hi >> 4) & 1);
304      alphanumeric_mode = (pattern_ix < 2) || ((pattern_ix == 3) && !(m_control_regs[7] & 0x08));
305      fg = (name_hi >> 5) & 0x7;
306      if (alphanumeric_mode)
307      {
308         if (name_hi & 4)
309         {   /* inverted color */
310            bg = fg;
311            fg = m_bg_color;
312         }
313         else
314            bg = m_bg_color;
315         dbl_w = name_hi & 0x2;
316         dbl_h = name_hi & 0x1;
317      }
318      else
319      {
320         bg = name_hi & 0x7;
321         dbl_w = 0;
322         dbl_h = 0;
323      }
324      if ((name_lo & 0x80) && m_blink)
325         fg = bg;    /* blink off time */
326      if (! dbl_h)
327      {   /* single height */
328         pattern = readbyte(patterntbl_base[pattern_ix] + (name_lo & 0x7f) + 128 * m_char_line_counter);
329         if (m_char_line_counter == 0)
330            m_dbl_h_phase[x] = 0;
331      }
332      else
333      {   /* double height */
334         if (! m_dbl_h_phase[x])
335            /* first phase: pattern from upper half */
336            pattern = readbyte(patterntbl_base[pattern_ix] + (name_lo & 0x7f) + 128 * (5 + (m_char_line_counter >> 1)));
337         else
338            /* second phase: pattern from lower half */
339            pattern = readbyte(patterntbl_base[pattern_ix] + (name_lo & 0x7f) + 128 * (m_char_line_counter >> 1));
340         if (m_char_line_counter == 0)
341            m_dbl_h_phase[x] = !m_dbl_h_phase[x];
342      }
343      if (!dbl_w)
344      {   /* single width */
345         for (xx = 0; xx < 8; xx++)
346         {
347            UINT16 color = (pattern & 0x80) ? fg : bg;
348#if TMS3556_DOUBLE_WIDTH
349            *ln++ = color;
350#endif
351            *ln++ = color;
352            pattern <<= 1;
353         }
354         dbl_w_phase = 0;
355      }
356      else
357      {   /* double width */
358         if (dbl_w_phase)
359            /* second phase: display right half */
360            pattern <<= 4;
361         for (xx = 0; xx < 4; xx++)
362         {
363            UINT16 color = (pattern & 0x80) ? fg : bg;
364#if TMS3556_DOUBLE_WIDTH
365            *ln++ = color; *ln++ = color;
366#endif
367            *ln++ = color; *ln++ = color;
368            pattern <<= 1;
369         }
370         dbl_w_phase = !dbl_w_phase;
371      }
372      name_offset += 2;
373   }
374
375   for (xx = 0; xx < TMS3556_RIGHT_BORDER; xx++)
376#if TMS3556_DOUBLE_WIDTH
377      *ln++ = m_bg_color;
378#endif
379      *ln++ = m_bg_color;
380
381   if (m_char_line_counter == 0)
382      m_name_offset = name_offset;
383}
384
385
386//-------------------------------------------------
387//  draw_line_bitmap_common - draw a line of bitmap
388//  (called by draw_line_bitmap and draw_line_mixed)
389//-------------------------------------------------
390
391void tms3556_device::draw_line_bitmap_common(UINT16 *ln)
392{
393   int x, xx;
394   offs_t nametbl_base;
395   int name_b, name_g, name_r;
396
397   nametbl_base = m_address_regs[2];
398
399   for (xx = 0; xx < TMS3556_LEFT_BORDER; xx++)
400#if TMS3556_DOUBLE_WIDTH
401      *ln++ = m_bg_color;
402#endif
403      *ln++ = m_bg_color;
404
405   for (x = 0; x < 40; x++)
406   {
407      name_b = readbyte(nametbl_base + m_name_offset);
408      name_g = readbyte(nametbl_base + m_name_offset + 1);
409      name_r = readbyte(nametbl_base + m_name_offset + 2);
410      for (xx = 0; xx < 8; xx++)
411      {
412         UINT16 color = ((name_b >> 5) & 0x4) | ((name_g >> 6) & 0x2) | ((name_r >> 7) & 0x1);
413#if TMS3556_DOUBLE_WIDTH
414         *ln++ = color;
415#endif
416         *ln++ = color;
417         name_b <<= 1;
418         name_g <<= 1;
419         name_r <<= 1;
420      }
421      m_name_offset += 3;
422   }
423
424   for (xx = 0; xx < TMS3556_RIGHT_BORDER; xx++)
425#if TMS3556_DOUBLE_WIDTH
426      *ln++ = m_bg_color;
427#endif
428      *ln++ = m_bg_color;
429}
430
431
432//-------------------------------------------------
433//  draw_line_text - draw a line in text mode
434//-------------------------------------------------
435
436void tms3556_device::draw_line_text(UINT16 *ln)
437{
438   if (m_char_line_counter == 0)
439      m_char_line_counter = 10;
440   m_char_line_counter--;
441   draw_line_text_common(ln);
442}
443
444
445//-------------------------------------------------
446//  draw_line_bitmap - draw a line in bitmap mode
447//-------------------------------------------------
448
449void tms3556_device::draw_line_bitmap(UINT16 *ln)
450{
451   draw_line_bitmap_common(ln);
452   m_bg_color = (readbyte(m_address_regs[2] + m_name_offset) >> 5) & 0x7;
453   m_name_offset += 2;
454}
455
456
457//-------------------------------------------------
458//  draw_line_mixed - draw a line in mixed mode
459//-------------------------------------------------
460
461void tms3556_device::draw_line_mixed(UINT16 *ln)
462{
463   if (m_cg_flag)
464   {   /* bitmap line */
465      draw_line_bitmap_common(ln);
466      m_bg_color = (readbyte(m_address_regs[2] + m_name_offset) >> 5) & 0x7;
467      m_cg_flag = (readbyte(m_address_regs[2] + m_name_offset) >> 4) & 0x1;
468      m_name_offset += 2;
469   }
470   else
471   {   /* text line */
472      if (m_char_line_counter == 0)
473         m_char_line_counter = 10;
474      m_char_line_counter--;
475      draw_line_text_common(ln);
476      if (m_char_line_counter == 0)
477      {
478         m_bg_color = (readbyte(m_address_regs[2] + m_name_offset) >> 5) & 0x7;
479         m_cg_flag = (readbyte(m_address_regs[2] + m_name_offset) >> 4) & 0x1;
480         m_name_offset += 2;
481      }
482   }
483}
484
485
486//-------------------------------------------------
487//  draw_line - draw a line. If non-interlaced mode,
488//  duplicate the line.
489//-------------------------------------------------
490
491void tms3556_device::draw_line(bitmap_ind16 &bmp, int line)
492{
493   int double_lines = 0;
494   UINT16 *ln, *ln2 = NULL;
495
496//  if (m_control_regs[4] & 0x??)
497//  {   // interlaced mode
498//      ln = &bmp->pix16(line, m_field);
499//  }
500//  else
501   {   /* non-interlaced mode */
502      ln = &bmp.pix16(line);
503      ln2 = &bmp.pix16(line, 1);
504      double_lines = 1;
505   }
506
507   if ((line < TMS3556_TOP_BORDER) || (line >= (TMS3556_TOP_BORDER + 250)))
508   {
509      /* draw top and bottom borders */
510      draw_line_empty(ln);
511   }
512   else
513   {
514      /* draw useful area */
515      switch (m_control_regs[6] >> 6)
516      {
517      case TMS3556_MODE_OFF:
518         draw_line_empty(ln);
519         break;
520      case TMS3556_MODE_TEXT:
521         draw_line_text(ln);
522         break;
523      case TMS3556_MODE_BITMAP:
524         draw_line_bitmap(ln);
525         break;
526      case TMS3556_MODE_MIXED:
527         draw_line_mixed(ln);
528         break;
529      }
530   }
531
532   if (double_lines)
533   {
534      memcpy (ln2, ln, TMS3556_TOTAL_WIDTH * (TMS3556_DOUBLE_WIDTH ? 2 : 1));
535   }
536}
537
538
539//-------------------------------------------------
540//  interrupt_start_vblank - Do vblank-time tasks
541//-------------------------------------------------
542
543void tms3556_device::interrupt_start_vblank(void)
544{
545   /* at every frame, vdp switches fields */
546   //m_field = !m_field;
547
548   /* color blinking */
549   if (m_blink_count)
550      m_blink_count--;
551   if (!m_blink_count)
552   {
553      m_blink = !m_blink;
554      m_blink_count = 60; /*no idea what the real value is*/
555   }
556   /* reset background color */
557   m_bg_color = (m_control_regs[7] >> 5) & 0x7;
558   /* reset name offset */
559   m_name_offset = 0;
560   /* reset character line counter */
561   m_char_line_counter = 0;
562   /* reset c/g flag */
563   m_cg_flag = 0;
564   /* reset double height phase flags */
565   memset(m_dbl_h_phase, 0, sizeof(m_dbl_h_phase));
566}
567
568
569//-------------------------------------------------
570//  interrupt - scanline handler
571//-------------------------------------------------
572
573void tms3556_device::interrupt(running_machine &machine)
574{
575   /* check for start of vblank */
576   if (m_scanline == 310)  /*no idea what the real value is*/
577      interrupt_start_vblank();
578
579   /* render the current line */
580   if ((m_scanline >= 0) && (m_scanline < TMS3556_TOTAL_HEIGHT))
581   {
582      //if (!video_skip_this_frame())
583         draw_line(m_bitmap, m_scanline);
584   }
585
586   if (++m_scanline == 313)
587      m_scanline = 0;
588}
trunk/src/mess/video/mc6847.c
r21684r21685
1/*********************************************************************
2
3    mc6847.c
4
5    Implementation of Motorola 6847 video hardware chip
6
7    Sources:
8    M6847 data sheet
9    M6847T1 info from Rainbow magazine (10/1986-12/1986)
10
11
12    AG  AS  INTEXT  INV  GM2  GM1  GM0
13    --  --  ------  ---  ---  ---  ---
14     0   0       0    0    X    X    X  Internal Alphanumerics
15     0   0       0    1    X    X    X  Internal Alphanumerics Inverted
16     0   0       1    0    X    X    X  External Alphanumerics
17     0   0       1    1    X    X    X  External Alphanumerics Inverted
18     0   1       0    X    X    X    X  Semigraphics 4
19     0   1       1    X    X    X    X  Semigraphics 6
20     1   X       X    X    0    0    0  Graphics CG1 (64x64x4)    (16 bpr)
21     1   X       X    X    0    0    1  Graphics RG1 (128x64x2)   (16 bpr)
22     1   X       X    X    0    1    0  Graphics CG2 (128x64x4)   (32 bpr)
23     1   X       X    X    0    1    1  Graphics RG2 (128x96x2)   (16 bpr)
24     1   X       X    X    1    0    0  Graphics CG3 (128x96x4)   (32 bpr)
25     1   X       X    X    1    0    1  Graphics RG3 (128x192x2)  (16 bpr)
26     1   X       X    X    1    1    0  Graphics CG6 (128x192x4)  (32 bpr)
27     1   X       X    X    1    1    1  Graphics RG6 (256x192x2)  (32 bpr)
28
29    Note: The M6847 relies on an external source (typically a 6883 SAM chip)
30    to feed it bytes; so the BPR (bytes per row) figures are effectively
31    suggestions.  Mismatching modes is responsible for the semigraphic modes
32    on the CoCo.
33
34    Timing:    (source Motorola M6847 Manual, experimentation, SockMaster)
35
36    Horizontal Sync:  Total Period: 228 clock cycles
37        @ CLK(0) + DHS_F            - falling edge (high to low)
38        @ CLK(16.5) + DHS_R         - rising edge (low to high)
39        @ CLK(42)                   - left border start
40        @ CLK(71.5)                 - body start
41        @ CLK(199.5)                - right border start
42        @ CLK(228) + DHS_F          - falling edge (high to low)
43        ...
44
45    Field Sync: Total Period 262*228 clock cycles
46        @ CLK(0) + DFS_F            - falling edge (high to low)
47        @ CLK(32*228) + DFS_R       - rising edge (low to high)
48        @ CLK(262*228) + DFS_F      - falling edge (high to low) (262.5 for the M6847Y)
49
50    DHS_F:  550ns
51    DHS_R:  740ns
52    DFS_F:  520ns
53    DFS_R:  500ns
54
55    The M6847T1 is a later variant of the M6847 chip that implements lower
56    case support and some other nifty features.  This chip is in the CoCo 2B.
57    I have not been able to find a pinout diagram for this chip so I am
58    assuming that the extra text modes on the CoCo 2B are activated by the
59    GM2-0 pins.  This needs to be confirmed.
60
61    The MC6847 datasheet states that a scanline is 227.5 clock cycles,
62    but experimentation suggests that it is 228.  The game "Dragon Fire"
63    has a fine tuned loop that runs in 57 clock cycles by the CPU's
64    reckoning (228 actual clock cycles) and would not function correctly
65    if skew existed.  SockMaster has confirmed that scanlines are in
66    fact 228 clock cycles.
67
68**********************************************************************/
69
70
71#include "emu.h"
72#include "video/mc6847.h"
73
74
75//**************************************************************************
76//  CONSTANTS
77//**************************************************************************
78
79#define TOP_BORDER              25
80#define USE_HORIZONTAL_CLIP     false
81
82#define TIMER_HSYNC_PERIOD      (228)
83#define TIMER_HSYNC_OFF_TIME    (10.0)
84#define TIMER_HSYNC_ON_TIME     (TIMER_HSYNC_OFF_TIME + 16.5)
85#define TIMER_FSYNC_OFF_TIME    (TIMER_HSYNC_PERIOD * TOP_BORDER + TIMER_HSYNC_ON_TIME)
86#define TIMER_FSYNC_ON_TIME     (TIMER_HSYNC_PERIOD * (TOP_BORDER + 192) + TIMER_HSYNC_ON_TIME)
87
88#define LOG_SCANLINE            0
89#define LOG_HSYNC               0
90#define LOG_FSYNC               1
91#define LOG_FLUSH               1
92#define LOG_INPUT               0
93
94
95const UINT32 mc6847_base_device::s_palette[mc6847_base_device::PALETTE_LENGTH] =
96{
97   MAKE_RGB(0x07, 0xff, 0x00), /* GREEN */
98   MAKE_RGB(0xff, 0xff, 0x00), /* YELLOW */
99   MAKE_RGB(0x3b, 0x08, 0xff), /* BLUE */
100   MAKE_RGB(0xcc, 0x00, 0x3b), /* RED */
101   MAKE_RGB(0xff, 0xff, 0xff), /* BUFF */
102   MAKE_RGB(0x07, 0xe3, 0x99), /* CYAN */
103   MAKE_RGB(0xff, 0x1c, 0xff), /* MAGENTA */
104   MAKE_RGB(0xff, 0x81, 0x00), /* ORANGE */
105
106   MAKE_RGB(0x00, 0x00, 0x00), /* BLACK */
107   MAKE_RGB(0x07, 0xff, 0x00), /* GREEN */
108   MAKE_RGB(0x00, 0x00, 0x00), /* BLACK */
109   MAKE_RGB(0xff, 0xff, 0xff), /* BUFF */
110
111   MAKE_RGB(0x00, 0x7c, 0x00), /* ALPHANUMERIC DARK GREEN */
112   MAKE_RGB(0x07, 0xff, 0x00), /* ALPHANUMERIC BRIGHT GREEN */
113   MAKE_RGB(0x91, 0x00, 0x00), /* ALPHANUMERIC DARK ORANGE */
114   MAKE_RGB(0xff, 0x81, 0x00)  /* ALPHANUMERIC BRIGHT ORANGE */
115};
116
117
118
119//**************************************************************************
120//  FRIEND DEVICE
121//**************************************************************************
122
123//-------------------------------------------------
124//  ctor
125//-------------------------------------------------
126
127mc6847_friend_device::mc6847_friend_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock,
128      const UINT8 *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, bool supports_partial_body_scanlines)
129   : device_t(mconfig, type, name, tag, owner, clock),
130      m_character_map(fontdata, is_mc6847t1)
131{
132   m_tpfs = tpfs;
133   m_supports_partial_body_scanlines = supports_partial_body_scanlines;
134
135   // The MC6847 and the GIME apply field sync on different scanlines
136   m_field_sync_falling_edge_scanline = field_sync_falling_edge_scanline;
137}
138
139
140
141//-------------------------------------------------
142//  setup_timer - sets up a single timer relative
143//  to the clock
144//-------------------------------------------------
145
146ATTR_FORCE_INLINE emu_timer *mc6847_friend_device::setup_timer(device_timer_id id, double offset, double period)
147{
148   emu_timer *timer = timer_alloc(id);
149   timer->adjust(
150      attotime::from_ticks(offset * 4, m_clock * 4),
151      0,
152      attotime::from_ticks(period * 4, m_clock * 4));
153   return timer;
154}
155
156
157
158//-------------------------------------------------
159//  device_start - device-specific startup
160//-------------------------------------------------
161
162void mc6847_friend_device::device_start(void)
163{
164   /* create the timers */
165   m_frame_timer = setup_timer(    TIMER_FRAME,        0,                      m_tpfs * TIMER_HSYNC_PERIOD);
166   m_hsync_on_timer = setup_timer( TIMER_HSYNC_ON,     TIMER_HSYNC_ON_TIME,    TIMER_HSYNC_PERIOD);
167   m_hsync_off_timer = setup_timer(TIMER_HSYNC_OFF,    TIMER_HSYNC_OFF_TIME,   TIMER_HSYNC_PERIOD);
168   m_fsync_timer = timer_alloc(TIMER_FSYNC);
169
170   m_top_border_scanlines = 0;
171   m_body_scanlines = 0;
172   m_wide = false;
173   m_recording_scanline = false;
174   m_physical_scanline = 0;
175   m_logical_scanline_zone = 0;
176   m_field_sync = false;
177   m_horizontal_sync = false;
178   set_geometry(25, 192, false);
179
180   /* save states */
181   save_item(NAME(m_physical_scanline));
182   save_item(NAME(m_logical_scanline));
183   save_item(NAME(m_logical_scanline_zone));
184   save_item(NAME(m_horizontal_sync));
185   save_item(NAME(m_field_sync));
186
187   /* artifacting */
188   m_artifacter.setup_config(this);
189}
190
191
192
193//-------------------------------------------------
194//  device_start - device-specific reset
195//-------------------------------------------------
196
197void mc6847_friend_device::device_reset(void)
198{
199   device_t::device_reset();
200   m_video_changed = true;
201}
202
203
204
205//-------------------------------------------------
206//  device_post_load - device-specific post load
207//-------------------------------------------------
208
209void mc6847_friend_device::device_post_load(void)
210{
211   device_t::device_post_load();
212   m_video_changed = true;
213}
214
215
216
217//-------------------------------------------------
218//  update_field_sync_timer
219//-------------------------------------------------
220
221void mc6847_friend_device::update_field_sync_timer(void)
222{
223   /* are we expecting field sync? */
224   bool expected_field_sync = (m_physical_scanline < m_field_sync_falling_edge_scanline)
225      || (m_logical_scanline_zone == SCANLINE_ZONE_VBLANK);
226
227   /* determine the duration */
228   attotime duration = (expected_field_sync != m_field_sync) ? attotime::from_ticks(160, m_clock) : attotime::never;
229
230   /* and reset the timer */
231   m_fsync_timer->adjust(duration, expected_field_sync ? 1 : 0);
232}
233
234
235
236//-------------------------------------------------
237//  device_timer
238//-------------------------------------------------
239
240void mc6847_friend_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
241{
242   switch(id)
243   {
244      case TIMER_FRAME:       new_frame();                    break;
245      case TIMER_HSYNC_ON:    change_horizontal_sync(true);   break;
246      case TIMER_HSYNC_OFF:   change_horizontal_sync(false);  break;
247      case TIMER_FSYNC:       change_field_sync(param != 0);  break;
248   }
249}
250
251
252
253//-------------------------------------------------
254//  new_frame
255//-------------------------------------------------
256
257ATTR_FORCE_INLINE void mc6847_friend_device::new_frame(void)
258{
259   m_physical_scanline = 0;
260   m_logical_scanline = 0;
261   m_logical_scanline_zone = SCANLINE_ZONE_FRAME_END;
262}
263
264
265
266//-------------------------------------------------
267//  scanline_zone_string
268//-------------------------------------------------
269
270const char *mc6847_friend_device::scanline_zone_string(scanline_zone zone)
271{
272   const char *result;
273   switch(zone)
274   {
275      case SCANLINE_ZONE_TOP_BORDER:      result = "SCANLINE_ZONE_TOP_BORDER";    break;
276      case SCANLINE_ZONE_BODY:            result = "SCANLINE_ZONE_BODY";          break;
277      case SCANLINE_ZONE_BOTTOM_BORDER:   result = "SCANLINE_ZONE_BOTTOM_BORDER"; break;
278      case SCANLINE_ZONE_RETRACE:         result = "SCANLINE_ZONE_RETRACE";       break;
279      case SCANLINE_ZONE_VBLANK:          result = "SCANLINE_ZONE_VBLANK";        break;
280      case SCANLINE_ZONE_FRAME_END:       result = "SCANLINE_ZONE_FRAME_END";     break;
281      default:
282         fatalerror("Should not get here\n");
283         break;
284   }
285   return result;
286}
287
288
289
290//-------------------------------------------------
291//  change_horizontal_sync
292//-------------------------------------------------
293
294ATTR_FORCE_INLINE void mc6847_friend_device::change_horizontal_sync(bool line)
295{
296   g_profiler.start(PROFILER_USER1);
297   if (line && !m_horizontal_sync)
298   {
299      if (LOG_SCANLINE)
300         logerror("%s: change_horizontal_sync():  Recording scanline\n", describe_context());
301
302      /* first store the scanline */
303      g_profiler.start(PROFILER_USER2);
304      switch((scanline_zone) m_logical_scanline_zone)
305      {
306         case SCANLINE_ZONE_TOP_BORDER:
307         case SCANLINE_ZONE_BOTTOM_BORDER:
308            record_border_scanline(m_physical_scanline);
309            break;
310
311         case SCANLINE_ZONE_BODY:
312            m_recording_scanline = true;
313            if (m_partial_scanline_clocks > 0)
314               record_partial_body_scanline(m_physical_scanline, m_logical_scanline, m_partial_scanline_clocks, 228);
315            else
316               record_body_scanline(m_physical_scanline, m_logical_scanline);
317            m_recording_scanline = false;
318            break;
319
320         case SCANLINE_ZONE_RETRACE:
321         case SCANLINE_ZONE_VBLANK:
322         case SCANLINE_ZONE_FRAME_END:
323            /* do nothing */
324            break;
325      }
326      g_profiler.stop();
327
328      /* advance to next scanline */
329      next_scanline();
330   }
331
332   /* finally output horizontal sync */
333   if (line != m_horizontal_sync)
334   {
335      m_horizontal_sync = line;
336
337      /* log if apprpriate */
338      if (LOG_HSYNC)
339         logerror("%s: change_horizontal_sync(): line=%d\n", describe_context(), line ? 1 : 0);
340
341      /* invoke callback */
342      if (!m_res_out_hsync_func.isnull())
343         m_res_out_hsync_func(line);
344
345      /* call virtual function */
346      horizontal_sync_changed(m_horizontal_sync);
347   }
348
349   /* and update the field sync timer */
350   update_field_sync_timer();
351   g_profiler.stop();
352}
353
354
355
356//-------------------------------------------------
357//  change_field_sync
358//-------------------------------------------------
359
360ATTR_FORCE_INLINE void mc6847_friend_device::change_field_sync(bool line)
361{
362   /* output field sync */
363   if (line != m_field_sync)
364   {
365      m_field_sync = line;
366
367      /* log if apprpriate */
368      if (LOG_FSYNC)
369         logerror("%s: change_field_sync(): line=%d\n", describe_context(), line ? 1 : 0);
370
371      /* invoke callback */
372      if (!m_res_out_fsync_func.isnull())
373         m_res_out_fsync_func(line);
374
375      /* call virtual function */
376      field_sync_changed(m_field_sync);
377   }
378}
379
380
381
382//-------------------------------------------------
383//  next_scanline
384//-------------------------------------------------
385
386ATTR_FORCE_INLINE void mc6847_friend_device::next_scanline(void)
387{
388   /* advance to next scanline */
389   m_physical_scanline++;
390   m_logical_scanline++;
391   m_partial_scanline_clocks = 0;
392
393   /* check for movement into the next "zone" */
394   if (m_logical_scanline_zone == SCANLINE_ZONE_FRAME_END)
395   {
396      /* we're now in the top border */
397      m_logical_scanline = 0;
398      m_logical_scanline_zone = SCANLINE_ZONE_TOP_BORDER;
399   }
400   else if ((m_logical_scanline_zone < SCANLINE_ZONE_VBLANK) && (m_physical_scanline >= 25+192+26+6))
401   {
402      /* we're now into vblank */
403      m_logical_scanline = 0;
404      m_logical_scanline_zone = SCANLINE_ZONE_VBLANK;
405   }
406   else if ((m_logical_scanline_zone < SCANLINE_ZONE_RETRACE) && (m_physical_scanline >= 25+192+26))
407   {
408      /* we're now into retrace */
409      m_logical_scanline = 0;
410      m_logical_scanline_zone = SCANLINE_ZONE_RETRACE;
411   }
412   else if ((m_logical_scanline_zone == SCANLINE_ZONE_TOP_BORDER) && (m_logical_scanline >= m_top_border_scanlines))
413   {
414      /* we're now into the body */
415      m_logical_scanline = 0;
416      m_logical_scanline_zone = SCANLINE_ZONE_BODY;
417   }
418   else if ((m_logical_scanline_zone == SCANLINE_ZONE_BODY) && (m_logical_scanline >= m_body_scanlines))
419   {
420      /* we're now into the bottom border */
421      m_logical_scanline = 0;
422      m_logical_scanline_zone = SCANLINE_ZONE_BOTTOM_BORDER;
423      enter_bottom_border();
424   }
425}
426
427
428
429//-------------------------------------------------
430//  horizontal_sync_changed
431//-------------------------------------------------
432
433void mc6847_friend_device::horizontal_sync_changed(bool line)
434{
435}
436
437
438
439//-------------------------------------------------
440//  field_sync_changed
441//-------------------------------------------------
442
443void mc6847_friend_device::field_sync_changed(bool line)
444{
445}
446
447
448
449//-------------------------------------------------
450//  enter_bottom_border
451//-------------------------------------------------
452
453void mc6847_friend_device::enter_bottom_border(void)
454{
455}
456
457
458
459//-------------------------------------------------
460//  record_border_scanline
461//-------------------------------------------------
462
463void mc6847_friend_device::record_border_scanline(UINT16 physical_scanline)
464{
465}
466
467
468
469//-------------------------------------------------
470//  get_clocks_since_hsync
471//-------------------------------------------------
472
473INT32 mc6847_friend_device::get_clocks_since_hsync()
474{
475   UINT64 hsync_on_clocks = attotime_to_clocks(m_hsync_on_timer->start());
476   UINT64 current_clocks = attotime_to_clocks(machine().time());
477   return (INT32) (current_clocks - hsync_on_clocks);
478}
479
480
481
482//-------------------------------------------------
483//  video_flush
484//-------------------------------------------------
485
486void mc6847_friend_device::video_flush()
487{
488   // first, only flush if...
489   //   1.  We support partial scanlines
490   //   2.  We're not already recording
491   //   3.  We're in the body
492   if (m_supports_partial_body_scanlines && !m_recording_scanline && (m_logical_scanline_zone == SCANLINE_ZONE_BODY))
493   {
494      UINT32 new_partial_scanline_clocks = get_clocks_since_hsync();
495      if (m_partial_scanline_clocks < new_partial_scanline_clocks)
496      {
497         if (LOG_FLUSH)
498            logerror("%s: new_partial_scanline_clocks=%u\n", describe_context(), new_partial_scanline_clocks);
499
500         m_recording_scanline = true;
501         record_partial_body_scanline(m_physical_scanline, m_logical_scanline, m_partial_scanline_clocks, new_partial_scanline_clocks);
502         m_recording_scanline = false;
503
504         m_partial_scanline_clocks = new_partial_scanline_clocks;
505      }
506   }
507}
508
509
510
511//-------------------------------------------------
512//  describe_context
513//-------------------------------------------------
514
515const char *mc6847_friend_device::describe_context(void)
516{
517   static char buffer[128];
518   snprintf(buffer, ARRAY_LENGTH(buffer), "%s (scanline %s:%d)",
519      machine().describe_context(),
520      scanline_zone_string((scanline_zone) m_logical_scanline_zone),
521      m_logical_scanline);
522   return buffer;
523}
524
525
526
527//**************************************************************************
528//  BASE DEVICE
529//**************************************************************************
530
531//-------------------------------------------------
532//  ctor
533//-------------------------------------------------
534
535mc6847_base_device::mc6847_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const UINT8 *fontdata, double tpfs)
536   :   mc6847_friend_device(mconfig, type, name, tag, owner, clock, fontdata, (type == MC6847T1_NTSC) || (type == MC6847T1_PAL), tpfs, 25+191, true)
537{
538   m_palette = s_palette;
539
540   for (int i = 0; i < ARRAY_LENGTH(s_palette); i++)
541   {
542      m_bw_palette[i] = black_and_white(s_palette[i]);
543   }
544}
545
546
547
548//-------------------------------------------------
549//  setup_fixed_mode - sets up a particular video
550//  mode bit with a decb callback
551//-------------------------------------------------
552
553void mc6847_base_device::setup_fixed_mode(struct devcb_read_line callback, UINT8 mode)
554{
555   if (callback.type == DEVCB_TYPE_NULL)
556   {
557      // do nothing
558   }
559   else if (callback.type == DEVCB_TYPE_CONSTANT && (callback.index == 0 || callback.index == 1))
560   {
561      // this mode is fixed
562      m_fixed_mode |= (callback.index ? mode : 0x00);
563      m_fixed_mode_mask |= mode;
564   }
565   else
566   {
567      // for reasons of performance, we currently only support DEVCB_NULL,
568      // DEVCB_LINE_GND and DEVCB_LINE_VCC
569      emu_fatalerror("mc6847 does not support this callback type for mode bits\n");
570   }
571}
572
573
574
575//-------------------------------------------------
576//  device_start - device-specific startup
577//-------------------------------------------------
578
579void mc6847_base_device::device_start()
580{
581   const mc6847_interface *config = (const mc6847_interface *) static_config();
582   assert(config);
583
584   /* inherited function */
585   mc6847_friend_device::device_start();
586
587   /* setup */
588   memset(m_data, 0, sizeof(m_data));
589
590   /* resolve callbacks */
591   m_res_input_func.resolve(config->m_input_func, *this);
592   m_res_out_hsync_func.resolve(config->m_out_hsync_func, *this);
593   m_res_out_fsync_func.resolve(config->m_out_fsync_func, *this);
594   m_get_char_rom = config->m_get_char_rom;
595
596   /* set up fixed mode */
597   m_fixed_mode = 0x00;
598   m_fixed_mode_mask = 0x00;
599   setup_fixed_mode(config->m_in_gm2_func,     MODE_GM2);
600   setup_fixed_mode(config->m_in_gm1_func,     MODE_GM1);
601   setup_fixed_mode(config->m_in_gm0_func,     MODE_GM0);
602   setup_fixed_mode(config->m_in_intext_func,  MODE_INTEXT);
603   setup_fixed_mode(config->m_in_inv_func,     MODE_INV);
604   setup_fixed_mode(config->m_in_as_func,      MODE_AS);
605   setup_fixed_mode(config->m_in_ag_func,      MODE_AG);
606   setup_fixed_mode(config->m_in_css_func,     MODE_CSS);
607
608   m_dirty = false;
609
610   /* state save */
611   save_item(NAME(m_dirty));
612   save_item(NAME(m_mode));
613
614   /* colors */
615   m_palette = config->m_black_and_white ? m_bw_palette : s_palette;
616}
617
618
619
620//-------------------------------------------------
621//  device_reset - device-specific reset
622//-------------------------------------------------
623
624void mc6847_base_device::device_reset()
625{
626   mc6847_friend_device::device_reset();
627   m_mode = m_fixed_mode;
628}
629
630
631
632//-------------------------------------------------
633//  input
634//-------------------------------------------------
635
636UINT8 mc6847_base_device::input(UINT16 address)
637{
638   UINT8 data = m_res_input_func(address);
639   if (LOG_INPUT)
640      logerror("%s: input: address=0x%04X data=0x%02X\n", describe_context(), address, data);
641   return data;
642}
643
644
645
646//-------------------------------------------------
647//  record_scanline_res
648//-------------------------------------------------
649
650template<int sample_count, int yres>
651void mc6847_base_device::record_scanline_res(int scanline, INT32 start_pos, INT32 end_pos)
652{
653   UINT8 current_sample_count = (start_pos > 0) ? m_data[scanline].m_sample_count : 0;
654
655   // main loop
656   for (INT32 pos = start_pos; pos < end_pos; pos++)
657   {
658      // set address at beginning of line
659      if (pos == 0)
660         m_video_address = scanline / (192 / yres) * sample_count;
661
662      if ((sample_count == 32) || ((pos % 1) == 0))
663      {
664         // input data
665         UINT8 data = input(m_video_address++);
666
667         if (pos < 32)
668         {
669            // update values
670            //assert(current_sample_count >= 0);
671            assert(current_sample_count < ARRAY_LENGTH(m_data[scanline].m_mode));
672            update_value(&m_data[scanline].m_mode[current_sample_count], simplify_mode(data, m_mode));
673            update_value(&m_data[scanline].m_data[current_sample_count], data);
674            current_sample_count++;
675         }
676      }
677   }
678
679   // update sample count
680   update_value(&m_data[scanline].m_sample_count, current_sample_count);
681}
682
683
684
685//-------------------------------------------------
686//  record_body_scanline
687//-------------------------------------------------
688
689ATTR_FORCE_INLINE void mc6847_base_device::record_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_pos, INT32 end_pos)
690{
691   // sanity checks
692   assert(scanline < 192);
693
694   if (m_mode & MODE_AG)
695   {
696      switch(m_mode & (MODE_GM2|MODE_GM1|MODE_GM0))
697      {
698         case 0:
699         case MODE_GM0:
700            record_scanline_res<16, 64>(scanline, start_pos, end_pos);
701            break;
702
703         case MODE_GM1:
704            record_scanline_res<32, 64>(scanline, start_pos, end_pos);
705            break;
706
707         case MODE_GM1|MODE_GM0:
708            record_scanline_res<16, 96>(scanline, start_pos, end_pos);
709            break;
710
711         case MODE_GM2:
712            record_scanline_res<32, 96>(scanline, start_pos, end_pos);
713            break;
714
715         case MODE_GM2|MODE_GM0:
716            record_scanline_res<16, 192>(scanline, start_pos, end_pos);
717            break;
718
719         case MODE_GM2|MODE_GM1:
720         case MODE_GM2|MODE_GM1|MODE_GM0:
721            record_scanline_res<32, 192>(scanline, start_pos, end_pos);
722            break;
723
724         default:
725            /* should not get here */
726            fatalerror("should not get here\n");
727            break;
728      }
729   }
730   else
731   {
732      record_scanline_res<32, 16>(scanline, start_pos, end_pos);
733   }
734}
735
736
737
738//-------------------------------------------------
739//  record_body_scanline
740//-------------------------------------------------
741
742void mc6847_base_device::record_body_scanline(UINT16 physical_scanline, UINT16 scanline)
743{
744   record_body_scanline(physical_scanline, scanline, 0, 32);
745}
746
747
748
749//-------------------------------------------------
750//  record_partial_body_scanline
751//-------------------------------------------------
752
753void mc6847_base_device::record_partial_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_clock, INT32 end_clock)
754{
755   INT32 start_pos = MAX(scanline_position_from_clock(start_clock), 0);
756   INT32 end_pos = MIN(scanline_position_from_clock(end_clock), 42);
757
758   if (start_pos < end_pos)
759      record_body_scanline(physical_scanline, scanline, start_pos, end_pos);
760}
761
762
763
764//-------------------------------------------------
765//  scanline_position_from_clock
766//-------------------------------------------------
767
768INT32 mc6847_base_device::scanline_position_from_clock(INT32 clocks_since_hsync)
769{
770   return (clocks_since_hsync - 20) / 4;
771}
772
773
774
775//-------------------------------------------------
776//  field_sync_changed
777//-------------------------------------------------
778
779void mc6847_base_device::field_sync_changed(bool line)
780{
781   /* when field sync is on, the DA* enter the Hi-Z state */
782   if (line && !m_res_input_func.isnull())
783      m_res_input_func(~0);
784}
785
786
787
788//-------------------------------------------------
789//  border_value
790//-------------------------------------------------
791
792ATTR_FORCE_INLINE mc6847_base_device::pixel_t mc6847_base_device::border_value(UINT8 mode, const pixel_t *palette, bool is_mc6847t1)
793{
794   pixel_t result;
795   switch(mc6847_friend_device::border_value(mode, is_mc6847t1))
796   {
797      case BORDER_COLOR_BLACK:
798         result = palette[8];
799         break;
800      case BORDER_COLOR_GREEN:
801         result = palette[0];
802         break;
803      case BORDER_COLOR_WHITE:
804         result = palette[4];
805         break;
806      case BORDER_COLOR_ORANGE:
807         result = palette[7];
808         break;
809      default:
810         fatalerror("Should not get here\n");
811         break;
812   }
813   return result;
814}
815
816
817
818//-------------------------------------------------
819//  update
820//-------------------------------------------------
821
822UINT32 mc6847_base_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
823{
824   int base_x = 32;
825   int base_y = 25;
826   int x, x2, y;
827   bool is_mc6847t1 = (type() == MC6847T1_NTSC) || (type() == MC6847T1_PAL);
828   int min_x = USE_HORIZONTAL_CLIP ? cliprect.min_x : 0;
829   int max_x = USE_HORIZONTAL_CLIP ? cliprect.max_x : (base_x * 2 + 256 - 1);
830   int min_y = cliprect.min_y;
831   int max_y = cliprect.max_y;
832   const pixel_t *palette = m_palette;
833
834   /* if the video didn't change, indicate as much */
835   if (!has_video_changed())
836      return UPDATE_HAS_NOT_CHANGED;
837
838   /* top border */
839   for (y = min_y; y < base_y; y++)
840   {
841      for (x = min_x; x <= max_x; x++)
842      {
843         *bitmap_addr(bitmap, y, x) = border_value(m_data[0].m_mode[0], palette, is_mc6847t1);
844      }
845   }
846
847   for (y = MAX(0, min_y - base_y); y <= MIN(192, max_y - base_y); y++)
848   {
849      /* left border */
850      for (x = min_x; x < base_x; x++)
851      {
852         *bitmap_addr(bitmap, y + base_y, x) = border_value(m_data[y].m_mode[0], palette, is_mc6847t1);
853      }
854
855      /* body */
856      x = 0;
857      int width = m_data[y].m_sample_count;
858      pixel_t *RESTRICT pixels = bitmap_addr(bitmap, base_y + y, base_x);
859      while(x < width)
860      {
861         /* determine how many bytes exist for which the mode is identical */
862         for (x2 = x + 1; (x2 < width) && (m_data[y].m_mode[x] == m_data[y].m_mode[x2]); x2++)
863            ;
864
865         /* emit the samples */
866         pixels += emit_mc6847_samples<1>(
867            m_data[y].m_mode[x],
868            &m_data[y].m_data[x],
869            x2 - x,
870            pixels,
871            m_palette,
872            m_get_char_rom,
873            x,
874            y);
875
876         /* update x */
877         x = x2;
878      }
879
880      /* right border */
881      for (x = base_x + 256; x <= max_x; x++)
882      {
883         *bitmap_addr(bitmap, y + base_y, x) = border_value(m_data[y].m_mode[width - 1], palette, is_mc6847t1);
884      }
885
886      /* artifacting */
887      m_artifacter.process_artifacts<1>(bitmap_addr(bitmap, y + base_y, base_x), m_data[y].m_mode[0], palette);
888   }
889
890   /* bottom border */
891   for (y = base_y + 192; y <= max_y; y++)
892   {
893      for (x = min_x; x <= max_x; x++)
894      {
895         int width = m_data[191].m_sample_count;
896         *bitmap_addr(bitmap, y, x) = border_value(m_data[191].m_mode[width - 1], palette, is_mc6847t1);
897      }
898   }
899   return 0;
900}
901
902
903
904//**************************************************************************
905//  CHARACTER MAP
906//**************************************************************************
907
908mc6847_friend_device::character_map::character_map(const UINT8 *text_fontdata, bool is_mc6847t1)
909{
910   int mode, i;
911
912   // set up font data
913   for (i = 0; i < 64*12; i++)
914   {
915      m_text_fontdata_inverse[i]              = text_fontdata[i] ^ 0xFF;
916      m_text_fontdata_lower_case[i]           = text_fontdata[i + (i < 32*12 ? 64*12 : 0)] ^ (i < 32*12 ? 0xFF : 0x00);
917      m_text_fontdata_lower_case_inverse[i]   = m_text_fontdata_lower_case[i] ^ 0xFF;
918   }
919
920   // loop through all modes
921   for (mode = 0; mode < sizeof(m_entries) / sizeof(m_entries[0]); mode++)
922   {
923      const UINT8 *fontdata;
924      UINT8 character_mask;
925      UINT8 color_shift_0 = 0;
926      UINT8 color_shift_1 = 0;
927      UINT8 color_mask_0 = 0x00;
928      UINT8 color_mask_1 = 0x00;
929      UINT16 color_base_0;
930      UINT16 color_base_1;
931
932      if ((mode & MODE_INTEXT) && !is_mc6847t1)
933      {
934         // semigraphics 6
935         fontdata            = semigraphics6_fontdata8x12;
936         character_mask      = 0x3F;
937         color_base_0        = 8;
938         color_base_1        = mode & MODE_CSS ? 4 : 0;
939         color_shift_1       = 6;
940         color_mask_1        = 0x03;
941      }
942      else if (mode & MODE_AS)
943      {
944         // semigraphics 4
945         fontdata            = semigraphics4_fontdata8x12;
946         character_mask      = 0x0F;
947         color_base_0        = 8;
948         color_base_1        = 0;
949         color_shift_1       = 4;
950         color_mask_1        = 0x07;
951      }
952      else
953      {
954         // text
955         bool is_lower_case  = is_mc6847t1 && ((mode & MODE_INV) == 0) && (mode & MODE_GM0);
956         bool is_inverse1    = (mode & MODE_INV) ? true : false;
957         bool is_inverse2    = is_mc6847t1 && (mode & MODE_GM1);
958         bool is_inverse     = (is_inverse1 && !is_inverse2) || (!is_inverse1 && is_inverse2);
959         fontdata            = is_inverse
960                           ? (is_lower_case ? m_text_fontdata_lower_case_inverse : m_text_fontdata_inverse)
961                           : (is_lower_case ? m_text_fontdata_lower_case : text_fontdata);
962         character_mask      = 0x3F;
963         color_base_0        = (mode & MODE_CSS ? 14 : 12);
964         color_base_1        = (mode & MODE_CSS ? 15 : 13);
965      }
966
967      // populate the entry
968      memset(&m_entries[mode], 0, sizeof(m_entries[mode]));
969      m_entries[mode].m_fontdata          = fontdata;
970      m_entries[mode].m_character_mask    = character_mask;
971      m_entries[mode].m_color_shift_0     = color_shift_0;
972      m_entries[mode].m_color_shift_1     = color_shift_1;
973      m_entries[mode].m_color_mask_0      = color_mask_0;
974      m_entries[mode].m_color_mask_1      = color_mask_1;
975      m_entries[mode].m_color_base_0      = color_base_0;
976      m_entries[mode].m_color_base_1      = color_base_1;
977   }
978}
979
980
981
982//-------------------------------------------------
983//  pal_round_fontdata8x12
984//-------------------------------------------------
985
986const UINT8 mc6847_friend_device::pal_round_fontdata8x12[] =
987{
988   0x00, 0x00, 0x38, 0x44, 0x04, 0x34, 0x4C, 0x4C, 0x38, 0x00, 0x00, 0x00,
989   0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x00, 0x00, 0x00,
990   0x00, 0x00, 0x78, 0x24, 0x24, 0x38, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
991   0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
992   0x00, 0x00, 0x78, 0x24, 0x24, 0x24, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
993   0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
994   0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
995   0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x4C, 0x44, 0x38, 0x00, 0x00, 0x00,
996   0x00, 0x00, 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
997   0x00, 0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
998   0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
999   0x00, 0x00, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
1000   0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
1001   0x00, 0x00, 0x44, 0x6C, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1002   0x00, 0x00, 0x44, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x44, 0x00, 0x00, 0x00,
1003   0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1004   0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
1005   0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
1006   0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
1007   0x00, 0x00, 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1008   0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1009   0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1010   0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00,
1011   0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x54, 0x6C, 0x44, 0x00, 0x00, 0x00,
1012   0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00, 0x00, 0x00,
1013   0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1014   0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7C, 0x00, 0x00, 0x00,
1015   0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00, 0x00,
1016   0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
1017   0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
1018   0x00, 0x00, 0x10, 0x38, 0x54, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1019   0x00, 0x00, 0x00, 0x10, 0x20, 0x7C, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00,
1020   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1021   0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
1022   0x00, 0x00, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1023   0x00, 0x00, 0x28, 0x28, 0x7C, 0x28, 0x7C, 0x28, 0x28, 0x00, 0x00, 0x00,
1024   0x00, 0x00, 0x10, 0x3C, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00, 0x00, 0x00,
1025   0x00, 0x00, 0x60, 0x64, 0x08, 0x10, 0x20, 0x4C, 0x0C, 0x00, 0x00, 0x00,
1026   0x00, 0x00, 0x20, 0x50, 0x50, 0x20, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
1027   0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1028   0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
1029   0x00, 0x00, 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
1030   0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00,
1031   0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
1032   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x40, 0x00, 0x00,
1033   0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1034   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1035   0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
1036   0x00, 0x00, 0x38, 0x44, 0x4C, 0x54, 0x64, 0x44, 0x38, 0x00, 0x00, 0x00,
1037   0x00, 0x00, 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1038   0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
1039   0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1040   0x00, 0x00, 0x08, 0x18, 0x28, 0x48, 0x7C, 0x08, 0x08, 0x00, 0x00, 0x00,
1041   0x00, 0x00, 0x7C, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1042   0x00, 0x00, 0x38, 0x40, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1043   0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00,
1044   0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1045   0x00, 0x00, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x38, 0x00, 0x00, 0x00,
1046   0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
1047   0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00,
1048   0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
1049   0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
1050   0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
1051   0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
1052
1053   /* Lower case */
1054   0x00, 0x00, 0x18, 0x24, 0x20, 0x70, 0x20, 0x24, 0x78, 0x00, 0x00, 0x00,
1055   0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x3C, 0x44, 0x3C, 0x00, 0x00, 0x00,
1056   0x00, 0x00, 0x40, 0x40, 0x58, 0x64, 0x44, 0x64, 0x58, 0x00, 0x00, 0x00,
1057   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
1058   0x00, 0x00, 0x04, 0x04, 0x34, 0x4C, 0x44, 0x4C, 0x34, 0x00, 0x00, 0x00,
1059   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x7C, 0x40, 0x38, 0x00, 0x00, 0x00,
1060   0x00, 0x00, 0x08, 0x14, 0x10, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1061   0x00, 0x00, 0x00, 0x00, 0x34, 0x4C, 0x44, 0x4C, 0x34, 0x04, 0x38, 0x00,
1062   0x00, 0x00, 0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1063   0x00, 0x00, 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1064   0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00,
1065   0x00, 0x00, 0x40, 0x40, 0x48, 0x50, 0x60, 0x50, 0x48, 0x00, 0x00, 0x00,
1066   0x00, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1067   0x00, 0x00, 0x00, 0x00, 0x78, 0x54, 0x54, 0x54, 0x54, 0x00, 0x00, 0x00,
1068   0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1069   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1070   0x00, 0x00, 0x00, 0x00, 0x78, 0x44, 0x44, 0x44, 0x78, 0x40, 0x40, 0x00,
1071   0x00, 0x00, 0x00, 0x00, 0x3C, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x00,
1072   0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
1073   0x00, 0x00, 0x00, 0x00, 0x3C, 0x40, 0x38, 0x04, 0x78, 0x00, 0x00, 0x00,
1074   0x00, 0x00, 0x20, 0x20, 0x70, 0x20, 0x20, 0x24, 0x18, 0x00, 0x00, 0x00,
1075   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x4C, 0x34, 0x00, 0x00, 0x00,
1076   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00,
1077   0x00, 0x00, 0x00, 0x00, 0x44, 0x54, 0x54, 0x28, 0x28, 0x00, 0x00, 0x00,
1078   0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00,
1079   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x38, 0x00, 0x00,
1080   0x00, 0x00, 0x00, 0x00, 0x7C, 0x08, 0x10, 0x20, 0x7C, 0x00, 0x00, 0x00,
1081   0x00, 0x00, 0x08, 0x10, 0x10, 0x20, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,
1082   0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1083   0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00,
1084   0x00, 0x00, 0x20, 0x54, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1085   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00
1086};
1087
1088
1089
1090//-------------------------------------------------
1091//  pal_square_fontdata8x12
1092//-------------------------------------------------
1093
1094const UINT8 mc6847_friend_device::pal_square_fontdata8x12[] =
1095{
1096   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x1A, 0x2A, 0x2A, 0x1C, 0x00, 0x00,
1097   0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x00, 0x00,
1098   0x00, 0x00, 0x00, 0x3C, 0x12, 0x12, 0x1C, 0x12, 0x12, 0x3C, 0x00, 0x00,
1099   0x00, 0x00, 0x00, 0x1C, 0x22, 0x20, 0x20, 0x20, 0x22, 0x1C, 0x00, 0x00,
1100   0x00, 0x00, 0x00, 0x3C, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3C, 0x00, 0x00,
1101   0x00, 0x00, 0x00, 0x3E, 0x20, 0x20, 0x3C, 0x20, 0x20, 0x3E, 0x00, 0x00,
1102   0x00, 0x00, 0x00, 0x3E, 0x20, 0x20, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00,
1103   0x00, 0x00, 0x00, 0x1E, 0x20, 0x20, 0x26, 0x22, 0x22, 0x1E, 0x00, 0x00,
1104   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22, 0x00, 0x00,
1105   0x00, 0x00, 0x00, 0x1C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1106   0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x22, 0x22, 0x1C, 0x00, 0x00,
1107   0x00, 0x00, 0x00, 0x22, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22, 0x00, 0x00,
1108   0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3E, 0x00, 0x00,
1109   0x00, 0x00, 0x00, 0x22, 0x36, 0x2A, 0x2A, 0x22, 0x22, 0x22, 0x00, 0x00,
1110   0x00, 0x00, 0x00, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x22, 0x22, 0x00, 0x00,
1111   0x00, 0x00, 0x00, 0x3E, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3E, 0x00, 0x00,
1112   0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00,
1113   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x2A, 0x24, 0x1A, 0x00, 0x00,
1114   0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x3C, 0x28, 0x24, 0x22, 0x00, 0x00,
1115   0x00, 0x00, 0x00, 0x1C, 0x22, 0x10, 0x08, 0x04, 0x22, 0x1C, 0x00, 0x00,
1116   0x00, 0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1117   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00,
1118   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00,
1119   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x2A, 0x2A, 0x36, 0x22, 0x00, 0x00,
1120   0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00,
1121   0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1122   0x00, 0x00, 0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x3E, 0x00, 0x00,
1123   0x00, 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00,
1124   0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00,
1125   0x00, 0x00, 0x00, 0x0E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E, 0x00, 0x00,
1126   0x00, 0x00, 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1127   0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x3E, 0x10, 0x08, 0x00, 0x00, 0x00,
1128   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1129   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00,
1130   0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1131   0x00, 0x00, 0x00, 0x14, 0x14, 0x36, 0x00, 0x36, 0x14, 0x14, 0x00, 0x00,
1132   0x00, 0x00, 0x00, 0x08, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x08, 0x00, 0x00,
1133   0x00, 0x00, 0x00, 0x32, 0x32, 0x04, 0x08, 0x10, 0x26, 0x26, 0x00, 0x00,
1134   0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x10, 0x2A, 0x24, 0x1A, 0x00, 0x00,
1135   0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1136   0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00,
1137   0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00, 0x00,
1138   0x00, 0x00, 0x00, 0x00, 0x08, 0x1C, 0x3E, 0x1C, 0x08, 0x00, 0x00, 0x00,
1139   0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x00,
1140   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x10, 0x20, 0x00, 0x00,
1141   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00,
1142   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
1143   0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00,
1144   0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00, 0x00,
1145   0x00, 0x00, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1146   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x1C, 0x20, 0x20, 0x3E, 0x00, 0x00,
1147   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x0C, 0x02, 0x22, 0x1C, 0x00, 0x00,
1148   0x00, 0x00, 0x00, 0x04, 0x0C, 0x14, 0x3E, 0x04, 0x04, 0x04, 0x00, 0x00,
1149   0x00, 0x00, 0x00, 0x3E, 0x20, 0x3C, 0x02, 0x02, 0x22, 0x1C, 0x00, 0x00,
1150   0x00, 0x00, 0x00, 0x1C, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x1C, 0x00, 0x00,
1151   0x00, 0x00, 0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00,
1152   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x1C, 0x22, 0x22, 0x1C, 0x00, 0x00,
1153   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x1E, 0x02, 0x02, 0x1C, 0x00, 0x00,
1154   0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
1155   0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00,
1156   0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00,
1157   0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00,
1158   0x00, 0x00, 0x00, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00,
1159   0x00, 0x00, 0x00, 0x18, 0x24, 0x04, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00,
1160
1161   /* Lower case */
1162   0x00, 0x00, 0x00, 0x0C, 0x12, 0x10, 0x38, 0x10, 0x12, 0x3C, 0x00, 0x00,
1163   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x02, 0x1E, 0x22, 0x1E, 0x00, 0x00,
1164   0x00, 0x00, 0x00, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x22, 0x3C, 0x00, 0x00,
1165   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x20, 0x20, 0x20, 0x1C, 0x00, 0x00,
1166   0x00, 0x00, 0x00, 0x02, 0x02, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x00, 0x00,
1167   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x3E, 0x20, 0x1C, 0x00, 0x00,
1168   0x00, 0x00, 0x00, 0x0C, 0x12, 0x10, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00,
1169   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x1C,
1170   0x00, 0x00, 0x00, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00,
1171   0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1172   0x00, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x24, 0x18,
1173   0x00, 0x00, 0x00, 0x20, 0x20, 0x24, 0x28, 0x38, 0x24, 0x22, 0x00, 0x00,
1174   0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1175   0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x2A, 0x2A, 0x2A, 0x2A, 0x00, 0x00,
1176   0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00, 0x00,
1177   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00,
1178   0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x22, 0x3C, 0x20, 0x20,
1179   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x03,
1180   0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
1181   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x00, 0x00,
1182   0x00, 0x00, 0x00, 0x10, 0x3C, 0x10, 0x10, 0x10, 0x12, 0x0C, 0x00, 0x00,
1183   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x26, 0x1A, 0x00, 0x00,
1184   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00,
1185   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x2A, 0x2A, 0x1C, 0x14, 0x00, 0x00,
1186   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00,
1187   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x1C,
1188   0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x04, 0x08, 0x10, 0x3E, 0x00, 0x00,
1189   0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x20, 0x10, 0x10, 0x08, 0x00, 0x00,
1190   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00,
1191   0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, 0x00,
1192   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00, 0x00,
1193   0x00, 0x00, 0x00, 0x08, 0x04, 0x3E, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00,
1194};
1195
1196
1197
1198//-------------------------------------------------
1199//  ntsc_round_fontdata8x12
1200//-------------------------------------------------
1201
1202const UINT8 mc6847_friend_device::ntsc_round_fontdata8x12[] =
1203{
1204   0x00, 0x00, 0x38, 0x44, 0x04, 0x34, 0x4C, 0x4C, 0x38, 0x00, 0x00, 0x00,
1205   0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x00, 0x00, 0x00,
1206   0x00, 0x00, 0x78, 0x24, 0x24, 0x38, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
1207   0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
1208   0x00, 0x00, 0x78, 0x24, 0x24, 0x24, 0x24, 0x24, 0x78, 0x00, 0x00, 0x00,
1209   0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
1210   0x00, 0x00, 0x7C, 0x40, 0x40, 0x70, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
1211   0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x4C, 0x44, 0x38, 0x00, 0x00, 0x00,
1212   0x00, 0x00, 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1213   0x00, 0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1214   0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1215   0x00, 0x00, 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
1216   0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
1217   0x00, 0x00, 0x44, 0x6C, 0x54, 0x54, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1218   0x00, 0x00, 0x44, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x44, 0x00, 0x00, 0x00,
1219   0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1220   0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
1221   0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
1222   0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x50, 0x48, 0x44, 0x00, 0x00, 0x00,
1223   0x00, 0x00, 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1224   0x00, 0x00, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1225   0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1226   0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00,
1227   0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x54, 0x6C, 0x44, 0x00, 0x00, 0x00,
1228   0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00, 0x00, 0x00,
1229   0x00, 0x00, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1230   0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7C, 0x00, 0x00, 0x00,
1231   0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00, 0x00,
1232   0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
1233   0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
1234   0x00, 0x00, 0x10, 0x38, 0x54, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1235   0x00, 0x00, 0x00, 0x10, 0x20, 0x7C, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00,
1236   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237   0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
1238   0x00, 0x00, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1239   0x00, 0x00, 0x28, 0x28, 0x7C, 0x28, 0x7C, 0x28, 0x28, 0x00, 0x00, 0x00,
1240   0x00, 0x00, 0x10, 0x3C, 0x50, 0x38, 0x14, 0x78, 0x10, 0x00, 0x00, 0x00,
1241   0x00, 0x00, 0x60, 0x64, 0x08, 0x10, 0x20, 0x4C, 0x0C, 0x00, 0x00, 0x00,
1242   0x00, 0x00, 0x20, 0x50, 0x50, 0x20, 0x54, 0x48, 0x34, 0x00, 0x00, 0x00,
1243   0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1244   0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
1245   0x00, 0x00, 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
1246   0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00,
1247   0x00, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
1248   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x40, 0x00, 0x00,
1249   0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1251   0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
1252   0x00, 0x00, 0x38, 0x44, 0x4C, 0x54, 0x64, 0x44, 0x38, 0x00, 0x00, 0x00,
1253   0x00, 0x00, 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1254   0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00,
1255   0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1256   0x00, 0x00, 0x08, 0x18, 0x28, 0x48, 0x7C, 0x08, 0x08, 0x00, 0x00, 0x00,
1257   0x00, 0x00, 0x7C, 0x40, 0x78, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
1258   0x00, 0x00, 0x38, 0x40, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1259   0x00, 0x00, 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00, 0x00,
1260   0x00, 0x00, 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1261   0x00, 0x00, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x38, 0x00, 0x00, 0x00,
1262   0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
1263   0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00,
1264   0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00,
1265   0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
1266   0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00,
1267   0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
1268
1269   /* Lower case */
1270   0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1271   0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x3C, 0x44, 0x3C, 0x00, 0x00, 0x00,
1272   0x00, 0x00, 0x40, 0x40, 0x58, 0x64, 0x44, 0x64, 0x58, 0x00, 0x00, 0x00,
1273   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
1274   0x00, 0x00, 0x04, 0x04, 0x34, 0x4C, 0x44, 0x4C, 0x34, 0x00, 0x00, 0x00,
1275   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x7C, 0x40, 0x38, 0x00, 0x00, 0x00,
1276   0x00, 0x00, 0x08, 0x14, 0x10, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1277   0x00, 0x00, 0x00, 0x00, 0x34, 0x4C, 0x44, 0x4C, 0x34, 0x04, 0x38, 0x00,
1278   0x00, 0x00, 0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1279   0x00, 0x00, 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1280   0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00,
1281   0x00, 0x00, 0x40, 0x40, 0x48, 0x50, 0x60, 0x50, 0x48, 0x00, 0x00, 0x00,
1282   0x00, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00,
1283   0x00, 0x00, 0x00, 0x00, 0x78, 0x54, 0x54, 0x54, 0x54, 0x00, 0x00, 0x00,
1284   0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00,
1285   0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
1286   0x00, 0x00, 0x00, 0x00, 0x78, 0x44, 0x44, 0x44, 0x78, 0x40, 0x40, 0x00,
1287   0x00, 0x00, 0x00, 0x00, 0x3C, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x04, 0x00,
1288   0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00,
1289   0x00, 0x00, 0x00, 0x00, 0x3C, 0x40, 0x38, 0x04, 0x78, 0x00, 0x00, 0x00,
1290   0x00, 0x00, 0x20, 0x20, 0x70, 0x20, 0x20, 0x24, 0x18, 0x00, 0x00, 0x00,
1291   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x4C, 0x34, 0x00, 0x00, 0x00,
1292   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00, 0x00, 0x00,
1293   0x00, 0x00, 0x00, 0x00, 0x44, 0x54, 0x54, 0x28, 0x28, 0x00, 0x00, 0x00,
1294   0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00,
1295   0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x38, 0x00, 0x00,
1296   0x00, 0x00, 0x00, 0x00, 0x7C, 0x08, 0x10, 0x20, 0x7C, 0x00, 0x00, 0x00,
1297   0x00, 0x00, 0x08, 0x10, 0x10, 0x20, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,
1298   0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
1299   0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00,
1300   0x00, 0x00, 0x20, 0x54, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1301   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00,
1302};
1303
1304
1305
1306//-------------------------------------------------
1307//  ntsc_square_fontdata8x12
1308//-------------------------------------------------
1309
1310const UINT8 mc6847_friend_device::ntsc_square_fontdata8x12[] =
1311{
1312   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x1A, 0x2A, 0x2A, 0x1C, 0x00, 0x00,
1313   0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x00, 0x00,
1314   0x00, 0x00, 0x00, 0x3C, 0x12, 0x12, 0x1C, 0x12, 0x12, 0x3C, 0x00, 0x00,
1315   0x00, 0x00, 0x00, 0x1C, 0x22, 0x20, 0x20, 0x20, 0x22, 0x1C, 0x00, 0x00,
1316   0x00, 0x00, 0x00, 0x3C, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3C, 0x00, 0x00,
1317   0x00, 0x00, 0x00, 0x3E, 0x20, 0x20, 0x38, 0x20, 0x20, 0x3E, 0x00, 0x00,
1318   0x00, 0x00, 0x00, 0x3E, 0x20, 0x20, 0x38, 0x20, 0x20, 0x20, 0x00, 0x00,
1319   0x00, 0x00, 0x00, 0x1E, 0x20, 0x20, 0x26, 0x22, 0x22, 0x1E, 0x00, 0x00,
1320   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22, 0x00, 0x00,
1321   0x00, 0x00, 0x00, 0x1C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1322   0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x22, 0x22, 0x1C, 0x00, 0x00,
1323   0x00, 0x00, 0x00, 0x22, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22, 0x00, 0x00,
1324   0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3E, 0x00, 0x00,
1325   0x00, 0x00, 0x00, 0x22, 0x36, 0x2A, 0x2A, 0x22, 0x22, 0x22, 0x00, 0x00,
1326   0x00, 0x00, 0x00, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x22, 0x22, 0x00, 0x00,
1327   0x00, 0x00, 0x00, 0x3E, 0x22, 0x22, 0x22, 0x22, 0x22, 0x3E, 0x00, 0x00,
1328   0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00,
1329   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x2A, 0x24, 0x1A, 0x00, 0x00,
1330   0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x3C, 0x28, 0x24, 0x22, 0x00, 0x00,
1331   0x00, 0x00, 0x00, 0x1C, 0x22, 0x10, 0x08, 0x04, 0x22, 0x1C, 0x00, 0x00,
1332   0x00, 0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1333   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00,
1334   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00,
1335   0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x2A, 0x2A, 0x36, 0x22, 0x00, 0x00,
1336   0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00,
1337   0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1338   0x00, 0x00, 0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x3E, 0x00, 0x00,
1339   0x00, 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, 0x00,
1340   0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00,
1341   0x00, 0x00, 0x00, 0x0E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E, 0x00, 0x00,
1342   0x00, 0x00, 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
1343   0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x3E, 0x10, 0x08, 0x00, 0x00, 0x00,
1344   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1345   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00,
1346   0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1347   0x00, 0x00, 0x00, 0x14, 0x14, 0x36, 0x00, 0x36, 0x14, 0x14, 0x00, 0x00,
1348   0x00, 0x00, 0x00, 0x08, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x08, 0x00, 0x00,
1349   0x00, 0x00, 0x00, 0x32, 0x32, 0x04, 0x08, 0x10, 0x26, 0x26, 0x00, 0x00,
1350   0x00, 0x00, 0x00, 0x10, 0x28, 0x28, 0x10, 0x2A, 0x24, 0x1A, 0x00, 0x00,
1351   0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1352   0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, 0x00,
1353   0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00, 0x00,
1354   0x00, 0x00, 0x00, 0x00, 0x08, 0x1C, 0x3E, 0x1C, 0x08, 0x00, 0x00, 0x00,
1355   0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x00,
1356   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x10, 0x20, 0x00, 0x00,
1357   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00,
1358   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
1359   0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00,
1360   0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00, 0x00,
1361   0x00, 0x00, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1362   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x1C, 0x20, 0x20, 0x3E, 0x00, 0x00,
1363   0x00, 0x00, 0x00, 0x1C, 0x22, 0x02, 0x04, 0x02, 0x22, 0x1C, 0x00, 0x00,
1364   0x00, 0x00, 0x00, 0x04, 0x0C, 0x14, 0x3E, 0x04, 0x04, 0x04, 0x00, 0x00,
1365   0x00, 0x00, 0x00, 0x3E, 0x20, 0x3C, 0x02, 0x02, 0x22, 0x1C, 0x00, 0x00,
1366   0x00, 0x00, 0x00, 0x1C, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x1C, 0x00, 0x00,
1367   0x00, 0x00, 0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00,
1368   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x1C, 0x22, 0x22, 0x1C, 0x00, 0x00,
1369   0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x1E, 0x02, 0x02, 0x1C, 0x00, 0x00,
1370   0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
1371   0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00,
1372   0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00,
1373   0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00,
1374   0x00, 0x00, 0x00, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00,
1375   0x00, 0x00, 0x00, 0x18, 0x24, 0x04, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00,
1376
1377   /* Lower case */
1378   0x00, 0x00, 0x00, 0x0C, 0x12, 0x10, 0x38, 0x10, 0x12, 0x3C, 0x00, 0x00,
1379   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x02, 0x1E, 0x22, 0x1E, 0x00, 0x00,
1380   0x00, 0x00, 0x00, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x22, 0x3C, 0x00, 0x00,
1381   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x20, 0x20, 0x20, 0x1C, 0x00, 0x00,
1382   0x00, 0x00, 0x00, 0x02, 0x02, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x00, 0x00,
1383   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x3E, 0x20, 0x1C, 0x00, 0x00,
1384   0x00, 0x00, 0x00, 0x0C, 0x12, 0x10, 0x38, 0x10, 0x10, 0x10, 0x00, 0x00,
1385   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x1C,
1386   0x00, 0x00, 0x00, 0x20, 0x20, 0x3C, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00,
1387   0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1388   0x00, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x24, 0x18,
1389   0x00, 0x00, 0x00, 0x20, 0x20, 0x24, 0x28, 0x38, 0x24, 0x22, 0x00, 0x00,
1390   0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00,
1391   0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x2A, 0x2A, 0x2A, 0x2A, 0x00, 0x00,
1392   0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00, 0x00,
1393   0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00,
1394   0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x22, 0x22, 0x22, 0x3C, 0x20, 0x20,
1395   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x03,
1396   0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
1397   0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x00, 0x00,
1398   0x00, 0x00, 0x00, 0x10, 0x3C, 0x10, 0x10, 0x10, 0x12, 0x0C, 0x00, 0x00,
1399   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x26, 0x1A, 0x00, 0x00,
1400   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00,
1401   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x2A, 0x2A, 0x1C, 0x14, 0x00, 0x00,
1402   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00,
1403   0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x1E, 0x02, 0x1C,
1404   0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x04, 0x08, 0x10, 0x3E, 0x00, 0x00,
1405   0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x20, 0x10, 0x10, 0x08, 0x00, 0x00,
1406   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00,
1407   0x00, 0x00, 0x00, 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, 0x00,
1408   0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00, 0x00,
1409   0x00, 0x00, 0x00, 0x08, 0x04, 0x3E, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00
1410};
1411
1412
1413
1414//-------------------------------------------------
1415//  semigraphics4_fontdata8x12
1416//-------------------------------------------------
1417
1418const UINT8 mc6847_friend_device::semigraphics4_fontdata8x12[] =
1419{
1420   /* Block Graphics (Semigraphics 4 Graphics ) */
1421   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1422   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1423   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1424   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1425   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1426   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1427   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1428   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1429   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1430   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1431   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1432   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1433   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1434   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1435   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1436   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1437};
1438
1439
1440
1441//-------------------------------------------------
1442//  semigraphics6_fontdata8x12
1443//-------------------------------------------------
1444
1445const UINT8 mc6847_friend_device::semigraphics6_fontdata8x12[] =
1446{
1447   /* Semigraphics 6 */
1448   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1449   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F,
1450   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0,
1451   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
1452   0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
1453   0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1454   0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0,
1455   0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
1456   0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
1457   0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
1458   0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1459   0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
1460   0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
1461   0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F,
1462   0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0,
1463   0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1464   0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1465   0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F,
1466   0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0,
1467   0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
1468   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
1469   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1470   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0,
1471   0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
1472   0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
1473   0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
1474   0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1475   0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
1476   0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
1477   0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F,
1478   0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0,
1479   0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1480   0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1481   0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F,
1482   0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0,
1483   0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
1484   0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
1485   0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1486   0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0,
1487   0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
1488   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
1489   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
1490   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1491   0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
1492   0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
1493   0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F,
1494   0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0,
1495   0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1496   0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1497   0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F,
1498   0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0,
1499   0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
1500   0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00,
1501   0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
1502   0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0,
1503   0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
1504   0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00,
1505   0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F,
1506   0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
1507   0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
1508   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
1509   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F,
1510   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0,
1511   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1512};
1513
1514
1515
1516//**************************************************************************
1517//  ARTIFACTING
1518//**************************************************************************
1519
1520INPUT_PORTS_START(mc6847_artifacting)
1521   PORT_START(ARTIFACTING_TAG)
1522   PORT_CONFNAME( 0x03, 0x01, "Artifacting" )
1523   PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
1524   PORT_CONFSETTING(    0x01, DEF_STR( Standard ) )
1525   PORT_CONFSETTING(    0x02, DEF_STR( Reverse ) )
1526INPUT_PORTS_END
1527
1528ioport_constructor mc6847_base_device::device_input_ports() const
1529{
1530   return INPUT_PORTS_NAME(mc6847_artifacting);
1531}
1532
1533
1534
1535//-------------------------------------------------
1536//  ctor
1537//-------------------------------------------------
1538
1539mc6847_base_device::artifacter::artifacter()
1540{
1541   m_config = NULL;
1542   m_artifacting = 0;
1543   m_saved_artifacting = 0;
1544   m_saved_c0 = 0;
1545   m_saved_c1 = 0;
1546   memset(m_expanded_colors, 0, sizeof(m_expanded_colors));
1547}
1548
1549
1550
1551//-------------------------------------------------
1552//  artifacter::setup_config
1553//-------------------------------------------------
1554
1555void mc6847_base_device::artifacter::setup_config(device_t *device)
1556{
1557   char port_name[32];
1558   snprintf(port_name, ARRAY_LENGTH(port_name), "%s:%s", device->tag(), ARTIFACTING_TAG);
1559   m_config = device->ioport(port_name);
1560}
1561
1562
1563
1564//-------------------------------------------------
1565//  artifacter::update_colors
1566//-------------------------------------------------
1567
1568void mc6847_base_device::artifacter::update_colors(pixel_t c0, pixel_t c1)
1569{
1570   /* Boy this code sucks; this code was adapted from the old M6847
1571    * artifacting implmentation.  The only reason that it didn't look as
1572    * horrible was because the code around it sucked as well.  Now that I
1573    * have cleaned everything up, the ugliness is much more prominent.
1574    *
1575    * Hopefully we will have a generic artifacting algorithm that plugs into
1576    * the MESS/MAME core directly so we can chuck this hack */
1577   static const double artifact_colors[14*3] =
1578   {
1579      0.157, 0.000, 0.157, /* [ 1] - dk purple   (reverse  2) */
1580      0.000, 0.157, 0.000, /* [ 2] - dk green    (reverse  1) */
1581      1.000, 0.824, 1.000, /* [ 3] - lt purple   (reverse  4) */
1582      0.824, 1.000, 0.824, /* [ 4] - lt green    (reverse  3) */
1583      0.706, 0.236, 0.118, /* [ 5] - dk blue     (reverse  6) */
1584      0.000, 0.197, 0.471, /* [ 6] - dk red      (reverse  5) */
1585      1.000, 0.550, 0.393, /* [ 7] - lt blue     (reverse  8) */
1586      0.275, 0.785, 1.000, /* [ 8] - lt red      (reverse  7) */
1587      0.000, 0.500, 1.000, /* [ 9] - red         (reverse 10) */
1588      1.000, 0.500, 0.000, /* [10] - blue        (reverse  9) */
1589      1.000, 0.942, 0.785, /* [11] - cyan        (reverse 12) */
1590      0.393, 0.942, 1.000, /* [12] - yellow      (reverse 11) */
1591      0.236, 0.000, 0.000, /* [13] - black-blue  (reverse 14) */
1592      0.000, 0.000, 0.236  /* [14] - black-red   (reverse 13) */
1593   };
1594
1595   static const UINT8 artifact_correction[128] =
1596   {
1597      0,  0,       0,  0,      0,  6,      0,  2,
1598      5,  7,       5,  7,      1,  3,      1, 11,
1599      8,  6,       8, 14,      8,  9,      8,  9,
1600      4,  4,       4, 15,     12, 12,     12, 15,
1601
1602      5, 13,       5, 13,     13,  0,     13,  2,
1603      10, 10,     10, 10,     10, 15,     10, 11,
1604      3,  1,       3,  1,     15,  9,     15,  9,
1605      11, 11,     11, 11,     15, 15,     15, 15,
1606
1607      14,  0,     14,  0,     14,  6,     14,  2,
1608      0,  7,       0,  7,      1,  3,      1, 11,
1609      9,  6,       9, 14,      9,  9,      9,  9,
1610      15,  4,     15, 15,     12, 12,     12, 15,
1611
1612      2, 13,       2, 13,      2,  0,      2,  2,
1613      10, 10,     10, 10,     10, 15,     10, 11,
1614      12,  1,     12,  1,     12,  9,     12,  9,
1615      15, 11,     15, 11,     15, 15,     15, 15
1616   };
1617
1618   pixel_t colors[16];
1619   int i;
1620
1621   /* do we need to update our artifact colors table? */
1622   if ((m_artifacting != m_saved_artifacting) || (c0 != m_saved_c0) || (c1 != m_saved_c1))
1623   {
1624      m_saved_artifacting = m_artifacting;
1625      m_saved_c0 = colors[0] = c0;
1626      m_saved_c1 = colors[15] = c1;
1627
1628      /* mix the other colors */
1629      for (i = 1; i <= 14; i++)
1630      {
1631         const double *factors = &artifact_colors[((i - 1) ^ (m_artifacting & 0x01)) * 3];
1632
1633         colors[i] = (mix_color(factors[0], c0 >> 16, c1 >> 16) << 16)
1634               |   (mix_color(factors[1], c0 >>  8, c1 >>  8) <<  8)
1635               |   (mix_color(factors[2], c0 >>  0, c1 >>  0) <<  0);
1636      }
1637      for (i = 0; i < 128; i++)
1638      {
1639         m_expanded_colors[i] = colors[artifact_correction[i]];
1640      }
1641   }
1642}
1643
1644
1645
1646//-------------------------------------------------
1647//  artifacter::update
1648//-------------------------------------------------
1649
1650mc6847_base_device::pixel_t mc6847_base_device::artifacter::mix_color(double factor, UINT8 c0, UINT8 c1)
1651{
1652   return (UINT32) (UINT8) ((c0 * (1.0 - factor)) + (c1 * (0.0 + factor)) + 0.5);
1653}
1654
1655
1656
1657//**************************************************************************
1658//  VARIATIONS
1659//**************************************************************************
1660
1661const device_type MC6847_NTSC = &device_creator<mc6847_ntsc_device>;
1662const device_type MC6847_PAL = &device_creator<mc6847_pal_device>;
1663const device_type MC6847Y_NTSC = &device_creator<mc6847y_ntsc_device>;
1664const device_type MC6847Y_PAL = &device_creator<mc6847y_pal_device>;
1665const device_type MC6847T1_NTSC = &device_creator<mc6847t1_ntsc_device>;
1666const device_type MC6847T1_PAL = &device_creator<mc6847t1_pal_device>;
1667
1668
1669
1670//-------------------------------------------------
1671//  mc6847_ntsc_device
1672//-------------------------------------------------
1673
1674mc6847_ntsc_device::mc6847_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1675   : mc6847_base_device(mconfig, MC6847_NTSC, "MC6847_NTSC", tag, owner, clock, ntsc_square_fontdata8x12, 262.0)
1676{
1677}
1678
1679
1680
1681//-------------------------------------------------
1682//  mc6847_pal_device
1683//-------------------------------------------------
1684
1685mc6847_pal_device::mc6847_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1686   : mc6847_base_device(mconfig, MC6847_PAL, "MC6847_PAL", tag, owner, clock, pal_square_fontdata8x12, 262.0)
1687{
1688}
1689
1690
1691
1692//-------------------------------------------------
1693//  mc6847y_ntsc_device
1694//-------------------------------------------------
1695
1696mc6847y_ntsc_device::mc6847y_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1697   : mc6847_base_device(mconfig, MC6847Y_NTSC, "MC6847Y_NTSC", tag, owner, clock, ntsc_square_fontdata8x12, 262.5)
1698{
1699}
1700
1701
1702
1703//-------------------------------------------------
1704//  mc6847y_pal_device
1705//-------------------------------------------------
1706
1707mc6847y_pal_device::mc6847y_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1708   : mc6847_base_device(mconfig, MC6847Y_PAL, "MC6847Y_PAL", tag, owner, clock, pal_square_fontdata8x12, 262.5)
1709{
1710}
1711
1712
1713
1714//-------------------------------------------------
1715//  mc6847t1_ntsc_device
1716//-------------------------------------------------
1717
1718mc6847t1_ntsc_device::mc6847t1_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1719   : mc6847_base_device(mconfig, MC6847T1_NTSC, "MC6847T1_NTSC", tag, owner, clock, ntsc_round_fontdata8x12, 262.0)
1720{
1721}
1722
1723
1724
1725//-------------------------------------------------
1726//  mc6847t1_pal_device
1727//-------------------------------------------------
1728
1729mc6847t1_pal_device::mc6847t1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1730   : mc6847_base_device(mconfig, MC6847T1_PAL, "MC6847T1_PAL", tag, owner, clock, pal_round_fontdata8x12, 262.0)
1731{
1732}
trunk/src/mess/video/tms3556.h
r21684r21685
1/***************************************************************************
2
3  Texas Instruments TMS3556 Video Display Processor
4
5 ***************************************************************************/
6
7
8#pragma once
9
10#ifndef __TMS3556_H__
11#define __TMS3556_H__
12
13///*************************************************************************
14//  MACROS / CONSTANTS
15///*************************************************************************
16
17#define TMS3556_TOP_BORDER 1
18#define TMS3556_BOTTOM_BORDER 1
19#define TMS3556_LEFT_BORDER 8
20#define TMS3556_RIGHT_BORDER 8
21#define TMS3556_TOTAL_WIDTH (320 + TMS3556_LEFT_BORDER + TMS3556_RIGHT_BORDER)
22#define TMS3556_TOTAL_HEIGHT (250 + TMS3556_TOP_BORDER + TMS3556_BOTTOM_BORDER)
23
24/* if DOUBLE_WIDTH set, the horizontal resolution is doubled */
25#define TMS3556_DOUBLE_WIDTH 1
26
27#define TMS3556_MODE_OFF    0
28#define TMS3556_MODE_TEXT   1
29#define TMS3556_MODE_BITMAP 2
30#define TMS3556_MODE_MIXED  3
31
32
33///*************************************************************************
34//  INTERFACE CONFIGURATION MACROS
35///*************************************************************************
36
37#define MCFG_TMS3556_ADD(_tag) \
38   MCFG_DEVICE_ADD(_tag, TMS3556, 0)
39
40///*************************************************************************
41//  TYPE DEFINITIONS
42///*************************************************************************
43
44// ======================> tms3556_device
45
46class tms3556_device :  public device_t,
47                  public device_memory_interface
48{
49public:
50   // construction/destruction
51   tms3556_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
52
53   DECLARE_READ8_MEMBER( vram_r );
54   DECLARE_WRITE8_MEMBER( vram_w );
55   DECLARE_READ8_MEMBER( reg_r );
56   DECLARE_WRITE8_MEMBER( reg_w );
57
58   void interrupt(running_machine &machine);
59
60   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
61
62protected:
63   // device-level overrides
64   virtual void device_start();
65
66   // device_config_memory_interface overrides
67   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
68
69   // address space configurations
70   const address_space_config      m_space_config;
71
72   inline UINT8 readbyte(offs_t address);
73   inline void writebyte(offs_t address, UINT8 data);
74
75   void draw_line_empty(UINT16 *ln);
76   void draw_line_text_common(UINT16 *ln);
77   void draw_line_bitmap_common(UINT16 *ln);
78   void draw_line_text(UINT16 *ln);
79   void draw_line_bitmap(UINT16 *ln);
80   void draw_line_mixed(UINT16 *ln);
81   void draw_line(bitmap_ind16 &bmp, int line);
82   void interrupt_start_vblank(void);
83
84private:
85   // registers
86   UINT8 m_control_regs[8];
87   UINT16 m_address_regs[8];
88   UINT16 m_write_ptr;
89
90   // register interface
91   int m_reg_ptr;
92   int m_reg_access_phase;
93   int m_magical_mystery_flag;
94
95   int m_scanline;             // scanline counter
96   int m_blink, m_blink_count; // blinking
97   int m_bg_color;             // background color for current line
98   int m_name_offset;          // current offset in name table
99   int m_cg_flag;              // c/g flag (mixed mode only)
100   int m_char_line_counter;    // character line counter (decrements from 10, 0 when we have reached
101                        // last line of character row)
102   int m_dbl_h_phase[40];      // double height phase flags (one per horizontal character position)
103
104   bitmap_ind16 m_bitmap;
105};
106
107
108// device type definition
109extern const device_type TMS3556;
110
111
112#endif
trunk/src/mess/video/mc6847.h
r21684r21685
1/*********************************************************************
2
3    mc6847.h
4
5    Implementation of Motorola 6847 video hardware chip
6
7***************************************************************************/
8
9#pragma once
10
11#ifndef __MC6847__
12#define __MC6847__
13
14
15//**************************************************************************
16//  MC6847 CONFIGURATION / INTERFACE
17//**************************************************************************
18
19#define MCFG_MC6847_REMOVE(_tag) \
20   MCFG_DEVICE_REMOVE(_tag)
21
22#define MCFG_MC6847_ADD(_tag, _variant, _clock, _config)        \
23   MCFG_DEVICE_ADD(_tag, _variant, _clock)                     \
24   MCFG_DEVICE_CONFIG(_config)
25
26#define MCFG_SCREEN_MC6847_NTSC_ADD(_tag, _mctag) \
27   MCFG_SCREEN_ADD(_tag, RASTER)                               \
28   MCFG_SCREEN_UPDATE_DEVICE(_mctag, mc6847_base_device, screen_update) \
29   MCFG_SCREEN_REFRESH_RATE(60)                                \
30   MCFG_SCREEN_SIZE(320, 243)                                  \
31   MCFG_SCREEN_VISIBLE_AREA(0, 320-1, 1, 241-1)                \
32   MCFG_SCREEN_VBLANK_TIME(0)
33#define MCFG_SCREEN_MC6847_PAL_ADD(_tag, _mctag) \
34   MCFG_SCREEN_ADD(_tag, RASTER)                               \
35   MCFG_SCREEN_UPDATE_DEVICE(_mctag, mc6847_base_device, screen_update) \
36   MCFG_SCREEN_REFRESH_RATE(50)                                \
37   MCFG_SCREEN_SIZE(320, 243)                                  \
38   MCFG_SCREEN_VISIBLE_AREA(0, 320-1, 1, 241-1)                \
39   MCFG_SCREEN_VBLANK_TIME(0)
40/* interface */
41struct mc6847_interface
42{
43   /* screen we are acting on */
44   const char *m_screen_tag;
45
46   /* if specified, this gets called whenever reading a byte (offs_t ~0 specifies DA* entering the tristate mode) */
47   devcb_read8                 m_input_func;
48
49   /* if specified, this gets called for every change of the HS pin (pin 38) */
50   devcb_write_line            m_out_hsync_func;
51
52   /* if specified, this gets called for every change of the FS pin (pin 37) */
53   devcb_write_line            m_out_fsync_func;
54
55   /* mode control lines input */
56   devcb_read_line             m_in_ag_func;
57   devcb_read_line             m_in_gm2_func;
58   devcb_read_line             m_in_gm1_func;
59   devcb_read_line             m_in_gm0_func;
60   devcb_read_line             m_in_css_func;
61   devcb_read_line             m_in_as_func;
62   devcb_read_line             m_in_intext_func;
63   devcb_read_line             m_in_inv_func;
64
65   /* if specified, this reads the external char rom off of the driver state */
66   UINT8 (*m_get_char_rom)(running_machine &machine, UINT8 ch, int line);
67
68   /* if true, this is black and white */
69   bool                        m_black_and_white;
70};
71
72#define ARTIFACTING_TAG     "artifacting"
73
74INPUT_PORTS_EXTERN(mc6847_artifacting);
75
76
77//**************************************************************************
78//  MC6847 CORE
79//**************************************************************************
80
81PALETTE_INIT( mc6847 );
82PALETTE_INIT( mc6847_bw );
83
84// base class so that the GIME emulation can access mc6847 stuff
85class mc6847_friend_device : public device_t
86{
87public:
88   // inlines
89   bool hs_r(void)                 { return m_horizontal_sync; }
90   bool fs_r(void)                 { return m_field_sync; }
91
92protected:
93   mc6847_friend_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock,
94      const UINT8 *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, bool supports_partial_body_scanlines);
95
96   // video mode constants
97   static const UINT8 MODE_AG      = 0x80;
98   static const UINT8 MODE_GM2     = 0x40;
99   static const UINT8 MODE_GM1     = 0x20;
100   static const UINT8 MODE_GM0     = 0x10;
101   static const UINT8 MODE_CSS     = 0x08;
102   static const UINT8 MODE_AS      = 0x04;
103   static const UINT8 MODE_INTEXT  = 0x02;
104   static const UINT8 MODE_INV     = 0x01;
105
106   // timer constants
107   static const device_timer_id TIMER_FRAME = 0;
108   static const device_timer_id TIMER_HSYNC_OFF = 1;
109   static const device_timer_id TIMER_HSYNC_ON = 2;
110   static const device_timer_id TIMER_FSYNC = 3;
111
112   // fonts
113   static const UINT8 pal_round_fontdata8x12[];
114   static const UINT8 pal_square_fontdata8x12[];
115   static const UINT8 ntsc_round_fontdata8x12[];
116   static const UINT8 ntsc_square_fontdata8x12[];
117   static const UINT8 semigraphics4_fontdata8x12[];
118   static const UINT8 semigraphics6_fontdata8x12[];
119
120   // pixel definitions
121   typedef UINT32 pixel_t;
122
123   pixel_t *bitmap_addr(bitmap_rgb32 &bitmap, int y, int x)
124   {
125      return &bitmap.pix32(y, x);
126   }
127
128   static UINT8 simplify_mode(UINT8 data, UINT8 mode)
129   {
130      // simplifies MC6847 modes to drop mode flags that are not significant
131      return mode & ~((mode & MODE_AG) ? (MODE_AS | MODE_INV) : 0);
132   }
133
134   // internal class that represents a MC6847 character map
135   class character_map
136   {
137   public:
138      // constructor that sets up the font data
139      character_map(const UINT8 *fontdata, bool is_mc6847t1);
140
141      // optimized template function that emits a single character
142      template<int xscale>
143      ATTR_FORCE_INLINE void emit_character(UINT8 mode, const UINT8 *data, int length, pixel_t *RESTRICT pixels, int y, const pixel_t *palette)
144      {
145         for (int i = 0; i < length; i++)
146         {
147            // get the character
148            UINT8 character = data[i];
149
150            // based on the mode, determine which entry to use
151            const entry *e = &m_entries[mode % (sizeof(m_entries) / sizeof(m_entries[0]))];
152
153            // identify the character in the font data
154            const UINT8 *font_character = e->m_fontdata + (character & e->m_character_mask) * 12;
155
156            // get the particular slice out
157            UINT8 font_character_slice = font_character[y % 12];
158
159            // get the two colors
160            UINT16 color_base_0 = e->m_color_base_0 + ((character >> e->m_color_shift_0) & e->m_color_mask_0);
161            UINT16 color_base_1 = e->m_color_base_1 + ((character >> e->m_color_shift_1) & e->m_color_mask_1);
162            pixel_t color_0 = palette[color_base_0];
163            pixel_t color_1 = palette[color_base_1];
164
165            // emit the bits
166            for (int j = 0; j < 8; j++)
167            {
168               for (int k = 0; k < xscale; k++)
169               {
170                  pixels[(i * 8 + j) * xscale + k] = bit_test(font_character_slice, j, color_0, color_1);
171               }
172            }
173         }
174      };
175
176   private:
177      struct entry
178      {
179         const UINT8 *m_fontdata;
180         UINT8 m_character_mask;
181         UINT8 m_color_shift_0;
182         UINT8 m_color_shift_1;
183         UINT8 m_color_mask_0;
184         UINT8 m_color_mask_1;
185         UINT16 m_color_base_0;
186         UINT16 m_color_base_1;
187      };
188
189      // lookup table for MC6847 modes to determine font data and color
190      entry m_entries[128];
191
192      // text font data calculated on startup
193      UINT8 m_text_fontdata_inverse[64*12];
194      UINT8 m_text_fontdata_lower_case[64*12];
195      UINT8 m_text_fontdata_lower_case_inverse[64*12];
196
197      // optimized function that tests a single bit
198      ATTR_FORCE_INLINE pixel_t bit_test(UINT8 data, int shift, pixel_t color_0, pixel_t color_1)
199      {
200         return data & (0x80 >> shift) ? color_1 : color_0;
201      }
202   };
203
204   // artficater internal class
205   class artifacter
206   {
207   public:
208      artifacter();
209
210      // artifacting config
211      void setup_config(device_t *device);
212      void poll_config(void) { m_artifacting = (m_config!=NULL) ? m_config->read() : 0; }
213
214      // artifacting application
215      template<int xscale>
216      ATTR_FORCE_INLINE void process_artifacts(pixel_t *pixels, UINT8 mode, const pixel_t *palette)
217      {
218         if (((mode & (MODE_AG|MODE_GM2|MODE_GM1|MODE_GM0)) == (MODE_AG|MODE_GM2|MODE_GM1|MODE_GM0))
219            && (m_artifacting != 0))
220         {
221            // identify the new colors and update
222            pixel_t c0 = palette[(mode & MODE_CSS) ? 10 : 8];
223            pixel_t c1 = palette[(mode & MODE_CSS) ? 11 : 9];
224            update_colors(c0, c1);
225
226            // generate the new line
227            pixel_t new_line[256];
228            int x, i;
229            for (x = 0; x < 256; x += 2)
230            {
231               UINT8 val = ((pixels[(x - 2) * xscale] == c1) ? 0x20 : 0x00)
232                  |   ((pixels[(x - 1) * xscale] == c1) ? 0x10 : 0x00)
233                  |   ((pixels[(x + 0) * xscale] == c1) ? 0x08 : 0x00)
234                  |   ((pixels[(x + 1) * xscale] == c1) ? 0x04 : 0x00)
235                  |   ((pixels[(x + 2) * xscale] == c1) ? 0x02 : 0x00)
236                  |   ((pixels[(x + 3) * xscale] == c1) ? 0x01 : 0x00);
237
238               new_line[x + 0] = m_expanded_colors[val * 2 + 0];
239               new_line[x + 1] = m_expanded_colors[val * 2 + 1];
240            }
241
242            // and copy it in
243            for (x = 0; x < 256; x++)
244            {
245               for (i = 0; i < xscale; i++)
246                  pixels[x * xscale + i] = new_line[x];
247            }
248         }
249      }
250
251   private:
252      ioport_port *m_config;
253      ioport_value m_artifacting;
254      ioport_value m_saved_artifacting;
255      pixel_t m_saved_c0, m_saved_c1;
256      pixel_t m_expanded_colors[128];
257
258      void update_colors(pixel_t c0, pixel_t c1);
259      static pixel_t mix_color(double factor, UINT8 c0, UINT8 c1);
260   };
261
262   enum border_color_t
263   {
264      BORDER_COLOR_BLACK,
265      BORDER_COLOR_GREEN,
266      BORDER_COLOR_WHITE,
267      BORDER_COLOR_ORANGE
268   };
269
270   // callbacks
271   devcb_resolved_write_line m_res_out_hsync_func;
272   devcb_resolved_write_line m_res_out_fsync_func;
273
274   // incidentals
275   character_map m_character_map;
276   artifacter m_artifacter;
277
278   // device-level overrides
279   virtual void device_start(void);
280   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
281   virtual void device_reset(void);
282   virtual void device_post_load(void);
283
284   // other overridables
285   virtual void new_frame(void);
286   virtual void horizontal_sync_changed(bool line);
287   virtual void field_sync_changed(bool line);
288   virtual void enter_bottom_border(void);
289   virtual void record_border_scanline(UINT16 physical_scanline);
290   virtual void record_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline) = 0;
291   virtual void record_partial_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline, INT32 start_clock, INT32 end_clock) = 0;
292
293   // miscellaneous
294   void video_flush(void);
295   const char *describe_context(void);
296
297   // setup functions
298   emu_timer *setup_timer(device_timer_id id, double offset, double period);
299
300   // converts to B&W
301   static pixel_t black_and_white(pixel_t color)
302   {
303      UINT8 average_color = (RGB_RED(color) + RGB_GREEN(color) + RGB_BLUE(color)) / 3;
304      return MAKE_RGB(average_color, average_color, average_color);
305   }
306
307   // changes the geometry
308   ATTR_FORCE_INLINE void set_geometry(UINT16 top_border_scanlines, UINT16 body_scanlines, bool wide)
309   {
310      if (UNEXPECTED((m_top_border_scanlines != top_border_scanlines)
311         || (m_body_scanlines != body_scanlines)
312         || (m_wide != wide)))
313      {
314         m_top_border_scanlines = top_border_scanlines;
315         m_body_scanlines = body_scanlines;
316         m_wide = wide;
317         update_field_sync_timer();
318      }
319   }
320
321   // calculates the border color
322   static ATTR_FORCE_INLINE border_color_t border_value(UINT8 mode, bool is_mc6847t1)
323   {
324      border_color_t result;
325
326      if (mode & MODE_AG)
327      {
328         // graphics
329         result = mode & MODE_CSS ? BORDER_COLOR_WHITE : BORDER_COLOR_GREEN;
330      }
331      else if (!is_mc6847t1 || ((mode & MODE_GM2) == 0))
332      {
333         // text, black border
334         result = BORDER_COLOR_BLACK;
335      }
336      else
337      {
338         // text, green or orange border
339         result = mode & MODE_CSS ? BORDER_COLOR_ORANGE : BORDER_COLOR_GREEN;
340      }
341      return result;
342   }
343
344   // checks to see if the video has changed
345   ATTR_FORCE_INLINE bool has_video_changed(void)
346   {
347      /* poll the artifacting config */
348      m_artifacter.poll_config();
349
350      /* if the video didn't change, indicate as much */
351      bool video_changed = m_video_changed;
352      m_video_changed = false;
353      return video_changed;
354   }
355
356   // updates a byte in the video state
357   template<class T>
358   ATTR_FORCE_INLINE bool update_value(T *ptr, T byte)
359   {
360      bool result = false;
361      if (*ptr != byte)
362      {
363         *ptr = byte;
364         m_video_changed = true;
365         result = true;
366      }
367      return result;
368   };
369
370   // template function for emitting graphics bytes
371   template<int bits_per_pixel, int xscale>
372   ATTR_FORCE_INLINE void emit_graphics(const UINT8 *data, int length, pixel_t *RESTRICT pixels, UINT16 color_base, const pixel_t *RESTRICT palette)
373   {
374      for (int i = 0; i < length; i++)
375      {
376         for (int j = 0; j < (8 / bits_per_pixel); j++)
377         {
378            for (int k = 0; k < xscale; k++)
379            {
380               UINT16 color = color_base + ((data[i] >> (8 - (j + 1) * bits_per_pixel)) & ((1 << bits_per_pixel) - 1));
381               pixels[(i * (8 / bits_per_pixel) + j) * xscale + k] = palette[color];
382            }
383         }
384      }
385   }
386
387   // template function for emitting samples
388   template<int xscale>
389   UINT32 emit_mc6847_samples(UINT8 mode, const UINT8 *data, int length, pixel_t *RESTRICT pixels, const pixel_t *RESTRICT palette,
390      UINT8 (*get_char_rom)(running_machine &machine, UINT8 ch, int line), int x, int y)
391   {
392      UINT32 result = 0;
393      if (mode & MODE_AG)
394      {
395         /* graphics */
396         switch(mode & (MODE_GM2|MODE_GM1|MODE_GM0))
397         {
398            case 0:
399               emit_graphics<2, xscale * 4>(data, length, pixels, (mode & MODE_CSS) ? 4 : 0, palette);
400               result = length * 8 * xscale * 2;
401               break;
402
403            case MODE_GM0:
404            case MODE_GM1|MODE_GM0:
405            case MODE_GM2|MODE_GM0:
406               emit_graphics<1, xscale * 2>(data, length, pixels, (mode & MODE_CSS) ? 10 : 8, palette);
407               result = length * 8 * xscale * 2;
408               break;
409
410            case MODE_GM1:
411            case MODE_GM2:
412            case MODE_GM2|MODE_GM1:
413               emit_graphics<2, xscale * 2>(data, length, pixels, (mode & MODE_CSS) ? 4 : 0, palette);
414               result = length * 8 * xscale;
415               break;
416
417            case MODE_GM2|MODE_GM1|MODE_GM0:
418               emit_graphics<1, xscale * 1>(data, length, pixels, (mode & MODE_CSS) ? 10 : 8, palette);
419               result = length * 8 * xscale;
420               break;
421
422            default:
423               /* should not get here */
424               fatalerror("Should not get here\n");
425               break;
426         }
427      }
428      else if ((get_char_rom != NULL) && ((mode & (MODE_AG|MODE_AS|MODE_INTEXT)) == MODE_INTEXT))
429      {
430         /* external ROM */
431         for (int i = 0; i < length; i++)
432         {
433            UINT8 byte = get_char_rom(machine(), data[i], y % 12) ^ (mode & MODE_INV ? 0xFF : 0x00);
434            emit_graphics<2, xscale * 2>(&byte, 1, &pixels[i * 8], (mode & MODE_CSS) ? 14 : 12, palette);
435         }
436         result = length * 8 * xscale;
437      }
438      else
439      {
440         /* text/semigraphics */
441         m_character_map.emit_character<xscale>(mode, data, length, pixels, y, palette);
442         result = length * 8 * xscale;
443      }
444      return result;
445   }
446
447private:
448   enum scanline_zone
449   {
450      SCANLINE_ZONE_TOP_BORDER,
451      SCANLINE_ZONE_BODY,
452      SCANLINE_ZONE_BOTTOM_BORDER,
453      SCANLINE_ZONE_RETRACE,
454      SCANLINE_ZONE_VBLANK,
455      SCANLINE_ZONE_FRAME_END
456   };
457
458   // timers
459   emu_timer *m_frame_timer;
460   emu_timer *m_hsync_on_timer;
461   emu_timer *m_hsync_off_timer;
462   emu_timer *m_fsync_timer;
463
464   // incidentals
465   double m_tpfs;
466   int m_field_sync_falling_edge_scanline;
467   bool m_wide;
468   bool m_video_changed;
469   UINT16 m_top_border_scanlines;
470   UINT16 m_body_scanlines;
471   bool m_recording_scanline;
472   bool m_supports_partial_body_scanlines;
473
474   // video state
475   UINT16 m_physical_scanline;
476   UINT16 m_logical_scanline;
477   UINT16 m_logical_scanline_zone;
478   bool m_horizontal_sync;
479   bool m_field_sync;
480   UINT32 m_partial_scanline_clocks;
481
482   // functions
483   void change_horizontal_sync(bool line);
484   void change_field_sync(bool line);
485   void update_field_sync_timer(void);
486   void next_scanline(void);
487   INT32 get_clocks_since_hsync();
488
489   // debugging
490   const char *scanline_zone_string(scanline_zone zone);
491};
492
493// actual base class for MC6847 family of devices
494class mc6847_base_device : public mc6847_friend_device
495{
496public:
497   /* updates the screen -- this will call begin_update(),
498      followed by update_row() reapeatedly and after all row
499      updating is complete, end_update() */
500   UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
501
502   // mode changing operations
503   DECLARE_WRITE_LINE_MEMBER( ag_w )       { change_mode(MODE_AG, state); }
504   DECLARE_WRITE_LINE_MEMBER( gm2_w )      { change_mode(MODE_GM2, state); }
505   DECLARE_WRITE_LINE_MEMBER( gm1_w )      { change_mode(MODE_GM1, state); }
506   DECLARE_WRITE_LINE_MEMBER( gm0_w )      { change_mode(MODE_GM0, state); }
507   DECLARE_WRITE_LINE_MEMBER( as_w )       { change_mode(MODE_AS, state); }
508   DECLARE_WRITE_LINE_MEMBER( css_w )      { change_mode(MODE_CSS, state); }
509   DECLARE_WRITE_LINE_MEMBER( intext_w )   { change_mode(MODE_INTEXT, state); }
510   DECLARE_WRITE_LINE_MEMBER( inv_w )      { change_mode(MODE_INV, state); }
511
512protected:
513   mc6847_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const UINT8 *fontdata, double tpfs);
514
515   // device-level overrides
516   virtual void device_start();
517   virtual void device_reset();
518   virtual ioport_constructor device_input_ports() const;
519
520   // other overrides
521   virtual void field_sync_changed(bool line);
522   virtual void record_body_scanline(UINT16 physical_scanline, UINT16 scanline);
523   virtual void record_partial_body_scanline(UINT16 physical_scanline, UINT16 logical_scanline, INT32 start_clock, INT32 end_clock);
524
525private:
526   struct video_scanline
527   {
528      UINT8 m_sample_count;
529      UINT8 m_mode[32];
530      UINT8 m_data[32];
531   };
532
533   // palette
534   static const int PALETTE_LENGTH = 16;
535   static const UINT32 s_palette[PALETTE_LENGTH];
536
537   // callbacks
538   devcb_resolved_read8 m_res_input_func;
539   UINT8 (*m_get_char_rom)(running_machine &machine, UINT8 ch, int line);
540
541   // incidentals
542   UINT8 m_fixed_mode;
543   UINT8 m_fixed_mode_mask;
544   const pixel_t *m_palette;
545   pixel_t m_bw_palette[PALETTE_LENGTH];
546
547   // state
548   UINT8 m_mode;
549   UINT16 m_video_address;
550   bool m_dirty;
551   video_scanline m_data[192];
552
553   void change_mode(UINT8 mode, int state)
554   {
555      // sanity check, to ensure that we're not changing fixed modes
556      assert((mode & m_fixed_mode_mask) == 0);
557
558      // calculate new mode
559      UINT8 new_mode;
560      if (state)
561         new_mode = m_mode | mode;
562      else
563         new_mode = m_mode & ~mode;
564
565      // has the mode changed?
566      if (new_mode != m_mode)
567      {
568         // it has!  check dirty flag
569         video_flush();
570         if (!m_dirty)
571         {
572            m_dirty = true;
573         }
574
575         // and set the new mode
576         m_mode = new_mode;
577      }
578   }
579
580   // setup functions
581   void setup_fixed_mode(struct devcb_read_line callback, UINT8 mode);
582
583   // runtime functions
584   void record_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_pos, INT32 end_pos);
585   pixel_t border_value(UINT8 mode, const pixel_t *palette, bool is_mc6847t1);
586
587   template<int xscale>
588   void emit_samples(UINT8 mode, const UINT8 *data, int length, pixel_t *pixels, int x, int y);
589
590   // template function for doing video update collection
591   template<int sample_count, int yres>
592   void record_scanline_res(int scanline, INT32 start_pos, INT32 end_pos);
593
594   // miscellaneous
595   UINT8 input(UINT16 address);
596   INT32 scanline_position_from_clock(INT32 clocks_since_hsync);
597};
598
599
600//**************************************************************************
601//  VARIATIONS
602//**************************************************************************
603
604class mc6847_ntsc_device : public mc6847_base_device
605{
606public:
607   mc6847_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
608};
609
610class mc6847_pal_device : public mc6847_base_device
611{
612public:
613   mc6847_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
614};
615
616class mc6847y_ntsc_device : public mc6847_base_device
617{
618public:
619   mc6847y_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
620};
621
622class mc6847y_pal_device : public mc6847_base_device
623{
624public:
625   mc6847y_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
626};
627
628class mc6847t1_ntsc_device : public mc6847_base_device
629{
630public:
631   mc6847t1_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
632};
633
634class mc6847t1_pal_device : public mc6847_base_device
635{
636public:
637   mc6847t1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
638};
639
640
641extern const device_type MC6847_NTSC;
642extern const device_type MC6847_PAL;
643extern const device_type MC6847Y_NTSC;
644extern const device_type MC6847Y_PAL;
645extern const device_type MC6847T1_NTSC;
646extern const device_type MC6847T1_PAL;
647
648#endif /* __MC6847__ */
trunk/src/mess/video/hd66421.c
r21684r21685
1/*
2
3    Hitachi HD66421 LCD Controller/Driver
4
5    (c) 2001-2007 Tim Schuerewegen
6
7*/
8
9#include "emu.h"
10#include "hd66421.h"
11
12//**************************************************************************
13//  MACROS / CONSTANTS
14//**************************************************************************
15
16#define LOG_LEVEL  1
17#define _logerror(level,x)  do { if (LOG_LEVEL > level) logerror x; } while (0)
18
19#define HD66421_RAM_SIZE  (HD66421_WIDTH * HD66421_HEIGHT / 4) // 2-bits per pixel
20
21// R0 - control register 1
22#define LCD_R0_RMW      0x80 // read-modify-write mode
23#define LCD_R0_DISP     0x40 // display on/off
24#define LCD_R0_STBY     0x20 // standby (internal operation and power circuit halt)
25#define LCD_R0_PWR      0x10
26#define LCD_R0_AMP      0x08
27#define LCD_R0_REV      0x04 // reverse
28#define LCD_R0_HOLT     0x02
29#define LCD_R0_ADC      0x01
30
31// R1 - control register 2
32#define LCD_R1_BIS1     0x80 // bias ratio (bit 1)
33#define LCD_R1_BIS0     0x40 // bias ratio (bit 0)
34#define LCD_R1_WLS      0x20
35#define LCD_R1_GRAY     0x10 // grayscale palette 4/32
36#define LCD_R1_DTY1     0x08 // display duty cycle (bit 1)
37#define LCD_R1_DTY0     0x04 // display duty cycle (bit 0)
38#define LCD_R1_INC      0x02
39#define LCD_R1_BLK      0x01 // blink function
40
41// register 0 to 16
42#define LCD_REG_CONTROL_1   0x00 // control register 1
43#define LCD_REG_CONTROL_2   0x01 // control register 2
44#define LCD_REG_ADDR_X      0x02 // x address register
45#define LCD_REG_ADDR_Y      0x03 // y address register
46#define LCD_REG_RAM         0x04 // display ram access register
47#define LCD_REG_START_Y     0x05 // display start line register
48#define LCD_REG_BLINK_START 0x06 // blink start line register
49#define LCD_REG_BLINK_END   0x07 // blink end line register
50#define LCD_REG_BLINK_1     0x08 // blink register 1
51#define LCD_REG_BLINK_2     0x09 // blink register 2
52#define LCD_REG_BLINK_3     0x0A // blink register 3
53#define LCD_REG_PARTIAL     0x0B // partial display block register
54#define LCD_REG_COLOR_1     0x0C // gray scale palette 1 (0,0)
55#define LCD_REG_COLOR_2     0x0D // gray scale palette 2 (0,1)
56#define LCD_REG_COLOR_3     0x0E // gray scale palette 3 (1,0)
57#define LCD_REG_COLOR_4     0x0F // gray scale palette 4 (1,1)
58#define LCD_REG_CONTRAST    0x10 // contrast control register
59#define LCD_REG_PLANE       0x11 // plane selection register
60
61//**************************************************************************
62//  GLOBAL VARIABLES
63//**************************************************************************
64
65// devices
66const device_type HD66421 = &device_creator<hd66421_device>;
67
68
69// default address map
70static ADDRESS_MAP_START( hd66421, AS_0, 8, hd66421_device )
71   AM_RANGE(0x0000, HD66421_RAM_SIZE) AM_RAM
72ADDRESS_MAP_END
73
74//-------------------------------------------------
75//  memory_space_config - return a description of
76//  any address spaces owned by this device
77//-------------------------------------------------
78
79const address_space_config *hd66421_device::memory_space_config(address_spacenum spacenum) const
80{
81   return (spacenum == AS_0) ? &m_space_config : NULL;
82}
83
84
85//**************************************************************************
86//  INLINE HELPERS
87//**************************************************************************
88
89//-------------------------------------------------
90//  readbyte - read a byte at the given address
91//-------------------------------------------------
92
93inline UINT8 hd66421_device::readbyte(offs_t address)
94{
95   return space().read_byte(address);
96}
97
98
99//-------------------------------------------------
100//  writebyte - write a byte at the given address
101//-------------------------------------------------
102
103inline void hd66421_device::writebyte(offs_t address, UINT8 data)
104{
105   space().write_byte(address, data);
106}
107
108
109//**************************************************************************
110//  LIVE DEVICE
111//**************************************************************************
112
113//-------------------------------------------------
114//  hd66421_device - constructor
115//-------------------------------------------------
116
117hd66421_device::hd66421_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
118   : device_t(mconfig, HD66421, "Hitachi HD66421 LCD Controller", tag, owner, clock),
119      device_memory_interface(mconfig, *this),
120      m_space_config("videoram", ENDIANNESS_LITTLE, 8, 17, 0, NULL, *ADDRESS_MAP_NAME(hd66421)),
121      m_cmd(0),
122      m_x(0),
123      m_y(0)
124{
125   for (int i = 0; i < 32; i++)
126   {
127      m_reg[i] = 0;
128   }
129}
130
131
132//-------------------------------------------------
133//  device_start - device-specific startup
134//-------------------------------------------------
135
136void hd66421_device::device_start()
137{
138   // register for state saving
139   save_item(NAME(m_cmd));
140   save_item(NAME(m_reg));
141   save_item(NAME(m_x));
142   save_item(NAME(m_y));
143}
144
145READ8_MEMBER( hd66421_device::reg_idx_r )
146{
147   _logerror( 2, ("reg_idx_r\n"));
148   return m_cmd;
149}
150
151WRITE8_MEMBER( hd66421_device::reg_idx_w )
152{
153   _logerror( 2, ("reg_idx_w (%02X)\n", data));
154   m_cmd = data;
155}
156
157READ8_MEMBER( hd66421_device::reg_dat_r )
158{
159   _logerror( 2, ("reg_dat_r\n"));
160   return m_reg[m_cmd];
161}
162
163WRITE8_MEMBER( hd66421_device::reg_dat_w )
164{
165   _logerror( 2, ("reg_dat_w (%02X)\n", data));
166   m_reg[m_cmd] = data;
167
168   switch (m_cmd)
169   {
170      case LCD_REG_ADDR_X :
171         m_x = data;
172         break;
173
174      case LCD_REG_ADDR_Y :
175         m_y = data;
176         break;
177
178      case LCD_REG_RAM :
179      {
180         UINT8 r1;
181         writebyte(m_y * (HD66421_WIDTH / 4) + m_x, data);
182         r1 = m_reg[LCD_REG_CONTROL_2];
183         if (r1 & 0x02)
184            m_x++;
185         else
186            m_y++;
187
188         if (m_x >= (HD66421_WIDTH / 4))
189         {
190            m_x = 0;
191            m_y++;
192         }
193
194         if (m_y >= HD66421_HEIGHT)
195            m_y = 0;
196      }
197      break;
198   }
199}
200
201void hd66421_device::plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color)
202{
203   bitmap.pix16(y, x) = (UINT16)color;
204}
205
206UINT32 hd66421_device::update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
207{
208   pen_t pen[4];
209
210   _logerror( 1, ("video_update_hd66421\n"));
211
212   // update palette
213   for (int i = 0; i < 4; i++)
214   {
215      double bright;
216      int temp;
217      temp = 31 - (m_reg[LCD_REG_COLOR_1 + i] - m_reg[LCD_REG_CONTRAST] + 0x03);
218      if (temp <  0) temp =  0;
219      if (temp > 31) temp = 31;
220      bright = 1.0 * temp / 31;
221      pen[i] = i;
222      #ifdef HD66421_BRIGHTNESS_DOES_NOT_WORK
223      palette_set_color(machine(), pen[i], 255 * bright, 255 * bright, 255 * bright);
224      #else
225      palette_set_pen_contrast(machine(), pen[i], bright);
226      #endif
227   }
228
229   // draw bitmap (bottom to top)
230   if (m_reg[0] & LCD_R0_DISP)
231   {
232      int x, y;
233      x = 0;
234      y = HD66421_HEIGHT - 1;
235
236      for (int i = 0; i < HD66421_RAM_SIZE; i++)
237      {
238         plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 6) & 3]);
239         plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 4) & 3]);
240         plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 2) & 3]);
241         plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 0) & 3]);
242         if (x >= HD66421_WIDTH)
243         {
244            x = 0;
245            y = y - 1;
246         }
247      }
248   }
249   else
250   {
251      rectangle rect(0, HD66421_WIDTH - 1, 0, HD66421_HEIGHT - 1);
252      bitmap.fill(get_white_pen(machine()), rect);
253   }
254   
255   return 0;
256}
trunk/src/mess/video/hd66421.h
r21684r21685
1/***************************************************************************
2
3  Hitachi HD66421 LCD Controller
4
5  (c) 2001-2007 Tim Schuerewegen
6
7 ***************************************************************************/
8
9#pragma once
10
11#ifndef __HD66421_H__
12#define __HD66421_H__
13
14
15///*************************************************************************
16//  MACROS / CONSTANTS
17///*************************************************************************
18
19//#define HD66421_BRIGHTNESS_DOES_NOT_WORK
20
21#define HD66421_WIDTH   160
22#define HD66421_HEIGHT  100
23
24
25/*----------- defined in video/hd66421.c -----------*/
26
27///*************************************************************************
28//  INTERFACE CONFIGURATION MACROS
29///*************************************************************************
30
31#define MCFG_HD66421_ADD(_tag) \
32   MCFG_DEVICE_ADD(_tag, HD66421, 0)
33
34///*************************************************************************
35//  TYPE DEFINITIONS
36///*************************************************************************
37
38// ======================> hd66421_device
39
40class hd66421_device :  public device_t,
41                  public device_memory_interface
42{
43public:
44   // construction/destruction
45   hd66421_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
46
47   DECLARE_READ8_MEMBER( reg_idx_r );
48   DECLARE_WRITE8_MEMBER( reg_idx_w );
49   DECLARE_READ8_MEMBER( reg_dat_r );
50   DECLARE_WRITE8_MEMBER( reg_dat_w );
51
52   UINT32 update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
53
54protected:
55   // device-level overrides
56   virtual void device_start();
57
58   // device_config_memory_interface overrides
59   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
60
61   // address space configurations
62   const address_space_config      m_space_config;
63
64   inline UINT8 readbyte(offs_t address);
65   inline void writebyte(offs_t address, UINT8 data);
66
67   void plot_pixel(bitmap_ind16 &bitmap, int x, int y, UINT32 color);
68
69private:
70   UINT8 m_cmd, m_reg[32];
71   int m_x, m_y;
72};
73
74
75// device type definition
76extern const device_type HD66421;
77
78
79#endif
trunk/src/mess/video/hd44352.c
r21684r21685
1/***************************************************************************
2
3        Hitachi HD44352 LCD controller
4
5***************************************************************************/
6
7#include "emu.h"
8#include "video/hd44352.h"
9
10#define     LCD_BYTE_INPUT          0x01
11#define     LCD_BYTE_OUTPUT         0x02
12#define     LCD_CHAR_OUTPUT         0x03
13#define     LCD_ON_OFF              0x04
14#define     LCD_CURSOR_GRAPHIC      0x06
15#define     LCD_CURSOR_CHAR         0x07
16#define     LCD_SCROLL_CHAR_WIDTH   0x08
17#define     LCD_CURSOR_STATUS       0x09
18#define     LCD_USER_CHARACTER      0x0b
19#define     LCD_CONTRAST            0x0c
20#define     LCD_IRQ_FREQUENCY       0x0d
21#define     LCD_CURSOR_POSITION     0x0e
22
23
24// devices
25const device_type HD44352 = &device_creator<hd44352_device>;
26
27//**************************************************************************
28//  live device
29//**************************************************************************
30
31//-------------------------------------------------
32//  hd44352_device - constructor
33//-------------------------------------------------
34
35hd44352_device::hd44352_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock):
36   device_t(mconfig, HD44352, "hd44352", tag, owner, clock)
37{
38}
39
40//-------------------------------------------------
41//  device_config_complete - perform any
42//  operations now that the configuration is
43//  complete
44//-------------------------------------------------
45
46void hd44352_device::device_config_complete()
47{
48   // inherit a copy of the static data
49   const hd44352_interface *intf = reinterpret_cast<const hd44352_interface *>(static_config());
50   if (intf != NULL)
51      *static_cast<hd44352_interface *>(this) = *intf;
52
53   // or initialize to defaults if none provided
54   else
55   {
56      memset(&m_on, 0, sizeof(m_on));
57   }
58}
59
60//-------------------------------------------------
61//  device_validity_check - perform validity checks
62//  on this device
63//-------------------------------------------------
64
65void hd44352_device::device_validity_check(validity_checker &valid) const
66{
67}
68//-------------------------------------------------
69//  device_start - device-specific startup
70//-------------------------------------------------
71
72void hd44352_device::device_start()
73{
74   m_on.resolve(m_on_cb, *this);
75
76   m_on_timer = timer_alloc(ON_TIMER);
77   m_on_timer->adjust(attotime::from_hz(m_clock/16384), 0, attotime::from_hz(m_clock/16384));
78
79   save_item( NAME(m_control_lines));
80   save_item( NAME(m_data_bus));
81   save_item( NAME(m_state));
82   save_item( NAME(m_offset));
83   save_item( NAME(m_char_width));
84   save_item( NAME(m_bank));
85   save_item( NAME(m_lcd_on));
86   save_item( NAME(m_scroll));
87   save_item( NAME(m_contrast));
88   save_item( NAME(m_byte_count));
89   save_item( NAME(m_cursor_status));
90   save_item( NAME(m_cursor_x));
91   save_item( NAME(m_cursor_y));
92   save_item( NAME(m_cursor_lcd));
93   save_item( NAME(m_video_ram[0]));
94   save_item( NAME(m_video_ram[1]));
95   save_item( NAME(m_par));
96   save_item( NAME(m_cursor));
97   save_item( NAME(m_custom_char[0]));
98   save_item( NAME(m_custom_char[1]));
99   save_item( NAME(m_custom_char[2]));
100   save_item( NAME(m_custom_char[3]));
101}
102
103
104//-------------------------------------------------
105//  device_reset - device-specific reset
106//-------------------------------------------------
107
108void hd44352_device::device_reset()
109{
110   memset(m_video_ram, 0x00, sizeof(m_video_ram));
111   memset(m_par, 0x00, sizeof(m_par));
112   memset(m_custom_char, 0x00, sizeof(m_custom_char));
113   memset(m_cursor, 0x00, sizeof(m_cursor));
114   m_control_lines = 0;
115   m_data_bus = 0xff;
116   m_state = 0;
117   m_bank = 0;
118   m_offset = 0;
119   m_char_width = 6;
120   m_lcd_on = 0;
121   m_scroll = 0;
122   m_byte_count = 0;
123   m_cursor_status = 0;
124   m_cursor_x = 0;
125   m_cursor_y = 0;
126   m_cursor_lcd = 0;
127   m_contrast = 0;
128}
129
130
131//-------------------------------------------------
132//  device_timer - handler timer events
133//-------------------------------------------------
134void hd44352_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
135{
136   switch(id)
137   {
138      case ON_TIMER:
139         if (m_control_lines & 0x40)
140         {
141            m_on(ASSERT_LINE);
142            m_on(CLEAR_LINE);
143         }
144         break;
145   }
146}
147
148//**************************************************************************
149//  device interface
150//**************************************************************************
151
152UINT32 hd44352_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
153{
154   UINT8 cw = m_char_width;
155
156   bitmap.fill(0, cliprect);
157
158   if (m_control_lines&0x80 && m_lcd_on)
159   {
160      for (int a=0; a<2; a++)
161         for (int py=0; py<4; py++)
162            for (int px=0; px<16; px++)
163               if (BIT(m_cursor_status, 4) && px == m_cursor_x && py == m_cursor_y && a == m_cursor_lcd)
164               {
165                  //draw the cursor
166                  for (int c=0; c<cw; c++)
167                  {
168                     UINT8 d = compute_newval((m_cursor_status>>5) & 0x07, m_video_ram[a][py*16*cw + px*cw + c + m_scroll * 48], m_cursor[c]);
169                     for (int b=0; b<8; b++)
170                     {
171                        bitmap.pix16(py*8 + b, a*cw*16 + px*cw + c) = BIT(d, 7-b);
172                     }
173                  }
174               }
175               else
176               {
177                  for (int c=0; c<cw; c++)
178                  {
179                     UINT8 d = m_video_ram[a][py*16*cw + px*cw + c + m_scroll * 48];
180                     for (int b=0; b<8; b++)
181                     {
182                        bitmap.pix16(py*8 + b, a*cw*16 + px*cw + c) = BIT(d, 7-b);
183                     }
184                  }
185               }
186   }
187
188   return 0;
189}
190
191
192void hd44352_device::control_write(UINT8 data)
193{
194   if(m_control_lines == data)
195      m_state = 0;
196
197   m_control_lines = data;
198}
199
200UINT8 hd44352_device::compute_newval(UINT8 type, UINT8 oldval, UINT8 newval)
201{
202   switch(type & 0x07)
203   {
204      case 0x00:
205         return (~oldval) & newval;
206      case 0x01:
207         return oldval ^ newval;
208      case 0x03:
209         return oldval & (~newval);
210      case 0x04:
211         return newval;
212      case 0x05:
213         return oldval | newval;
214      case 0x07:
215         return oldval;
216      case 0x02:
217      case 0x06:
218      default:
219         return 0;
220   }
221}
222
223UINT8 hd44352_device::get_char(UINT16 pos)
224{
225   switch ((UINT8)pos/8)
226   {
227      case 0xcf:
228         return m_custom_char[0][pos%8];
229      case 0xdf:
230         return m_custom_char[1][pos%8];
231      case 0xef:
232         return m_custom_char[2][pos%8];
233      case 0xff:
234         return m_custom_char[3][pos%8];
235      default:
236         return region()->u8(pos);
237   }
238}
239
240void hd44352_device::data_write(UINT8 data)
241{
242   // verify that controller is active
243   if (!(m_control_lines&0x80))
244      return;
245
246   if (m_control_lines & 0x01)
247   {
248      if (!(m_control_lines&0x02) && !(m_control_lines&0x04))
249         return;
250
251      switch (m_state)
252      {
253         case 0:     //parameter 0
254            m_par[m_state++] = data;
255            break;
256         case 1:     //parameter 1
257            m_par[m_state++] = data;
258            break;
259         case 2:     //parameter 2
260            m_par[m_state++] = data;
261            break;
262      }
263
264      switch (m_par[0] & 0x0f)
265      {
266         case LCD_BYTE_INPUT:
267         case LCD_CHAR_OUTPUT:
268            {
269               if (m_state == 1)
270                  m_bank = BIT(data, 4);
271               else if (m_state == 2)
272                  m_offset = ((data>>1)&0x3f) % 48 + (BIT(data,7) * 48);
273               else if (m_state == 3)
274                  m_offset += ((data & 0x03) * 96);
275            }
276            break;
277         case LCD_BYTE_OUTPUT:
278            {
279               if (m_state == 1)
280                  m_bank = BIT(data, 4);
281               else if (m_state == 2)
282                  m_offset = ((data>>1)&0x3f) % 48 + (BIT(data,7) * 48);
283               else if (m_state == 3)
284                  m_offset += ((data & 0x03) * 96);
285            }
286            break;
287         case LCD_ON_OFF:
288            {
289               if (m_state == 1)
290                  m_lcd_on = BIT(data, 4);
291               m_data_bus = 0xff;
292               m_state = 0;
293            }
294            break;
295         case LCD_SCROLL_CHAR_WIDTH:
296            {
297               if (m_state == 1)
298               {
299                  m_char_width = 8-((data>>4)&3);
300                  m_scroll = ((data>>6)&3);
301               }
302
303               m_data_bus = 0xff;
304               m_state = 0;
305            }
306            break;
307         case LCD_CURSOR_STATUS:
308            {
309               if (m_state == 1)
310                  m_cursor_status = data;
311               m_data_bus = 0xff;
312               m_state = 0;
313            }
314            break;
315         case LCD_CONTRAST:
316            {
317               if (m_state == 1)
318                  m_contrast = (m_contrast & 0x00ffff) | (data<<16);
319               else if (m_state == 2)
320                  m_contrast = (m_contrast & 0xff00ff) | (data<<8);
321               else if (m_state == 3)
322               {
323                  m_contrast = (m_contrast & 0xffff00) | (data<<0);
324                  m_state = 0;
325               }
326
327               m_data_bus = 0xff;
328            }
329            break;
330         case LCD_IRQ_FREQUENCY:
331            {
332               if (m_state == 1)
333               {
334                  UINT32 on_timer_rate;
335
336                  switch((data>>4) & 0x0f)
337                  {
338                     case 0x00:      on_timer_rate = 16384;      break;
339                     case 0x01:      on_timer_rate = 8;          break;
340                     case 0x02:      on_timer_rate = 16;         break;
341                     case 0x03:      on_timer_rate = 32;         break;
342                     case 0x04:      on_timer_rate = 64;         break;
343                     case 0x05:      on_timer_rate = 128;        break;
344                     case 0x06:      on_timer_rate = 256;        break;
345                     case 0x07:      on_timer_rate = 512;        break;
346                     case 0x08:      on_timer_rate = 1024;       break;
347                     case 0x09:      on_timer_rate = 2048;       break;
348                     case 0x0a:      on_timer_rate = 4096;       break;
349                     case 0x0b:      on_timer_rate = 4096;       break;
350                     default:        on_timer_rate = 8192;       break;
351                  }
352
353                  m_on_timer->adjust(attotime::from_hz(m_clock/on_timer_rate), 0, attotime::from_hz(m_clock/on_timer_rate));
354               }
355               m_data_bus = 0xff;
356               m_state = 0;
357            }
358            break;
359         case LCD_CURSOR_POSITION:
360            {
361               if (m_state == 1)
362                  m_cursor_lcd = BIT(data, 4);    //0:left lcd 1:right lcd;
363               else if (m_state == 2)
364                  m_cursor_x = ((data>>1)&0x3f) % 48 + (BIT(data,7) * 48);
365               else if (m_state == 3)
366               {
367                  m_cursor_y = data & 0x03;
368                  m_state = 0;
369               }
370
371               m_data_bus = 0xff;
372            }
373            break;
374      }
375
376      m_byte_count = 0;
377      m_data_bus = 0xff;
378   }
379   else
380   {
381      switch (m_par[0] & 0x0f)
382      {
383         case LCD_BYTE_INPUT:
384            {
385               if (((m_par[0]>>5) & 0x07) != 0x03)
386                  break;
387
388               m_offset %= 0x180;
389               m_data_bus = ((m_video_ram[m_bank][m_offset]<<4)&0xf0) | ((m_video_ram[m_bank][m_offset]>>4)&0x0f);
390               m_offset++; m_byte_count++;
391            }
392            break;
393         case LCD_BYTE_OUTPUT:
394            {
395               m_offset %= 0x180;
396               m_video_ram[m_bank][m_offset] = compute_newval((m_par[0]>>5) & 0x07, m_video_ram[m_bank][m_offset], data);
397               m_offset++; m_byte_count++;
398
399               m_data_bus = 0xff;
400            }
401            break;
402         case LCD_CHAR_OUTPUT:
403            {
404               int char_pos = data*8;
405
406               for (int i=0; i<m_char_width; i++)
407               {
408                  m_offset %= 0x180;
409                  m_video_ram[m_bank][m_offset] = compute_newval((m_par[0]>>5) & 0x07, m_video_ram[m_bank][m_offset], get_char(char_pos));
410                  m_offset++; char_pos++;
411               }
412
413               m_byte_count++;
414               m_data_bus = 0xff;
415            }
416            break;
417         case LCD_CURSOR_GRAPHIC:
418            if (m_byte_count<8)
419            {
420               m_cursor[m_byte_count] = data;
421               m_byte_count++;
422               m_data_bus = 0xff;
423            }
424            break;
425         case LCD_CURSOR_CHAR:
426            if (m_byte_count<1)
427            {
428               UINT8 char_code = ((data<<4)&0xf0) | ((data>>4)&0x0f);
429
430               for (int i=0; i<8; i++)
431                  m_cursor[i] = get_char(char_code*8 + i);
432
433               m_byte_count++;
434               m_data_bus = 0xff;
435            }
436            break;
437         case LCD_USER_CHARACTER:
438            if (m_byte_count<8)
439            {
440               m_custom_char[(m_par[1]&0x03)][m_byte_count] = data;
441               m_byte_count++;
442               m_data_bus = 0xff;
443            }
444            break;
445         default:
446            m_data_bus = 0xff;
447      }
448
449      m_state=0;
450   }
451}
452
453UINT8 hd44352_device::data_read()
454{
455   return m_data_bus;
456}
trunk/src/mess/video/hd44352.h
r21684r21685
1/***************************************************************************
2
3        Hitachi HD44352 LCD controller
4
5***************************************************************************/
6
7#pragma once
8
9#ifndef __hd44352_H__
10#define __hd44352_H__
11
12
13#define MCFG_HD44352_ADD( _tag, _clock, _config) \
14   MCFG_DEVICE_ADD( _tag, HD44352, _clock ) \
15   MCFG_DEVICE_CONFIG( _config )
16
17//**************************************************************************
18//  TYPE DEFINITIONS
19//**************************************************************************
20
21
22// ======================> hd44352_interface
23
24struct hd44352_interface
25{
26   devcb_write_line    m_on_cb;        // ON line
27};
28
29// ======================> hd44352_device
30
31class hd44352_device :
32                  public device_t,
33                  public hd44352_interface
34{
35public:
36   // construction/destruction
37   hd44352_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
38
39   // device interface
40   UINT8 data_read();
41   void data_write(UINT8 data);
42   void control_write(UINT8 data);
43
44   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
45
46protected:
47   // device-level overrides
48   virtual void device_start();
49   virtual void device_reset();
50   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
51   virtual void device_config_complete();
52   virtual void device_validity_check(validity_checker &valid) const;
53
54private:
55   UINT8 compute_newval(UINT8 type, UINT8 oldval, UINT8 newval);
56   UINT8 get_char(UINT16 pos);
57
58   static const device_timer_id ON_TIMER = 1;
59   emu_timer *m_on_timer;
60
61   UINT8 m_video_ram[2][0x180];
62   UINT8 m_control_lines;
63   UINT8 m_data_bus;
64   UINT8 m_par[3];
65   UINT8 m_state;
66   UINT16 m_bank;
67   UINT16 m_offset;
68   UINT8 m_char_width;
69   UINT8 m_lcd_on;
70   UINT8 m_scroll;
71   UINT32 m_contrast;
72
73   UINT8 m_custom_char[4][8];      // 4 chars * 8 bytes
74   UINT8 m_byte_count;
75   UINT8 m_cursor_status;
76   UINT8 m_cursor[8];
77   UINT8 m_cursor_x;
78   UINT8 m_cursor_y;
79   UINT8 m_cursor_lcd;
80
81   devcb_resolved_write_line m_on;         // ON line callback
82};
83
84// device type definition
85extern const device_type HD44352;
86
87#endif
trunk/src/mess/drivers/c65.c
r21684r21685
5858#include "video/vic4567.h"
5959#include "includes/cbm.h"
6060#include "machine/cbm_snqk.h"
61#include "includes/c64_legacy.h"
6261#include "includes/c65.h"
6362#include "machine/cbmiec.h"
6463#include "machine/ram.h"
r21684r21685
202201 *
203202 *************************************/
204203
204static int c64_paddle_read( device_t *device, address_space &space, int which )
205{
206   running_machine &machine = device->machine();
207   int pot1 = 0xff, pot2 = 0xff, pot3 = 0xff, pot4 = 0xff, temp;
208   UINT8 cia0porta = mos6526_pa_r(machine.device("cia_0"), space, 0);
209   int controller1 = machine.root_device().ioport("CTRLSEL")->read() & 0x07;
210   int controller2 = machine.root_device().ioport("CTRLSEL")->read() & 0x70;
211   /* Notice that only a single input is defined for Mouse & Lightpen in both ports */
212   switch (controller1)
213   {
214      case 0x01:
215         if (which)
216            pot2 = machine.root_device().ioport("PADDLE2")->read();
217         else
218            pot1 = machine.root_device().ioport("PADDLE1")->read();
219         break;
220
221      case 0x02:
222         if (which)
223            pot2 = machine.root_device().ioport("TRACKY")->read();
224         else
225            pot1 = machine.root_device().ioport("TRACKX")->read();
226         break;
227
228      case 0x03:
229         if (which && (machine.root_device().ioport("JOY1_2B")->read() & 0x20))  /* Joy1 Button 2 */
230            pot1 = 0x00;
231         break;
232
233      case 0x04:
234         if (which)
235            pot2 = machine.root_device().ioport("LIGHTY")->read();
236         else
237            pot1 = machine.root_device().ioport("LIGHTX")->read();
238         break;
239
240      case 0x06:
241         if (which && (machine.root_device().ioport("OTHER")->read() & 0x04))    /* Lightpen Signal */
242            pot2 = 0x00;
243         break;
244
245      case 0x00:
246      case 0x07:
247         break;
248
249      default:
250         logerror("Invalid Controller Setting %d\n", controller1);
251         break;
252   }
253
254   switch (controller2)
255   {
256      case 0x10:
257         if (which)
258            pot4 = machine.root_device().ioport("PADDLE4")->read();
259         else
260            pot3 = machine.root_device().ioport("PADDLE3")->read();
261         break;
262
263      case 0x20:
264         if (which)
265            pot4 = machine.root_device().ioport("TRACKY")->read();
266         else
267            pot3 = machine.root_device().ioport("TRACKX")->read();
268         break;
269
270      case 0x30:
271         if (which && (machine.root_device().ioport("JOY2_2B")->read() & 0x20))  /* Joy2 Button 2 */
272            pot4 = 0x00;
273         break;
274
275      case 0x40:
276         if (which)
277            pot4 = machine.root_device().ioport("LIGHTY")->read();
278         else
279            pot3 = machine.root_device().ioport("LIGHTX")->read();
280         break;
281
282      case 0x60:
283         if (which && (machine.root_device().ioport("OTHER")->read() & 0x04))    /* Lightpen Signal */
284            pot4 = 0x00;
285         break;
286
287      case 0x00:
288      case 0x70:
289         break;
290
291      default:
292         logerror("Invalid Controller Setting %d\n", controller1);
293         break;
294   }
295
296   if (machine.root_device().ioport("CTRLSEL")->read() & 0x80)     /* Swap */
297   {
298      temp = pot1; pot1 = pot3; pot3 = temp;
299      temp = pot2; pot2 = pot4; pot4 = temp;
300   }
301
302   switch (cia0porta & 0xc0)
303   {
304      case 0x40:
305         return which ? pot2 : pot1;
306
307      case 0x80:
308         return which ? pot4 : pot3;
309
310      case 0xc0:
311         return which ? pot2 : pot1;
312
313      default:
314         return 0;
315   }
316}
317
205318READ8_MEMBER( c65_state::sid_potx_r )
206319{
207320   device_t *sid = machine().device("sid_r");
r21684r21685
333446   /* floppy from serial bus */
334447   MCFG_CBM_IEC_ADD(NULL)
335448
336   MCFG_FRAGMENT_ADD(c64_cartslot)
337
338449   /* internal ram */
339450   MCFG_RAM_ADD(RAM_TAG)
340451   MCFG_RAM_DEFAULT_SIZE("128K")
trunk/src/mess/mess.mak
r21684r21685
432432   $(MAME_VIDEO)/amigaaga.o    \
433433   $(MAME_MACHINE)/amiga.o     \
434434   $(MAME_AUDIO)/amiga.o       \
435   $(MAME_MACHINE)/cd32.o  \
435   $(MAME_MACHINE)/cd32.o      \
436436   $(MAME_VIDEO)/tia.o         \
437437   $(MAME_MACHINE)/atari.o     \
438438   $(MAME_VIDEO)/atari.o       \
r21684r21685
456456   $(MAME_VIDEO)/rdpspn16.o    \
457457   $(MAME_MACHINE)/pcshare.o   \
458458   $(MAME_MACHINE)/megadriv.o  \
459   $(MAME_MACHINE)/megacd.o \
460   $(MAME_MACHINE)/megacdcd.o \
461   $(MAME_MACHINE)/mega32x.o \
462   $(MAME_MACHINE)/megavdp.o \
459   $(MAME_MACHINE)/megacd.o    \
460   $(MAME_MACHINE)/megacdcd.o  \
461   $(MAME_MACHINE)/mega32x.o   \
462   $(MAME_MACHINE)/megavdp.o   \
463463   $(MAME_MACHINE)/dc.o        \
464464   $(MAME_DRIVERS)/naomi.o     \
465465   $(MAME_MACHINE)/dc.o        \
r21684r21685
493493   $(MAME_DRIVERS)/vectrex.o   \
494494   $(MAME_VIDEO)/vectrex.o     \
495495   $(MAME_MACHINE)/vectrex.o   \
496   $(MAME_DRIVERS)/cps1.o  \
497   $(MAME_VIDEO)/cps1.o    \
498   $(MAME_DRIVERS)/konamim2.o \
496   $(MAME_DRIVERS)/cps1.o      \
497   $(MAME_VIDEO)/cps1.o        \
498   $(MAME_DRIVERS)/konamim2.o  \
499499
500500
501501#-------------------------------------------------
r21684r21685
506506$(MESSOBJ)/shared.a: \
507507   $(MESS_AUDIO)/mea8000.o     \
508508   $(MESS_AUDIO)/spchroms.o    \
509   $(MESS_MACHINE)/microdrv.o  \
510   $(MESS_MACHINE)/74145.o     \
509   $(MESS_MACHINE)/3c503.o     \
511510   $(MESS_MACHINE)/68561mpcc.o \
512511   $(MESS_MACHINE)/8530scc.o   \
513   $(MESS_MACHINE)/at45dbxx.o  \
514   $(MESS_MACHINE)/ay31015.o   \
515   $(MESS_MACHINE)/er59256.o   \
512   $(MESS_MACHINE)/appldriv.o  \
513   $(MESS_MACHINE)/applefdc.o  \
514   $(MESS_MACHINE)/cntr_covox.o\
515   $(MESS_MACHINE)/dp8390.o    \
516516   $(MESS_MACHINE)/hd63450.o   \
517517   $(MESS_MACHINE)/i8271.o     \
518518   $(MESS_MACHINE)/ieee488.o   \
r21684r21685
520520   $(MESS_MACHINE)/kb3600.o    \
521521   $(MESS_MACHINE)/keyboard.o  \
522522   $(MESS_MACHINE)/kr2376.o    \
523   $(MESS_MACHINE)/mc6843.o    \
524   $(MESS_MACHINE)/mc6846.o    \
525   $(MESS_MACHINE)/mc6854.o    \
526   $(MESS_MACHINE)/mm58274c.o  \
523   $(MESS_MACHINE)/mb8795.o    \
524   $(MESS_MACHINE)/microdrv.o  \
525   $(MESS_MACHINE)/midiinport.o    \
526   $(MESS_MACHINE)/midioutport.o   \
527527   $(MESS_MACHINE)/mpc105.o    \
528   $(MESS_MACHINE)/mos6530.o   \
529   $(MESS_MACHINE)/s100.o      \
530   $(MESS_MACHINE)/sed1200.o   \
531528   $(MESS_MACHINE)/msm6222b.o  \
532   $(MESS_MACHINE)/serial.o    \
533529   $(MESS_MACHINE)/ncr5380.o   \
534   $(MESS_MACHINE)/ncr5380n.o  \
530   $(MESS_MACHINE)/ncr5380n.o  \
535531   $(MESS_MACHINE)/ncr5390.o   \
532   $(MESS_MACHINE)/ne1000.o    \
533   $(MESS_MACHINE)/ne2000.o    \
534   $(MESS_MACHINE)/null_modem.o\
536535   $(MESS_MACHINE)/pc_kbdc.o   \
537536   $(MESS_MACHINE)/pc_lpt.o    \
538   $(MESS_MACHINE)/cntr_covox.o \
539   $(MESS_MACHINE)/pcf8593.o   \
537   $(MESS_MACHINE)/s100.o      \
540538   $(MESS_MACHINE)/sa1403d.o   \
539   $(MESS_MACHINE)/sed1200.o   \
540   $(MESS_MACHINE)/serial.o    \
541541   $(MESS_MACHINE)/smartmed.o  \
542542   $(MESS_MACHINE)/smc92x4.o   \
543   $(MESS_MACHINE)/terminal.o  \
544   $(MESS_MACHINE)/teleprinter.o   \
545   $(MESS_MACHINE)/upd7002.o   \
546   $(MESS_MACHINE)/wd11c00_17.o    \
547   $(MESS_MACHINE)/wd2010.o    \
548   $(MESS_VIDEO)/dl1416.o      \
549   $(MESS_VIDEO)/hd44780.o     \
550   $(MESS_VIDEO)/hd66421.o     \
551   $(MESS_VIDEO)/mc6847.o      \
552   $(MESS_VIDEO)/tms3556.o     \
553   $(MESS_VIDEO)/upd7220.o     \
554   $(MESS_MACHINE)/applefdc.o  \
555543   $(MESS_MACHINE)/sonydriv.o  \
556   $(MESS_MACHINE)/appldriv.o  \
557   $(MESS_MACHINE)/dp8390.o    \
558   $(MESS_MACHINE)/ne1000.o    \
559   $(MESS_MACHINE)/ne2000.o    \
560   $(MESS_MACHINE)/3c503.o     \
561   $(MESS_MACHINE)/z80bin.o    \
562   $(MESS_MACHINE)/mb8795.o    \
563   $(MESS_MACHINE)/midiinport.o    \
564   $(MESS_MACHINE)/midioutport.o   \
565   $(MESS_MACHINE)/null_modem.o    \
566   $(MESS_MACHINE)/vcsctrl.o   \
544   $(MESS_MACHINE)/teleprinter.o   \
545   $(MESS_MACHINE)/terminal.o  \
567546   $(MESS_MACHINE)/vcs_joy.o   \
547   $(MESS_MACHINE)/vcs_joybooster.o\
548   $(MESS_MACHINE)/vcs_keypad.o    \
568549   $(MESS_MACHINE)/vcs_lightpen.o  \
569550   $(MESS_MACHINE)/vcs_paddles.o   \
570   $(MESS_MACHINE)/vcs_joybooster.o    \
571551   $(MESS_MACHINE)/vcs_wheel.o \
572   $(MESS_MACHINE)/vcs_keypad.o    \
552   $(MESS_MACHINE)/vcsctrl.o   \
553   $(MESS_MACHINE)/z80bin.o    \
573554
574555
575
576556#-------------------------------------------------
577557# manufacturer-specific groupings for drivers
578558#-------------------------------------------------
r21684r21685
610590
611591$(MESSOBJ)/adc.a:               \
612592   $(MESS_DRIVERS)/super6.o    \
613   $(MESS_DRIVERS)/superslave.o    \
593   $(MESS_DRIVERS)/superslave.o\
614594
615595$(MESSOBJ)/alesis.a:            \
616596   $(MESS_DRIVERS)/alesis.o    \
r21684r21685
659639   $(MESS_MACHINE)/apollo_eth.o  \
660640   $(MESS_MACHINE)/apollo_net.o  \
661641   $(MESS_MACHINE)/apollo_kbd.o  \
662   $(MESS_MACHINE)/3c505.o  \
663   $(MESS_MACHINE)/apollo.o  \
642   $(MESS_MACHINE)/3c505.o     \
643   $(MESS_MACHINE)/apollo.o    \
664644
665645$(MESSOBJ)/apple.a:             \
666646   $(MESS_VIDEO)/apple2.o      \
r21684r21685
680660   $(MESS_MACHINE)/a2thunderclock.o    \
681661   $(MESS_MACHINE)/a2softcard.o \
682662   $(MESS_MACHINE)/a2videoterm.o \
683   $(MESS_MACHINE)/a2ssc.o \
684   $(MESS_MACHINE)/a2swyft.o \
685   $(MESS_MACHINE)/a2eauxslot.o \
663   $(MESS_MACHINE)/a2ssc.o     \
664   $(MESS_MACHINE)/a2swyft.o   \
665   $(MESS_MACHINE)/a2eauxslot.o\
686666   $(MESS_MACHINE)/a2themill.o \
687   $(MESS_MACHINE)/a2sam.o \
688   $(MESS_MACHINE)/a2alfam2.o \
689   $(MESS_MACHINE)/laser128.o \
690   $(MESS_MACHINE)/a2echoii.o \
691   $(MESS_MACHINE)/a2arcadebd.o \
692   $(MESS_MACHINE)/a2midi.o \
693   $(MESS_MACHINE)/a2vulcan.o \
694   $(MESS_MACHINE)/a2zipdrive.o \
667   $(MESS_MACHINE)/a2sam.o     \
668   $(MESS_MACHINE)/a2alfam2.o  \
669   $(MESS_MACHINE)/laser128.o  \
670   $(MESS_MACHINE)/a2echoii.o  \
671   $(MESS_MACHINE)/a2arcadebd.o\
672   $(MESS_MACHINE)/a2midi.o    \
673   $(MESS_MACHINE)/a2vulcan.o  \
674   $(MESS_MACHINE)/a2zipdrive.o\
695675   $(MESS_MACHINE)/a2estd80col.o \
696676   $(MESS_MACHINE)/a2eext80col.o \
697677   $(MESS_MACHINE)/a2eramworks3.o \
r21684r21685
730710   $(MESS_VIDEO)/pds30_cb264.o \
731711   $(MESS_VIDEO)/pds30_procolor816.o \
732712   $(MESS_VIDEO)/pds30_sigmalview.o \
733   $(MESS_VIDEO)/pds30_30hr.o \
734   $(MESS_VIDEO)/pds30_mc30.o \
713   $(MESS_VIDEO)/pds30_30hr.o  \
714   $(MESS_VIDEO)/pds30_mc30.o  \
735715
736716$(MESSOBJ)/applied.a:           \
737717   $(MESS_VIDEO)/mbee.o        \
r21684r21685
821801   $(MESS_DRIVERS)/pv2000.o    \
822802   $(MESS_DRIVERS)/pb1000.o    \
823803   $(MESS_DRIVERS)/fp6000.o    \
824   $(MESS_VIDEO)/hd44352.o     \
825804
826805$(MESSOBJ)/cbm.a:               \
827   $(MESS_DRIVERS)/pet.o      \
806   $(MESS_DRIVERS)/pet.o       \
828807   $(MESS_MACHINE)/petcass.o   \
829   $(MESS_MACHINE)/petexp.o      \
808   $(MESS_MACHINE)/petexp.o    \
830809   $(MESS_MACHINE)/petuser.o   \
831810   $(MESS_MACHINE)/pet_64k.o   \
832811   $(MESS_MACHINE)/superpet.o  \
833812   $(MESS_MACHINE)/mos6702.o   \
834813   $(MESS_DRIVERS)/c64.o       \
835   $(MESS_MACHINE)/c64_legacy.o       \
836814   $(MESS_DRIVERS)/c64dtv.o    \
837815   $(MESS_MACHINE)/c64exp.o    \
838816   $(MESS_MACHINE)/c64user.o   \
r21684r21685
841819   $(MESS_MACHINE)/c64_4ksa.o  \
842820   $(MESS_MACHINE)/c64_4tba.o  \
843821   $(MESS_MACHINE)/c64_16kb.o  \
844   $(MESS_MACHINE)/c64_bn1541.o    \
822   $(MESS_MACHINE)/c64_bn1541.o\
845823   $(MESS_MACHINE)/c64_comal80.o   \
846824   $(MESS_MACHINE)/c64_cpm.o   \
847825   $(MESS_MACHINE)/c64_currah_speech.o \
r21684r21685
856834   $(MESS_MACHINE)/c64_exos.o  \
857835   $(MESS_MACHINE)/c64_fcc.o   \
858836   $(MESS_MACHINE)/c64_final.o \
859   $(MESS_MACHINE)/c64_final3.o    \
837   $(MESS_MACHINE)/c64_final3.o\
860838   $(MESS_MACHINE)/c64_fun_play.o  \
861839   $(MESS_MACHINE)/c64_geocable.o  \
862840   $(MESS_MACHINE)/c64_georam.o    \
r21684r21685
874852   $(MESS_MACHINE)/c64_midi_siel.o   \
875853   $(MESS_MACHINE)/c64_mikro_assembler.o   \
876854   $(MESS_MACHINE)/c64_multiscreen.o   \
877   $(MESS_MACHINE)/c64_neoram.o    \
855   $(MESS_MACHINE)/c64_neoram.o\
878856   $(MESS_MACHINE)/c64_ocean.o \
879857   $(MESS_MACHINE)/c64_pagefox.o   \
880858   $(MESS_MACHINE)/c64_prophet64.o \
r21684r21685
903881   $(MESS_MACHINE)/c64_warp_speed.o    \
904882   $(MESS_MACHINE)/c64_westermann.o    \
905883   $(MESS_MACHINE)/c64_xl80.o  \
906   $(MESS_MACHINE)/c64_zaxxon.o    \
884   $(MESS_MACHINE)/c64_zaxxon.o\
907885   $(MESS_MACHINE)/interpod.o  \
908886   $(MESS_DRIVERS)/vic10.o     \
909887   $(MESS_MACHINE)/vic10exp.o  \
r21684r21685
933911   $(MESS_MACHINE)/cbm2_std.o  \
934912   $(MESS_MACHINE)/cbm2_24k.o  \
935913   $(MESS_MACHINE)/cbm2_graphic.o  \
936   $(MESS_MACHINE)/cbm2user.o  \
914   $(MESS_MACHINE)/cbm2user.o  \
937915   $(MESS_DRIVERS)/c65.o       \
938916   $(MESS_MACHINE)/c65.o       \
939917   $(MESS_DRIVERS)/c128.o      \
r21684r21685
950928   $(MESS_MACHINE)/d9060hd.o   \
951929   $(MESS_MACHINE)/softbox.o   \
952930   $(MESS_MACHINE)/serialbox.o \
953   $(MESS_MACHINE)/cmdhd.o \
931   $(MESS_MACHINE)/cmdhd.o     \
954932   $(MESS_MACHINE)/fd2000.o    \
955933   $(MESS_DRIVERS)/clcd.o      \
956934   $(MESS_MACHINE)/cbm.o       \
r21684r21685
11661144$(MESSOBJ)/exidy.a:             \
11671145   $(MESS_MACHINE)/sorcerer.o  \
11681146   $(MESS_DRIVERS)/sorcerer.o  \
1169   $(MESS_MACHINE)/micropolis.o    \
1147   $(MESS_MACHINE)/micropolis.o\
11701148
11711149$(MESSOBJ)/fairch.a:            \
11721150   $(MESS_VIDEO)/channelf.o    \
r21684r21685
11791157   $(MESS_MACHINE)/upd71071.o  \
11801158   $(MESS_MACHINE)/fm_scsi.o   \
11811159   $(MESS_DRIVERS)/fm7.o       \
1182   $(MESS_VIDEO)/fm7.o     \
1160   $(MESS_VIDEO)/fm7.o         \
11831161
11841162$(MESSOBJ)/funtech.a:           \
11851163   $(MESS_DRIVERS)/supracan.o  \
r21684r21685
12111189   $(MESS_MACHINE)/mboard.o    \
12121190   $(MESS_DRIVERS)/glasgow.o   \
12131191   $(MESS_DRIVERS)/mephisto.o  \
1214      $(MESS_DRIVERS)/mmodular.o  \
1192   $(MESS_DRIVERS)/mmodular.o  \
12151193
12161194
12171195$(MESSOBJ)/hitachi.a:           \
12181196   $(MESS_DRIVERS)/bmjr.o      \
12191197   $(MESS_DRIVERS)/bml3.o      \
1220   $(MESS_DRIVERS)/b16.o           \
1198   $(MESS_DRIVERS)/b16.o       \
12211199
12221200$(MESSOBJ)/homebrew.a:          \
12231201   $(MESS_DRIVERS)/4004clk.o   \
r21684r21685
13011279   $(MESS_MACHINE)/abc_dos.o   \
13021280   $(MESS_MACHINE)/abc_fd2.o   \
13031281   $(MESS_MACHINE)/abc_hdc.o   \
1304   $(MESS_MACHINE)/abc_uni800.o    \
1282   $(MESS_MACHINE)/abc_uni800.o\
13051283   $(MESS_MACHINE)/abc_sio.o   \
13061284   $(MESS_MACHINE)/abc_slutprov.o  \
13071285   $(MESS_MACHINE)/abc_turbo.o \
r21684r21685
13291307$(MESSOBJ)/matsushi.a:          \
13301308   $(MESS_DRIVERS)/jr100.o     \
13311309   $(MESS_DRIVERS)/jr200.o     \
1332   $(MESS_DRIVERS)/myb3k.o         \
1310   $(MESS_DRIVERS)/myb3k.o     \
13331311
13341312$(MESSOBJ)/mb.a:                \
13351313   $(MESS_DRIVERS)/microvsn.o  \
r21684r21685
13661344
13671345$(MESSOBJ)/morrow.a:            \
13681346   $(MESS_DRIVERS)/mpz80.o     \
1369   $(MESS_MACHINE)/s100_dj2db.o        \
1370   $(MESS_MACHINE)/s100_djdma.o        \
1347   $(MESS_MACHINE)/s100_dj2db.o\
1348   $(MESS_MACHINE)/s100_djdma.o\
13711349   $(MESS_MACHINE)/s100_mm65k16s.o     \
13721350   $(MESS_MACHINE)/s100_wunderbus.o    \
13731351
r21684r21685
14301408   $(MESS_MACHINE)/sns_sdd1.o  \
14311409   $(MESS_MACHINE)/sns_sfx.o   \
14321410   $(MESS_MACHINE)/sns_spc7110.o \
1433   $(MESS_MACHINE)/sns_sufami.o \
1411   $(MESS_MACHINE)/sns_sufami.o\
14341412   $(MESS_MACHINE)/sns_upd.o   \
14351413   $(MESS_DRIVERS)/snes.o      \
14361414   $(MESS_DRIVERS)/n64.o       \
r21684r21685
14831461
14841462$(MESSOBJ)/palm.a:              \
14851463   $(MESS_DRIVERS)/palm.o      \
1486   $(MESS_MACHINE)/mc68328.o   \
14871464   $(MESS_VIDEO)/mc68328.o     \
14881465   $(MESS_DRIVERS)/palmz22.o   \
14891466
r21684r21685
14941471$(MESSOBJ)/pitronic.a:          \
14951472   $(MESS_DRIVERS)/beta.o      \
14961473
1497$(MESSOBJ)/pc.a:            \
1474$(MESSOBJ)/pc.a:                \
14981475   $(MESS_VIDEO)/pc_aga.o      \
14991476   $(MESS_MACHINE)/tandy1t.o   \
15001477   $(MESS_MACHINE)/europc.o    \
r21684r21685
15081485$(MESSOBJ)/pc9801.a:            \
15091486   $(MESS_MACHINE)/pc9801_26.o \
15101487   $(MESS_MACHINE)/pc9801_86.o \
1511   $(MESS_MACHINE)/pc9801_118.o    \
1488   $(MESS_MACHINE)/pc9801_118.o\
15121489   $(MESS_MACHINE)/pc9801_cbus.o   \
1513   $(MESS_MACHINE)/pc9801_kbd.o    \
1490   $(MESS_MACHINE)/pc9801_kbd.o\
15141491
15151492$(MESSOBJ)/pcshare.a:           \
15161493   $(MESS_MACHINE)/pc_turbo.o  \
r21684r21685
15181495   $(MESS_MACHINE)/pc_joy.o    \
15191496   $(MESS_MACHINE)/pc_keyboards.o \
15201497   $(MESS_MACHINE)/kb_keytro.o \
1521   $(MESS_MACHINE)/kb_msnat.o \
1498   $(MESS_MACHINE)/kb_msnat.o \
15221499   $(MESS_MACHINE)/isa_adlib.o \
15231500   $(MESS_MACHINE)/ser_mouse.o \
15241501   $(MESS_MACHINE)/isa_com.o   \
r21684r21685
15281505   $(MESS_MACHINE)/isa_gus.o   \
15291506   $(MESS_MACHINE)/isa_hdc.o   \
15301507   $(MESS_MACHINE)/isa_ibm_mfc.o   \
1531   $(MESS_MACHINE)/isa_mpu401.o    \
1508   $(MESS_MACHINE)/isa_mpu401.o\
15321509   $(MESS_MACHINE)/isa_sblaster.o  \
15331510   $(MESS_MACHINE)/isa_stereo_fx.o \
15341511   $(MESS_MACHINE)/isa_ssi2001.o   \
15351512   $(MESS_MACHINE)/isa_ide.o   \
1536   $(MESS_MACHINE)/isa_ide_cd.o    \
1513   $(MESS_MACHINE)/isa_ide_cd.o\
15371514   $(MESS_MACHINE)/isa_aha1542.o   \
15381515   $(MESS_VIDEO)/isa_cga.o     \
15391516   $(MESS_VIDEO)/isa_mda.o     \
r21684r21685
15751552
15761553$(MESSOBJ)/psion.a:             \
15771554   $(MESS_DRIVERS)/psion.o     \
1578   $(MESS_MACHINE)/psion_pack.o    \
1555   $(MESS_MACHINE)/psion_pack.o\
15791556
15801557$(MESSOBJ)/radio.a:             \
15811558   $(MESS_DRIVERS)/radio86.o   \
r21684r21685
15891566$(MESSOBJ)/rca.a:               \
15901567   $(MESS_DRIVERS)/studio2.o   \
15911568   $(MESS_DRIVERS)/vip.o       \
1592   $(MESS_MACHINE)/vip_byteio.o    \
1569   $(MESS_MACHINE)/vip_byteio.o\
15931570   $(MESS_MACHINE)/vip_exp.o   \
15941571   $(MESS_MACHINE)/vp550.o     \
15951572   $(MESS_MACHINE)/vp570.o     \
r21684r21685
17001677   $(MESS_DRIVERS)/x1twin.o    \
17011678   $(MESS_DRIVERS)/mz2500.o    \
17021679   $(MESS_DRIVERS)/pce220.o    \
1703   $(MESS_MACHINE)/pce220_ser.o    \
1680   $(MESS_MACHINE)/pce220_ser.o\
17041681   $(MESS_DRIVERS)/mz6500.o    \
17051682
17061683$(MESSOBJ)/sinclair.a:          \
17071684   $(MESS_VIDEO)/spectrum.o    \
17081685   $(MESS_VIDEO)/timex.o       \
1709   $(MESS_VIDEO)/zx.o      \
1686   $(MESS_VIDEO)/zx.o          \
17101687   $(MESS_DRIVERS)/zx.o        \
17111688   $(MESS_MACHINE)/zx.o        \
17121689   $(MESS_DRIVERS)/spectrum.o  \
r21684r21685
18041781   $(MESS_VIDEO)/tmc600.o      \
18051782   $(MESS_DRIVERS)/tmc2000e.o  \
18061783
1807$(MESSOBJ)/tem.a:           \
1784$(MESSOBJ)/tem.a:               \
18081785   $(MESS_DRIVERS)/tec1.o      \
18091786
1810$(MESSOBJ)/tesla.a:         \
1787$(MESSOBJ)/tesla.a:             \
18111788   $(MESS_DRIVERS)/ondra.o     \
18121789   $(MESS_MACHINE)/ondra.o     \
18131790   $(MESS_VIDEO)/ondra.o       \
r21684r21685
18341811   $(MESS_MACHINE)/990_hd.o    \
18351812   $(MESS_MACHINE)/990_tap.o   \
18361813   $(MESS_MACHINE)/ti990.o     \
1837   $(MESS_MACHINE)/at29040a.o  \
18381814   $(MESS_MACHINE)/ti99/datamux.o  \
18391815   $(MESS_MACHINE)/ti99/videowrp.o \
18401816   $(MESS_MACHINE)/ti99/grom.o \
r21684r21685
18461822   $(MESS_MACHINE)/ti99/ti32kmem.o  \
18471823   $(MESS_MACHINE)/ti99/ti_fdc.o  \
18481824   $(MESS_MACHINE)/ti99/bwg.o  \
1849   $(MESS_MACHINE)/ti99/hfdc.o \
1825   $(MESS_MACHINE)/ti99/hfdc.o \
18501826   $(MESS_MACHINE)/ti99/ti99_hd.o  \
18511827   $(MESS_MACHINE)/ti99/p_code.o \
18521828   $(MESS_MACHINE)/ti99/myarcmem.o \
r21684r21685
18541830   $(MESS_MACHINE)/ti99/tn_ide.o \
18551831   $(MESS_MACHINE)/ti99/tn_usbsm.o \
18561832   $(MESS_MACHINE)/ti99/evpc.o \
1857   $(MESS_MACHINE)/ti99/hsgpl.o    \
1833   $(MESS_MACHINE)/ti99/hsgpl.o\
18581834   $(MESS_MACHINE)/ti99/ti_rs232.o \
18591835   $(MESS_MACHINE)/ti99/spchsyn.o  \
18601836   $(MESS_MACHINE)/ti99/speech8.o  \
r21684r21685
18961872$(MESSOBJ)/toshiba.a:           \
18971873   $(MESS_DRIVERS)/pasopia.o   \
18981874   $(MESS_DRIVERS)/pasopia7.o  \
1899   $(MESS_DRIVERS)/paso1600.o      \
1875   $(MESS_DRIVERS)/paso1600.o  \
19001876
19011877$(MESSOBJ)/trs.a:               \
19021878   $(MESS_MACHINE)/6883sam.o   \
19031879   $(MESS_MACHINE)/ds1315.o    \
19041880   $(MESS_MACHINE)/coco.o      \
1905   $(MESS_MACHINE)/coco12.o        \
1906   $(MESS_DRIVERS)/coco12.o        \
1881   $(MESS_MACHINE)/coco12.o    \
1882   $(MESS_DRIVERS)/coco12.o    \
19071883   $(MESS_MACHINE)/coco3.o     \
19081884   $(MESS_DRIVERS)/coco3.o     \
1909   $(MESS_VIDEO)/gime.o            \
1910   $(MESS_MACHINE)/dragon.o        \
1911   $(MESS_DRIVERS)/dragon.o        \
1912   $(MESS_MACHINE)/dgnalpha.o      \
1913   $(MESS_MACHINE)/coco_vhd.o      \
1914   $(MESS_MACHINE)/cococart.o      \
1915   $(MESS_MACHINE)/coco_232.o      \
1885   $(MESS_VIDEO)/gime.o        \
1886   $(MESS_MACHINE)/dragon.o    \
1887   $(MESS_DRIVERS)/dragon.o    \
1888   $(MESS_MACHINE)/dgnalpha.o  \
1889   $(MESS_MACHINE)/coco_vhd.o  \
1890   $(MESS_MACHINE)/cococart.o  \
1891   $(MESS_MACHINE)/coco_232.o  \
19161892   $(MESS_MACHINE)/coco_orch90.o\
1917   $(MESS_MACHINE)/coco_pak.o      \
1918   $(MESS_MACHINE)/coco_fdc.o      \
1919   $(MESS_MACHINE)/coco_multi.o    \
1893   $(MESS_MACHINE)/coco_pak.o  \
1894   $(MESS_MACHINE)/coco_fdc.o  \
1895   $(MESS_MACHINE)/coco_multi.o\
19201896   $(MESS_DRIVERS)/mc10.o      \
19211897   $(MESS_MACHINE)/trs80.o     \
19221898   $(MESS_VIDEO)/trs80.o       \
r21684r21685
19901966   $(MESS_DRIVERS)/wangpc.o    \
19911967   $(MESS_MACHINE)/wangpcbus.o \
19921968   $(MESS_MACHINE)/wangpckb.o  \
1993   $(MESS_MACHINE)/wangpc_emb.o    \
1994   $(MESS_MACHINE)/wangpc_lic.o    \
1995   $(MESS_MACHINE)/wangpc_lvc.o    \
1996   $(MESS_MACHINE)/wangpc_mcc.o    \
1997   $(MESS_MACHINE)/wangpc_mvc.o    \
1998   $(MESS_MACHINE)/wangpc_rtc.o    \
1999   $(MESS_MACHINE)/wangpc_tig.o    \
2000   $(MESS_MACHINE)/wangpc_wdc.o    \
1969   $(MESS_MACHINE)/wangpc_emb.o\
1970   $(MESS_MACHINE)/wangpc_lic.o\
1971   $(MESS_MACHINE)/wangpc_lvc.o\
1972   $(MESS_MACHINE)/wangpc_mcc.o\
1973   $(MESS_MACHINE)/wangpc_mvc.o\
1974   $(MESS_MACHINE)/wangpc_rtc.o\
1975   $(MESS_MACHINE)/wangpc_tig.o\
1976   $(MESS_MACHINE)/wangpc_wdc.o\
20011977
20021978$(MESSOBJ)/wavemate.a:          \
20031979   $(MESS_DRIVERS)/bullet.o    \
r21684r21685
20151991   $(MESS_MACHINE)/iq151cart.o \
20161992   $(MESS_MACHINE)/iq151_rom.o \
20171993   $(MESS_MACHINE)/iq151_disc2.o   \
2018   $(MESS_MACHINE)/iq151_minigraf.o    \
1994   $(MESS_MACHINE)/iq151_minigraf.o\
20191995   $(MESS_MACHINE)/iq151_ms151a.o  \
20201996   $(MESS_MACHINE)/iq151_staper.o  \
20211997   $(MESS_VIDEO)/iq151_grafik.o    \
trunk/src/mess/machine/mc68328.c
r21684r21685
1/**********************************************************************
2
3    Motorola 68328 ("DragonBall") System-on-a-Chip implementation
4
5    By MooglyGuy
6    contact mooglyguy@gmail.com with licensing and usage questions.
7
8**********************************************************************/
9
10#include "emu.h"
11#include "cpu/m68000/m68000.h"
12#include "includes/mc68328.h"
13#include "mc68328.h"
14
15#define VERBOSE_LEVEL   (0)
16
17INLINE void verboselog(running_machine &machine, int n_level, const char *s_fmt, ...)
18{
19   if( VERBOSE_LEVEL >= n_level )
20   {
21      va_list v;
22      char buf[ 32768 ];
23      va_start( v, s_fmt );
24      vsprintf( buf, s_fmt, v );
25      va_end( v );
26      logerror( "%s: %s", machine.describe_context(), buf );
27   }
28}
29
30static void mc68328_set_interrupt_line(device_t *device, UINT32 line, UINT32 active)
31{
32   mc68328_t* mc68328 = mc68328_get_safe_token( device );
33   device_t *cpu = device->machine().device(mc68328->iface->m68k_cpu_tag);
34
35   if(active)
36   {
37      mc68328->regs.ipr |= line;
38
39      if(!(mc68328->regs.imr & line) && !(mc68328->regs.isr & line))
40      {
41         mc68328->regs.isr |= line;
42
43         if(mc68328->regs.isr & INT_M68K_LINE7)
44         {
45            cpu->execute().set_input_line_and_vector(M68K_IRQ_7, ASSERT_LINE, mc68328->regs.ivr | 0x07);
46         }
47         else if(mc68328->regs.isr & INT_M68K_LINE6)
48         {
49            cpu->execute().set_input_line_and_vector(M68K_IRQ_6, ASSERT_LINE, mc68328->regs.ivr | 0x06);
50         }
51         else if(mc68328->regs.isr & INT_M68K_LINE5)
52         {
53            cpu->execute().set_input_line_and_vector(M68K_IRQ_5, ASSERT_LINE, mc68328->regs.ivr | 0x05);
54         }
55         else if(mc68328->regs.isr & INT_M68K_LINE4)
56         {
57            cpu->execute().set_input_line_and_vector(M68K_IRQ_4, ASSERT_LINE, mc68328->regs.ivr | 0x04);
58         }
59         else if(mc68328->regs.isr & INT_M68K_LINE3)
60         {
61            cpu->execute().set_input_line_and_vector(M68K_IRQ_3, ASSERT_LINE, mc68328->regs.ivr | 0x03);
62         }
63         else if(mc68328->regs.isr & INT_M68K_LINE2)
64         {
65            cpu->execute().set_input_line_and_vector(M68K_IRQ_2, ASSERT_LINE, mc68328->regs.ivr | 0x02);
66         }
67         else if(mc68328->regs.isr & INT_M68K_LINE1)
68         {
69            cpu->execute().set_input_line_and_vector(M68K_IRQ_1, ASSERT_LINE, mc68328->regs.ivr | 0x01);
70         }
71      }
72   }
73   else
74   {
75      mc68328->regs.isr &= ~line;
76
77      if((line & INT_M68K_LINE7) && !(mc68328->regs.isr & INT_M68K_LINE7))
78      {
79         cpu->execute().set_input_line(M68K_IRQ_7, CLEAR_LINE);
80      }
81      if((line & INT_M68K_LINE6) && !(mc68328->regs.isr & INT_M68K_LINE6))
82      {
83         cpu->execute().set_input_line(M68K_IRQ_6, CLEAR_LINE);
84      }
85      if((line & INT_M68K_LINE5) && !(mc68328->regs.isr & INT_M68K_LINE5))
86      {
87         cpu->execute().set_input_line(M68K_IRQ_5, CLEAR_LINE);
88      }
89      if((line & INT_M68K_LINE4) && !(mc68328->regs.isr & INT_M68K_LINE4))
90      {
91         cpu->execute().set_input_line(M68K_IRQ_4, CLEAR_LINE);
92      }
93      if((line & INT_M68K_LINE3) && !(mc68328->regs.isr & INT_M68K_LINE3))
94      {
95         cpu->execute().set_input_line(M68K_IRQ_3, CLEAR_LINE);
96      }
97      if((line & INT_M68K_LINE2) && !(mc68328->regs.isr & INT_M68K_LINE2))
98      {
99         cpu->execute().set_input_line(M68K_IRQ_2, CLEAR_LINE);
100      }
101      if((line & INT_M68K_LINE1) && !(mc68328->regs.isr & INT_M68K_LINE1))
102      {
103         cpu->execute().set_input_line(M68K_IRQ_1, CLEAR_LINE);
104      }
105   }
106}
107
108static void mc68328_poll_port_d_interrupts(device_t *device)
109{
110   mc68328_t* mc68328 = mc68328_get_safe_token( device );
111   UINT8 line_transitions = mc68328->regs.pddataedge & mc68328->regs.pdirqedge;
112   UINT8 line_holds = mc68328->regs.pddata &~ mc68328->regs.pdirqedge;
113   UINT8 line_interrupts = (line_transitions | line_holds) & mc68328->regs.pdirqen;
114
115   if(line_interrupts)
116   {
117      mc68328_set_interrupt_line(device, line_interrupts << 8, 1);
118   }
119   else
120   {
121      mc68328_set_interrupt_line(device, INT_KBDINTS, 0);
122   }
123}
124
125void mc68328_set_penirq_line(device_t *device, int state)
126{
127   mc68328_t* mc68328 = mc68328_get_safe_token( device );
128
129   if(state)
130   {
131      mc68328_set_interrupt_line(device, INT_PEN, 1);
132   }
133   else
134   {
135      mc68328->regs.ipr &= ~INT_PEN;
136      mc68328_set_interrupt_line(device, INT_PEN, 0);
137   }
138}
139
140void mc68328_set_port_d_lines(device_t *device, UINT8 state, int bit)
141{
142   mc68328_t* mc68328 = mc68328_get_safe_token( device );
143   UINT8 old_button_state = mc68328->regs.pddata;
144
145   if(state & (1 << bit))
146   {
147      mc68328->regs.pddata |= (1 << bit);
148   }
149   else
150   {
151      mc68328->regs.pddata &= ~(1 << bit);
152   }
153
154   mc68328->regs.pddataedge |= ~old_button_state & mc68328->regs.pddata;
155
156   mc68328_poll_port_d_interrupts(device);
157}
158
159static UINT32 mc68328_get_timer_frequency(device_t *device, UINT32 index)
160{
161   mc68328_t* mc68328 = mc68328_get_safe_token( device );
162   UINT32 frequency = 0;
163
164   switch(mc68328->regs.tctl[index] & TCTL_CLKSOURCE)
165   {
166      case TCTL_CLKSOURCE_SYSCLK:
167         frequency = 32768 * 506;
168         break;
169
170      case TCTL_CLKSOURCE_SYSCLK16:
171         frequency = (32768 * 506) / 16;
172         break;
173
174      case TCTL_CLKSOURCE_32KHZ4:
175      case TCTL_CLKSOURCE_32KHZ5:
176      case TCTL_CLKSOURCE_32KHZ6:
177      case TCTL_CLKSOURCE_32KHZ7:
178         frequency = 32768;
179         break;
180   }
181   frequency /= (mc68328->regs.tprer[index] + 1);
182
183   return frequency;
184}
185
186static void mc68328_maybe_start_timer(device_t *device, UINT32 index, UINT32 new_enable)
187{
188   mc68328_t* mc68328 = mc68328_get_safe_token( device );
189
190   if((mc68328->regs.tctl[index] & TCTL_TEN) == TCTL_TEN_ENABLE && (mc68328->regs.tctl[index] & TCTL_CLKSOURCE) > TCTL_CLKSOURCE_STOP)
191   {
192      if((mc68328->regs.tctl[index] & TCTL_CLKSOURCE) == TCTL_CLKSOURCE_TIN)
193      {
194         mc68328->gptimer[index]->adjust(attotime::never);
195      }
196      else if(mc68328->regs.tcmp[index] == 0)
197      {
198         mc68328->gptimer[index]->adjust(attotime::never);
199      }
200      else
201      {
202         UINT32 frequency = mc68328_get_timer_frequency(device, index);
203         attotime period = (attotime::from_hz(frequency) *  mc68328->regs.tcmp[index]);
204
205         if(new_enable)
206         {
207            mc68328->regs.tcn[index] = 0x0000;
208         }
209
210         mc68328->gptimer[index]->adjust(period);
211      }
212   }
213   else
214   {
215      mc68328->gptimer[index]->adjust(attotime::never);
216   }
217}
218
219static void mc68328_timer_compare_event(device_t *device, UINT32 index)
220{
221   mc68328_t* mc68328 = mc68328_get_safe_token( device );
222
223   mc68328->regs.tcn[index] = mc68328->regs.tcmp[index];
224   mc68328->regs.tstat[index] |= TSTAT_COMP;
225
226   if((mc68328->regs.tctl[index] & TCTL_FRR) == TCTL_FRR_RESTART)
227   {
228      UINT32 frequency = mc68328_get_timer_frequency(device, index);
229
230      if(frequency > 0)
231      {
232         attotime period = attotime::from_hz(frequency) * mc68328->regs.tcmp[index];
233
234         mc68328->regs.tcn[index] = 0x0000;
235
236         mc68328->gptimer[index]->adjust(period);
237      }
238      else
239      {
240         mc68328->gptimer[index]->adjust(attotime::never);
241      }
242   }
243   else
244   {
245      UINT32 frequency = mc68328_get_timer_frequency(device, index);
246
247      if(frequency > 0)
248      {
249         attotime period = attotime::from_hz(frequency) * 0x10000;
250
251         mc68328->gptimer[index]->adjust(period);
252      }
253      else
254      {
255         mc68328->gptimer[index]->adjust(attotime::never);
256      }
257   }
258   if((mc68328->regs.tctl[index] & TCTL_IRQEN) == TCTL_IRQEN_ENABLE)
259   {
260      mc68328_set_interrupt_line(device, (index == 0) ? INT_TIMER1 : INT_TIMER2, 1);
261   }
262}
263
264static TIMER_CALLBACK( mc68328_timer1_hit )
265{
266   device_t *device = machine.device(MC68328_TAG);
267
268   mc68328_timer_compare_event(device, 0);
269}
270
271static TIMER_CALLBACK( mc68328_timer2_hit )
272{
273   device_t *device = machine.device(MC68328_TAG);
274
275   mc68328_timer_compare_event(device, 1);
276}
277
278static TIMER_CALLBACK( mc68328_pwm_transition )
279{
280   device_t *device = machine.device(MC68328_TAG);
281   mc68328_t* mc68328 = mc68328_get_safe_token( device );
282
283   if(mc68328->regs.pwmw >= mc68328->regs.pwmp || mc68328->regs.pwmw == 0 || mc68328->regs.pwmp == 0)
284   {
285      mc68328->pwm->adjust(attotime::never);
286      return;
287   }
288
289   if(((mc68328->regs.pwmc & PWMC_POL) == 0 && (mc68328->regs.pwmc & PWMC_PIN) != 0) ||
290      ((mc68328->regs.pwmc & PWMC_POL) != 0 && (mc68328->regs.pwmc & PWMC_PIN) == 0))
291   {
292      UINT32 frequency = 32768 * 506;
293      UINT32 divisor = 4 << (mc68328->regs.pwmc & PWMC_CLKSEL); // ?? Datasheet says 2 <<, but then we're an octave higher than CoPilot.
294      attotime period;
295
296      frequency /= divisor;
297      period = attotime::from_hz(frequency) * (mc68328->regs.pwmp - mc68328->regs.pwmw);
298
299      mc68328->pwm->adjust(period);
300
301      if(mc68328->regs.pwmc & PWMC_IRQEN)
302      {
303         mc68328_set_interrupt_line(device, INT_PWM, 1);
304      }
305   }
306   else
307   {
308      UINT32 frequency = 32768 * 506;
309      UINT32 divisor = 4 << (mc68328->regs.pwmc & PWMC_CLKSEL); // ?? Datasheet says 2 <<, but then we're an octave higher than CoPilot.
310      attotime period;
311
312      frequency /= divisor;
313      period = attotime::from_hz(frequency) * mc68328->regs.pwmw;
314
315      mc68328->pwm->adjust(period);
316   }
317
318   mc68328->regs.pwmc ^= PWMC_PIN;
319
320   if( !mc68328->out_pwm.isnull() )
321   {
322      mc68328->out_pwm( 0, (mc68328->regs.pwmc & PWMC_PIN) ? 1 : 0 );
323   }
324}
325
326static TIMER_CALLBACK( mc68328_rtc_tick )
327{
328   device_t *device = machine.device(MC68328_TAG);
329   mc68328_t* mc68328 = mc68328_get_safe_token( device );
330
331   if(mc68328->regs.rtcctl & RTCCTL_ENABLE)
332   {
333      UINT32 set_int = 0;
334
335      mc68328->regs.hmsr++;
336
337      if(mc68328->regs.rtcienr & RTCINT_SECOND)
338      {
339         set_int = 1;
340         mc68328->regs.rtcisr |= RTCINT_SECOND;
341      }
342
343      if((mc68328->regs.hmsr & 0x0000003f) == 0x0000003c)
344      {
345         mc68328->regs.hmsr &= 0xffffffc0;
346         mc68328->regs.hmsr += 0x00010000;
347
348         if(mc68328->regs.rtcienr & RTCINT_MINUTE)
349         {
350            set_int = 1;
351            mc68328->regs.rtcisr |= RTCINT_MINUTE;
352         }
353
354         if((mc68328->regs.hmsr & 0x003f0000) == 0x003c0000)
355         {
356            mc68328->regs.hmsr &= 0xffc0ffff;
357            mc68328->regs.hmsr += 0x0100000;
358
359            if((mc68328->regs.hmsr & 0x1f000000) == 0x18000000)
360            {
361               mc68328->regs.hmsr &= 0xe0ffffff;
362
363               if(mc68328->regs.rtcienr & RTCINT_DAY)
364               {
365                  set_int = 1;
366                  mc68328->regs.rtcisr |= RTCINT_DAY;
367               }
368            }
369         }
370
371         if(mc68328->regs.stpwtch != 0x003f)
372         {
373            mc68328->regs.stpwtch--;
374            mc68328->regs.stpwtch &= 0x003f;
375
376            if(mc68328->regs.stpwtch == 0x003f)
377            {
378               if(mc68328->regs.rtcienr & RTCINT_STOPWATCH)
379               {
380                  set_int = 1;
381                  mc68328->regs.rtcisr |= RTCINT_STOPWATCH;
382               }
383            }
384         }
385      }
386
387      if(mc68328->regs.hmsr == mc68328->regs.alarm)
388      {
389         if(mc68328->regs.rtcienr & RTCINT_ALARM)
390         {
391            set_int = 1;
392            mc68328->regs.rtcisr |= RTCINT_STOPWATCH;
393         }
394      }
395
396      if(set_int)
397      {
398         mc68328_set_interrupt_line(device, INT_RTC, 1);
399      }
400      else
401      {
402         mc68328_set_interrupt_line(device, INT_RTC, 0);
403      }
404   }
405}
406
407WRITE16_DEVICE_HANDLER( mc68328_w )
408{
409   mc68328_t* mc68328 = mc68328_get_safe_token( device );
410   UINT32 address = offset << 1;
411   UINT16 temp16[4] = { 0 };
412   UINT32 imr_old = mc68328->regs.imr, imr_diff;
413
414   switch(address)
415   {
416      case 0x000:
417         if( mem_mask & 0x00ff )
418         {
419            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff001) = %02x\n", data & 0x00ff);
420         }
421         else
422         {
423            verboselog(space.machine(), 2, "mc68328_w: SCR = %02x\n", (data >> 8) & 0x00ff);
424         }
425         break;
426
427      case 0x100:
428         verboselog(space.machine(), 2, "mc68328_w: GRPBASEA = %04x\n", data);
429         mc68328->regs.grpbasea = data;
430         break;
431
432      case 0x102:
433         verboselog(space.machine(), 2, "mc68328_w: GRPBASEB = %04x\n", data);
434         mc68328->regs.grpbaseb = data;
435         break;
436
437      case 0x104:
438         verboselog(space.machine(), 2, "mc68328_w: GRPBASEC = %04x\n", data);
439         mc68328->regs.grpbasec = data;
440         break;
441
442      case 0x106:
443         verboselog(space.machine(), 2, "mc68328_w: GRPBASED = %04x\n", data);
444         mc68328->regs.grpbased = data;
445         break;
446
447      case 0x108:
448         verboselog(space.machine(), 2, "mc68328_w: GRPMASKA = %04x\n", data);
449         mc68328->regs.grpmaska = data;
450         break;
451
452      case 0x10a:
453         verboselog(space.machine(), 2, "mc68328_w: GRPMASKB = %04x\n", data);
454         mc68328->regs.grpmaskb = data;
455         break;
456
457      case 0x10c:
458         verboselog(space.machine(), 2, "mc68328_w: GRPMASKC = %04x\n", data);
459         mc68328->regs.grpmaskc = data;
460         break;
461
462      case 0x10e:
463         verboselog(space.machine(), 2, "mc68328_w: GRPMASKD = %04x\n", data);
464         mc68328->regs.grpmaskd = data;
465         break;
466
467      case 0x110:
468         verboselog(space.machine(), 5, "mc68328_w: CSA0(0) = %04x\n", data);
469         mc68328->regs.csa0 &= 0xffff0000 | (~mem_mask);
470         mc68328->regs.csa0 |= data & mem_mask;
471         break;
472
473      case 0x112:
474         verboselog(space.machine(), 5, "mc68328_w: CSA0(16) = %04x\n", data);
475         mc68328->regs.csa0 &= ~(mem_mask << 16);
476         mc68328->regs.csa0 |= (data & mem_mask) << 16;
477         break;
478
479      case 0x114:
480         verboselog(space.machine(), 5, "mc68328_w: CSA1(0) = %04x\n", data);
481         mc68328->regs.csa1 &= 0xffff0000 | (~mem_mask);
482         mc68328->regs.csa1 |= data & mem_mask;
483         break;
484
485      case 0x116:
486         verboselog(space.machine(), 5, "mc68328_w: CSA1(16) = %04x\n", data);
487         mc68328->regs.csa1 &= ~(mem_mask << 16);
488         mc68328->regs.csa1 |= (data & mem_mask) << 16;
489         break;
490
491      case 0x118:
492         verboselog(space.machine(), 5, "mc68328_w: CSA2(0) = %04x\n", data);
493         mc68328->regs.csa2 &= 0xffff0000 | (~mem_mask);
494         mc68328->regs.csa2 |= data & mem_mask;
495         break;
496
497      case 0x11a:
498         verboselog(space.machine(), 5, "mc68328_w: CSA2(16) = %04x\n", data);
499         mc68328->regs.csa2 &= ~(mem_mask << 16);
500         mc68328->regs.csa2 |= (data & mem_mask) << 16;
501         break;
502
503      case 0x11c:
504         verboselog(space.machine(), 5, "mc68328_w: CSA3(0) = %04x\n", data);
505         mc68328->regs.csa3 &= 0xffff0000 | (~mem_mask);
506         mc68328->regs.csa3 |= data & mem_mask;
507         break;
508
509      case 0x11e:
510         verboselog(space.machine(), 5, "mc68328_w: CSA3(16) = %04x\n", data);
511         mc68328->regs.csa3 &= ~(mem_mask << 16);
512         mc68328->regs.csa3 |= (data & mem_mask) << 16;
513         break;
514
515      case 0x120:
516         verboselog(space.machine(), 5, "mc68328_w: CSB0(0) = %04x\n", data);
517         mc68328->regs.csb0 &= 0xffff0000 | (~mem_mask);
518         mc68328->regs.csb0 |= data & mem_mask;
519         break;
520
521      case 0x122:
522         verboselog(space.machine(), 5, "mc68328_w: CSB0(16) = %04x\n", data);
523         mc68328->regs.csb0 &= ~(mem_mask << 16);
524         mc68328->regs.csb0 |= (data & mem_mask) << 16;
525         break;
526
527      case 0x124:
528         verboselog(space.machine(), 5, "mc68328_w: CSB1(0) = %04x\n", data);
529         mc68328->regs.csb1 &= 0xffff0000 | (~mem_mask);
530         mc68328->regs.csb1 |= data & mem_mask;
531         break;
532
533      case 0x126:
534         verboselog(space.machine(), 5, "mc68328_w: CSB1(16) = %04x\n", data);
535         mc68328->regs.csb1 &= ~(mem_mask << 16);
536         mc68328->regs.csb1 |= (data & mem_mask) << 16;
537         break;
538
539      case 0x128:
540         verboselog(space.machine(), 5, "mc68328_w: CSB2(0) = %04x\n", data);
541         mc68328->regs.csb2 &= 0xffff0000 | (~mem_mask);
542         mc68328->regs.csb2 |= data & mem_mask;
543         break;
544
545      case 0x12a:
546         verboselog(space.machine(), 5, "mc68328_w: CSB2(16) = %04x\n", data);
547         mc68328->regs.csb2 &= ~(mem_mask << 16);
548         mc68328->regs.csb2 |= (data & mem_mask) << 16;
549         break;
550
551      case 0x12c:
552         verboselog(space.machine(), 5, "mc68328_w: CSB3(0) = %04x\n", data);
553         mc68328->regs.csb3 &= 0xffff0000 | (~mem_mask);
554         mc68328->regs.csb3 |= data & mem_mask;
555         break;
556
557      case 0x12e:
558         verboselog(space.machine(), 5, "mc68328_w: CSB3(16) = %04x\n", data);
559         mc68328->regs.csb3 &= ~(mem_mask << 16);
560         mc68328->regs.csb3 |= (data & mem_mask) << 16;
561         break;
562
563      case 0x130:
564         verboselog(space.machine(), 5, "mc68328_w: CSC0(0) = %04x\n", data);
565         mc68328->regs.csc0 &= 0xffff0000 | (~mem_mask);
566         mc68328->regs.csc0 |= data & mem_mask;
567         break;
568
569      case 0x132:
570         verboselog(space.machine(), 5, "mc68328_w: CSC0(16) = %04x\n", data);
571         mc68328->regs.csc0 &= ~(mem_mask << 16);
572         mc68328->regs.csc0 |= (data & mem_mask) << 16;
573         break;
574
575      case 0x134:
576         verboselog(space.machine(), 5, "mc68328_w: CSC1(0) = %04x\n", data);
577         mc68328->regs.csc1 &= 0xffff0000 | (~mem_mask);
578         mc68328->regs.csc1 |= data & mem_mask;
579         break;
580
581      case 0x136:
582         verboselog(space.machine(), 5, "mc68328_w: CSC1(16) = %04x\n", data);
583         mc68328->regs.csc1 &= ~(mem_mask << 16);
584         mc68328->regs.csc1 |= (data & mem_mask) << 16;
585         break;
586
587      case 0x138:
588         verboselog(space.machine(), 5, "mc68328_w: CSC2(0) = %04x\n", data);
589         mc68328->regs.csc2 &= 0xffff0000 | (~mem_mask);
590         mc68328->regs.csc2 |= data & mem_mask;
591         break;
592
593      case 0x13a:
594         verboselog(space.machine(), 5, "mc68328_w: CSC2(16) = %04x\n", data);
595         mc68328->regs.csc2 &= ~(mem_mask << 16);
596         mc68328->regs.csc2 |= (data & mem_mask) << 16;
597         break;
598
599      case 0x13c:
600         verboselog(space.machine(), 5, "mc68328_w: CSC3(0) = %04x\n", data);
601         mc68328->regs.csc3 &= 0xffff0000 | (~mem_mask);
602         mc68328->regs.csc3 |= data & mem_mask;
603         break;
604
605      case 0x13e:
606         verboselog(space.machine(), 5, "mc68328_w: CSC3(16) = %04x\n", data);
607         mc68328->regs.csc3 &= ~(mem_mask << 16);
608         mc68328->regs.csc3 |= (data & mem_mask) << 16;
609         break;
610
611      case 0x140:
612         verboselog(space.machine(), 5, "mc68328_w: CSD0(0) = %04x\n", data);
613         mc68328->regs.csd0 &= 0xffff0000 | (~mem_mask);
614         mc68328->regs.csd0 |= data & mem_mask;
615         break;
616
617      case 0x142:
618         verboselog(space.machine(), 5, "mc68328_w: CSD0(16) = %04x\n", data);
619         mc68328->regs.csd0 &= ~(mem_mask << 16);
620         mc68328->regs.csd0 |= (data & mem_mask) << 16;
621         break;
622
623      case 0x144:
624         verboselog(space.machine(), 5, "mc68328_w: CSD1(0) = %04x\n", data);
625         mc68328->regs.csd1 &= 0xffff0000 | (~mem_mask);
626         mc68328->regs.csd1 |= data & mem_mask;
627         break;
628
629      case 0x146:
630         verboselog(space.machine(), 5, "mc68328_w: CSD1(16) = %04x\n", data);
631         mc68328->regs.csd1 &= ~(mem_mask << 16);
632         mc68328->regs.csd1 |= (data & mem_mask) << 16;
633         break;
634
635      case 0x148:
636         verboselog(space.machine(), 5, "mc68328_w: CSD2(0) = %04x\n", data);
637         mc68328->regs.csd2 &= 0xffff0000 | (~mem_mask);
638         mc68328->regs.csd2 |= data & mem_mask;
639         break;
640
641      case 0x14a:
642         verboselog(space.machine(), 5, "mc68328_w: CSD2(16) = %04x\n", data);
643         mc68328->regs.csd2 &= ~(mem_mask << 16);
644         mc68328->regs.csd2 |= (data & mem_mask) << 16;
645         break;
646
647      case 0x14c:
648         verboselog(space.machine(), 5, "mc68328_w: CSD3(0) = %04x\n", data);
649         mc68328->regs.csd3 &= 0xffff0000 | (~mem_mask);
650         mc68328->regs.csd3 |= data & mem_mask;
651         break;
652
653      case 0x14e:
654         verboselog(space.machine(), 5, "mc68328_w: CSD3(16) = %04x\n", data);
655         mc68328->regs.csd3 &= ~(mem_mask << 16);
656         mc68328->regs.csd3 |= (data & mem_mask) << 16;
657         break;
658
659      case 0x200:
660         verboselog(space.machine(), 2, "mc68328_w: PLLCR = %04x\n", data);
661         mc68328->regs.pllcr = data;
662         break;
663
664      case 0x202:
665         verboselog(space.machine(), 2, "mc68328_w: PLLFSR = %04x\n", data);
666         mc68328->regs.pllfsr = data;
667         break;
668
669      case 0x206:
670         if( mem_mask & 0x00ff )
671         {
672            verboselog(space.machine(), 2, "mc68328_w: PCTLR = %02x\n", data & 0x00ff);
673            mc68328->regs.pctlr = data & 0x00ff;
674         }
675         else
676         {
677            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff206) = %02x\n", (data >> 8) & 0x00ff);
678         }
679         break;
680
681      case 0x300:
682         if( mem_mask & 0x00ff )
683         {
684            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff301) = %02x\n", data & 0x00ff);
685         }
686         else
687         {
688            verboselog(space.machine(), 2, "mc68328_w: IVR = %02x\n", (data >> 8) & 0x00ff);
689            mc68328->regs.ivr = (data >> 8) & 0x00ff;
690         }
691         break;
692
693      case 0x302:
694         verboselog(space.machine(), 2, "mc68328_w: ICR = %04x\n", data);
695         mc68328->regs.icr = data;
696         break;
697
698      case 0x304:
699         verboselog(space.machine(), 2, "mc68328_w: IMR(16) = %04x\n", data);
700         mc68328->regs.imr &= ~(mem_mask << 16);
701         mc68328->regs.imr |= (data & mem_mask) << 16;
702         mc68328->regs.isr &= ~((data & mem_mask) << 16);
703
704         imr_diff = imr_old ^ mc68328->regs.imr;
705         mc68328_set_interrupt_line(device, imr_diff, 0);
706         break;
707
708      case 0x306:
709         verboselog(space.machine(), 2, "mc68328_w: IMR(0) = %04x\n", data);
710         mc68328->regs.imr &= 0xffff0000 | (~mem_mask);
711         mc68328->regs.imr |= data & mem_mask;
712         mc68328->regs.isr &= ~(data & mem_mask);
713
714         imr_diff = imr_old ^ mc68328->regs.imr;
715         mc68328_set_interrupt_line(device, imr_diff, 0);
716         break;
717
718      case 0x308:
719      {
720         verboselog(space.machine(), 2, "mc68328_w: IWR(16) = %04x\n", data);
721         mc68328->regs.iwr &= ~(mem_mask << 16);
722         mc68328->regs.iwr |= (data & mem_mask) << 16;
723      }
724      break;
725
726      case 0x30a:
727         verboselog(space.machine(), 2, "mc68328_w: IWR(0) = %04x\n", data);
728         mc68328->regs.iwr &= 0xffff0000 | (~mem_mask);
729         mc68328->regs.iwr |= data & mem_mask;
730         break;
731
732      case 0x30c:
733         verboselog(space.machine(), 2, "mc68328_w: ISR(16) = %04x\n", data);
734         // Clear edge-triggered IRQ1
735         if((mc68328->regs.icr & ICR_ET1) == ICR_ET1 && (data & INT_IRQ1_SHIFT) == INT_IRQ1_SHIFT)
736         {
737            mc68328->regs.isr &= ~INT_IRQ1;
738         }
739
740         // Clear edge-triggered IRQ2
741         if((mc68328->regs.icr & ICR_ET2) == ICR_ET2 && (data & INT_IRQ2_SHIFT) == INT_IRQ2_SHIFT)
742         {
743            mc68328->regs.isr &= ~INT_IRQ2;
744         }
745
746         // Clear edge-triggered IRQ3
747         if((mc68328->regs.icr & ICR_ET3) == ICR_ET3 && (data & INT_IRQ3_SHIFT) == INT_IRQ3_SHIFT)
748         {
749            mc68328->regs.isr &= ~INT_IRQ3;
750         }
751
752         // Clear edge-triggered IRQ6
753         if((mc68328->regs.icr & ICR_ET6) == ICR_ET6 && (data & INT_IRQ6_SHIFT) == INT_IRQ6_SHIFT)
754         {
755            mc68328->regs.isr &= ~INT_IRQ6;
756         }
757
758         // Clear edge-triggered IRQ7
759         if((data & INT_IRQ7_SHIFT) == INT_IRQ7_SHIFT)
760         {
761            mc68328->regs.isr &= ~INT_IRQ7;
762         }
763         break;
764
765      case 0x30e:
766         verboselog(space.machine(), 2, "mc68328_w: ISR(0) = %04x (Ignored)\n", data);
767         break;
768
769      case 0x310:
770         verboselog(space.machine(), 2, "mc68328_w: IPR(16) = %04x (Ignored)\n");
771         break;
772
773      case 0x312:
774         verboselog(space.machine(), 2, "mc68328_w: IPR(0) = %04x (Ignored)\n");
775         break;
776
777      case 0x400:
778         if( mem_mask & 0x00ff )
779         {
780            verboselog(space.machine(), 2, "mc68328_w: PADATA = %02x\n", data & 0x00ff);
781            mc68328->regs.padata = data & 0x00ff;
782            if(!mc68328->out_port_a.isnull())
783            {
784               mc68328->out_port_a( 0, data & 0x00ff );
785            }
786         }
787         else
788         {
789            verboselog(space.machine(), 2, "mc68328_w: PADIR = %02x\n", (data >> 8) & 0x00ff);
790            mc68328->regs.padir = (data >> 8) & 0x00ff;
791         }
792         break;
793
794      case 0x402:
795         if( mem_mask & 0x00ff )
796         {
797            verboselog(space.machine(), 2, "mc68328_w: PASEL = %02x\n", data & 0x00ff);
798            mc68328->regs.pasel = data & 0x00ff;
799         }
800         else
801         {
802            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff402) = %02x\n", (data >> 8) & 0x00ff);
803         }
804         break;
805
806      case 0x408:
807         if( mem_mask & 0x00ff )
808         {
809            verboselog(space.machine(), 2, "mc68328_w: PBDATA = %02x\n", data & 0x00ff);
810            mc68328->regs.pbdata = data & 0x00ff;
811            if(!mc68328->out_port_b.isnull())
812            {
813               mc68328->out_port_b( 0, data & 0x00ff );
814            }
815         }
816         else
817         {
818            verboselog(space.machine(), 2, "mc68328_w: PBDIR = %02x\n", (data >> 8) & 0x00ff);
819            mc68328->regs.pbdir = (data >> 8) & 0x00ff;
820         }
821         break;
822
823      case 0x40a:
824         if( mem_mask & 0x00ff )
825         {
826            verboselog(space.machine(), 2, "mc68328_w: PBSEL = %02x\n", data & 0x00ff);
827            mc68328->regs.pbsel = data & 0x00ff;
828         }
829         else
830         {
831            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff40a) = %02x\n", (data >> 8) & 0x00ff);
832         }
833         break;
834
835      case 0x410:
836         if( mem_mask & 0x00ff )
837         {
838            verboselog(space.machine(), 2, "mc68328_w: PCDATA = %02x\n", data & 0x00ff);
839            mc68328->regs.pcdata = data & 0x00ff;
840            if(!mc68328->out_port_c.isnull())
841            {
842               mc68328->out_port_c( 0, data & 0x00ff );
843            }
844         }
845         else
846         {
847            verboselog(space.machine(), 2, "mc68328_w: PCDIR = %02x\n", (data >> 8) & 0x00ff);
848            mc68328->regs.pcdir = (data >> 8) & 0x00ff;
849         }
850         break;
851
852      case 0x412:
853         if( mem_mask & 0x00ff )
854         {
855            verboselog(space.machine(), 2, "mc68328_w: PCSEL = %02x\n", data & 0x00ff);
856            mc68328->regs.pcsel = data & 0x00ff;
857         }
858         else
859         {
860            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff412) = %02x\n", (data >> 8) & 0x00ff);
861         }
862         break;
863
864      case 0x418:
865         if( mem_mask & 0x00ff )
866         {
867            verboselog(space.machine(), 2, "mc68328_w: PDDATA = %02x\n", data & 0x00ff);
868
869            mc68328->regs.pddataedge &= ~(data & 0x00ff);
870            mc68328_poll_port_d_interrupts(device);
871         }
872         else
873         {
874            verboselog(space.machine(), 2, "mc68328_w: PDDIR = %02x\n", (data >> 8) & 0x00ff);
875            mc68328->regs.pddir = (data >> 8) & 0x00ff;
876         }
877         break;
878
879      case 0x41a:
880         if( mem_mask & 0x00ff )
881         {
882            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff41b) = %02x\n", data & 0x00ff);
883         }
884         else
885         {
886            verboselog(space.machine(), 2, "mc68328_w: PDPUEN = %02x\n", (data >> 8) & 0x00ff);
887            mc68328->regs.pdpuen = (data >> 8) & 0x00ff;
888         }
889         break;
890
891      case 0x41c:
892         if( mem_mask & 0x00ff )
893         {
894            verboselog(space.machine(), 2, "mc68328_w: PDIRQEN = %02x\n", data & 0x00ff);
895            mc68328->regs.pdirqen = data & 0x00ff;
896
897            mc68328_poll_port_d_interrupts(device);
898         }
899         else
900         {
901            verboselog(space.machine(), 2, "mc68328_w: PDPOL = %02x\n", (data >> 8) & 0x00ff);
902            mc68328->regs.pdpol = (data >> 8) & 0x00ff;
903         }
904         break;
905
906      case 0x41e:
907         if( mem_mask & 0x00ff )
908         {
909            verboselog(space.machine(), 2, "mc68328_w: PDIRQEDGE = %02x\n", data & 0x00ff);
910            mc68328->regs.pdirqedge = data & 0x00ff;
911         }
912         else
913         {
914            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff41e) = %02x\n", (data >> 8) & 0x00ff);
915         }
916         break;
917
918      case 0x420:
919         if( mem_mask & 0x00ff )
920         {
921            verboselog(space.machine(), 2, "mc68328_w: PEDATA = %02x\n", data & 0x00ff);
922            mc68328->regs.pedata = data & 0x00ff;
923            if(!mc68328->out_port_e.isnull())
924            {
925               mc68328->out_port_e( 0, data & 0x00ff );
926            }
927         }
928         else
929         {
930            verboselog(space.machine(), 2, "mc68328_w: PEDIR = %02x\n", (data >> 8) & 0x00ff);
931            mc68328->regs.pedir = (data >> 8) & 0x00ff;
932         }
933         break;
934
935      case 0x422:
936         if( mem_mask & 0x00ff )
937         {
938            verboselog(space.machine(), 2, "mc68328_w: PESEL = %02x\n", data & 0x00ff);
939            mc68328->regs.pesel = data & 0x00ff;
940         }
941         else
942         {
943            verboselog(space.machine(), 2, "mc68328_w: PEPUEN = %02x\n", (data >> 8) & 0x00ff);
944            mc68328->regs.pepuen = (data >> 8) & 0x00ff;
945            mc68328->regs.pedata |= mc68328->regs.pepuen;
946         }
947         break;
948
949      case 0x428:
950         if( mem_mask & 0x00ff )
951         {
952            verboselog(space.machine(), 2, "mc68328_w: PFDATA = %02x\n", data & 0x00ff);
953            mc68328->regs.pfdata = data & 0x00ff;
954            if(!mc68328->out_port_f.isnull())
955            {
956               mc68328->out_port_f( 0, data & 0x00ff );
957            }
958         }
959         else
960         {
961            verboselog(space.machine(), 2, "mc68328_w: PFDIR = %02x\n", (data >> 8) & 0x00ff);
962            mc68328->regs.pfdir = (data >> 8) & 0x00ff;
963         }
964         break;
965
966      case 0x42a:
967         if( mem_mask & 0x00ff )
968         {
969            verboselog(space.machine(), 2, "mc68328_w: PFSEL = %02x\n", data & 0x00ff);
970            mc68328->regs.pfsel = data & 0x00ff;
971         }
972         else
973         {
974            verboselog(space.machine(), 2, "mc68328_w: PFPUEN = %02x\n", (data >> 8) & 0x00ff);
975            mc68328->regs.pfpuen = (data >> 8) & 0x00ff;
976         }
977         break;
978
979      case 0x430:
980         if( mem_mask & 0x00ff )
981         {
982            verboselog(space.machine(), 2, "mc68328_w: PGDATA = %02x\n", data & 0x00ff);
983            mc68328->regs.pgdata = data & 0x00ff;
984            if(!mc68328->out_port_g.isnull())
985            {
986               mc68328->out_port_g( 0, data & 0x00ff );
987            }
988         }
989         else
990         {
991            verboselog(space.machine(), 2, "mc68328_w: PGDIR = %02x\n", (data >> 8) & 0x00ff);
992            mc68328->regs.pgdir = (data >> 8) & 0x00ff;
993         }
994         break;
995
996      case 0x432:
997         if( mem_mask & 0x00ff )
998         {
999            verboselog(space.machine(), 2, "mc68328_w: PGSEL = %02x\n", data & 0x00ff);
1000            mc68328->regs.pgsel = data & 0x00ff;
1001         }
1002         else
1003         {
1004            verboselog(space.machine(), 2, "mc68328_w: PGPUEN = %02x\n", (data >> 8) & 0x00ff);
1005            mc68328->regs.pgpuen = (data >> 8) & 0x00ff;
1006         }
1007         break;
1008
1009      case 0x438:
1010         if( mem_mask & 0x00ff )
1011         {
1012            verboselog(space.machine(), 2, "mc68328_w: PJDATA = %02x\n", data & 0x00ff);
1013            mc68328->regs.pjdata = data & 0x00ff;
1014            if(!mc68328->out_port_j.isnull())
1015            {
1016               mc68328->out_port_j( 0, data & 0x00ff );
1017            }
1018         }
1019         else
1020         {
1021            verboselog(space.machine(), 2, "mc68328_w: PJDIR = %02x\n", (data >> 8) & 0x00ff);
1022            mc68328->regs.pjdir = (data >> 8) & 0x00ff;
1023         }
1024         break;
1025
1026      case 0x43a:
1027         if( mem_mask & 0x00ff )
1028         {
1029            verboselog(space.machine(), 2, "mc68328_w: PJSEL = %02x\n", data & 0x00ff);
1030            mc68328->regs.pjsel = data & 0x00ff;
1031         }
1032         else
1033         {
1034            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfff43a) = %02x\n", (data >> 8) & 0x00ff);
1035         }
1036         break;
1037
1038      case 0x440:
1039         if( mem_mask & 0x00ff )
1040         {
1041            verboselog(space.machine(), 2, "mc68328_w: PKDATA = %02x\n", data & 0x00ff);
1042            mc68328->regs.pkdata = data & 0x00ff;
1043            if(!mc68328->out_port_k.isnull())
1044            {
1045               mc68328->out_port_k( 0, data & 0x00ff );
1046            }
1047         }
1048         else
1049         {
1050            verboselog(space.machine(), 2, "mc68328_w: PKDIR = %02x\n", (data >> 8) & 0x00ff);
1051            mc68328->regs.pkdir = (data >> 8) & 0x00ff;
1052         }
1053         break;
1054
1055      case 0x442:
1056         if( mem_mask & 0x00ff )
1057         {
1058            verboselog(space.machine(), 2, "mc68328_w: PKSEL = %02x\n", data & 0x00ff);
1059            mc68328->regs.pksel = data & 0x00ff;
1060         }
1061         else
1062         {
1063            verboselog(space.machine(), 2, "mc68328_w: PKPUEN = %02x\n", (data >> 8) & 0x00ff);
1064            mc68328->regs.pgpuen = (data >> 8) & 0x00ff;
1065         }
1066         break;
1067
1068      case 0x448:
1069         if( mem_mask & 0x00ff )
1070         {
1071            verboselog(space.machine(), 2, "mc68328_w: PMDATA = %02x\n", data & 0x00ff);
1072            mc68328->regs.pmdata = data & 0x00ff;
1073            if(!mc68328->out_port_m.isnull())
1074            {
1075               mc68328->out_port_m( 0, data & 0x00ff );
1076            }
1077         }
1078         else
1079         {
1080            verboselog(space.machine(), 2, "mc68328_w: PMDIR = %02x\n", (data >> 8) & 0x00ff);
1081            mc68328->regs.pmdir = (data >> 8) & 0x00ff;
1082         }
1083         break;
1084
1085      case 0x44a:
1086         if( mem_mask & 0x00ff )
1087         {
1088            verboselog(space.machine(), 2, "mc68328_w: PMSEL = %02x\n", data & 0x00ff);
1089            mc68328->regs.pmsel = data & 0x00ff;
1090         }
1091         else
1092         {
1093            verboselog(space.machine(), 2, "mc68328_w: PMPUEN = %02x\n", (data >> 8) & 0x00ff);
1094            mc68328->regs.pmpuen = (data >> 8) & 0x00ff;
1095         }
1096         break;
1097
1098      case 0x500:
1099         verboselog(space.machine(), 2, "mc68328_w: PWMC = %04x\n", data);
1100
1101         mc68328->regs.pwmc = data;
1102
1103         if(mc68328->regs.pwmc & PWMC_PWMIRQ)
1104         {
1105            mc68328_set_interrupt_line(device, INT_PWM, 1);
1106         }
1107
1108         mc68328->regs.pwmc &= ~PWMC_LOAD;
1109
1110         if((mc68328->regs.pwmc & PWMC_PWMEN) != 0 && mc68328->regs.pwmw != 0 && mc68328->regs.pwmp != 0)
1111         {
1112            UINT32 frequency = 32768 * 506;
1113            UINT32 divisor = 4 << (mc68328->regs.pwmc & PWMC_CLKSEL); // ?? Datasheet says 2 <<, but then we're an octave higher than CoPilot.
1114            attotime period;
1115            frequency /= divisor;
1116            period = attotime::from_hz(frequency) * mc68328->regs.pwmw;
1117            mc68328->pwm->adjust(period);
1118            if(mc68328->regs.pwmc & PWMC_IRQEN)
1119            {
1120               mc68328_set_interrupt_line(device, INT_PWM, 1);
1121            }
1122            mc68328->regs.pwmc ^= PWMC_PIN;
1123         }
1124         else
1125         {
1126            mc68328->pwm->adjust(attotime::never);
1127         }
1128         break;
1129
1130      case 0x502:
1131         verboselog(space.machine(), 2, "mc68328_w: PWMP = %04x\n", data);
1132         mc68328->regs.pwmp = data;
1133         break;
1134
1135      case 0x504:
1136         verboselog(space.machine(), 2, "mc68328_w: PWMW = %04x\n", data);
1137         mc68328->regs.pwmw = data;
1138         break;
1139
1140      case 0x506:
1141         verboselog(space.machine(), 2, "mc68328_w: PWMCNT = %04x\n", data);
1142         mc68328->regs.pwmcnt = 0;
1143         break;
1144
1145      case 0x600:
1146         verboselog(space.machine(), 2, "mc68328_w: TCTL1 = %04x\n", data);
1147         temp16[0] = mc68328->regs.tctl[0];
1148         mc68328->regs.tctl[0] = data;
1149         if((temp16[0] & TCTL_TEN) == (mc68328->regs.tctl[0] & TCTL_TEN))
1150         {
1151            mc68328_maybe_start_timer(device, 0, 0);
1152         }
1153         else if((temp16[0] & TCTL_TEN) != TCTL_TEN_ENABLE && (mc68328->regs.tctl[0] & TCTL_TEN) == TCTL_TEN_ENABLE)
1154         {
1155            mc68328_maybe_start_timer(device, 0, 1);
1156         }
1157         break;
1158
1159      case 0x602:
1160         verboselog(space.machine(), 2, "mc68328_w: TPRER1 = %04x\n", data);
1161         mc68328->regs.tprer[0] = data;
1162         mc68328_maybe_start_timer(device, 0, 0);
1163         break;
1164
1165      case 0x604:
1166         verboselog(space.machine(), 2, "mc68328_w: TCMP1 = %04x\n", data);
1167         mc68328->regs.tcmp[0] = data;
1168         mc68328_maybe_start_timer(device, 0, 0);
1169         break;
1170
1171      case 0x606:
1172         verboselog(space.machine(), 2, "mc68328_w: TCR1 = %04x (Ignored)\n", data);
1173         break;
1174
1175      case 0x608:
1176         verboselog(space.machine(), 2, "mc68328_w: TCN1 = %04x (Ignored)\n", data);
1177         break;
1178
1179      case 0x60a:
1180         verboselog(space.machine(), 5, "mc68328_w: TSTAT1 = %04x\n", data);
1181         mc68328->regs.tstat[0] &= ~mc68328->regs.tclear[0];
1182         if(!(mc68328->regs.tstat[0] & TSTAT_COMP))
1183         {
1184            mc68328_set_interrupt_line(device, INT_TIMER1, 0);
1185         }
1186         break;
1187
1188      case 0x60c:
1189         verboselog(space.machine(), 2, "mc68328_w: TCTL2 = %04x\n", data);
1190         temp16[0] = mc68328->regs.tctl[1];
1191         mc68328->regs.tctl[1] = data;
1192         if((temp16[0] & TCTL_TEN) == (mc68328->regs.tctl[1] & TCTL_TEN))
1193         {
1194            mc68328_maybe_start_timer(device, 1, 0);
1195         }
1196         else if((temp16[0] & TCTL_TEN) != TCTL_TEN_ENABLE && (mc68328->regs.tctl[1] & TCTL_TEN) == TCTL_TEN_ENABLE)
1197         {
1198            mc68328_maybe_start_timer(device, 1, 1);
1199         }
1200         break;
1201
1202      case 0x60e:
1203         verboselog(space.machine(), 2, "mc68328_w: TPRER2 = %04x\n", data);
1204         mc68328->regs.tprer[1] = data;
1205         mc68328_maybe_start_timer(device, 1, 0);
1206         break;
1207
1208      case 0x610:
1209         verboselog(space.machine(), 2, "mc68328_w: TCMP2 = %04x\n", data);
1210         mc68328->regs.tcmp[1] = data;
1211         mc68328_maybe_start_timer(device, 1, 0);
1212         break;
1213
1214      case 0x612:
1215         verboselog(space.machine(), 2, "mc68328_w: TCR2 = %04x (Ignored)\n", data);
1216         break;
1217
1218      case 0x614:
1219         verboselog(space.machine(), 2, "mc68328_w: TCN2 = %04x (Ignored)\n", data);
1220         break;
1221
1222      case 0x616:
1223         verboselog(space.machine(), 2, "mc68328_w: TSTAT2 = %04x\n", data);
1224         mc68328->regs.tstat[1] &= ~mc68328->regs.tclear[1];
1225         if(!(mc68328->regs.tstat[1] & TSTAT_COMP))
1226         {
1227            mc68328_set_interrupt_line(device, INT_TIMER2, 0);
1228         }
1229         break;
1230
1231      case 0x618:
1232         verboselog(space.machine(), 2, "mc68328_w: WCTLR = %04x\n", data);
1233         mc68328->regs.wctlr = data;
1234         break;
1235
1236      case 0x61a:
1237         verboselog(space.machine(), 2, "mc68328_w: WCMPR = %04x\n", data);
1238         mc68328->regs.wcmpr = data;
1239         break;
1240
1241      case 0x61c:
1242         verboselog(space.machine(), 2, "mc68328_w: WCN = %04x (Ignored)\n", data);
1243         break;
1244
1245      case 0x700:
1246         verboselog(space.machine(), 2, "mc68328_w: SPISR = %04x\n", data);
1247         mc68328->regs.spisr = data;
1248         break;
1249
1250      case 0x800:
1251         verboselog(space.machine(), 2, "mc68328_w: SPIMDATA = %04x\n", data);
1252         if(!mc68328->out_spim.isnull())
1253         {
1254            mc68328->out_spim( 0, data, 0xffff );
1255         }
1256         else
1257         {
1258            mc68328->regs.spimdata = data;
1259         }
1260         break;
1261
1262      case 0x802:
1263         verboselog(space.machine(), 2, "mc68328_w: SPIMCONT = %04x\n", data);
1264         verboselog(space.machine(), 3, "           Count = %d\n", data & SPIM_CLOCK_COUNT);
1265         verboselog(space.machine(), 3, "           Polarity = %s\n", (data & SPIM_POL) ? "Inverted" : "Active-high");
1266         verboselog(space.machine(), 3, "           Phase = %s\n", (data & SPIM_PHA) ? "Opposite" : "Normal");
1267         verboselog(space.machine(), 3, "           IRQ Enable = %s\n", (data & SPIM_IRQEN) ? "Enable" : "Disable");
1268         verboselog(space.machine(), 3, "           IRQ Pending = %s\n", (data & SPIM_SPIMIRQ) ? "Yes" : "No");
1269         verboselog(space.machine(), 3, "           Exchange = %s\n", (data & SPIM_XCH) ? "Initiate" : "Idle");
1270         verboselog(space.machine(), 3, "           SPIM Enable = %s\n", (data & SPIM_SPMEN) ? "Enable" : "Disable");
1271         verboselog(space.machine(), 3, "           Data Rate = Divide By %d\n", 1 << ((((data & SPIM_RATE) >> 13) & 0x0007) + 2) );
1272         mc68328->regs.spimcont = data;
1273         // $$HACK$$ We should probably emulate the ADS7843 A/D device properly.
1274         if(data & SPIM_XCH)
1275         {
1276            mc68328->regs.spimcont &= ~SPIM_XCH;
1277            if(mc68328->iface->spim_xch_trigger)
1278            {
1279               (mc68328->iface->spim_xch_trigger)( device );
1280            }
1281            if(data & SPIM_IRQEN)
1282            {
1283               mc68328->regs.spimcont |= SPIM_SPIMIRQ;
1284               verboselog(space.machine(), 3, "Triggering SPIM Interrupt\n" );
1285               mc68328_set_interrupt_line(device, INT_SPIM, 1);
1286            }
1287         }
1288         if(!(data & SPIM_IRQEN))
1289         {
1290            mc68328_set_interrupt_line(device, INT_SPIM, 0);
1291         }
1292         break;
1293
1294      case 0x900:
1295         verboselog(space.machine(), 2, "mc68328_w: USTCNT = %04x\n", data);
1296         mc68328->regs.ustcnt = data;
1297         break;
1298
1299      case 0x902:
1300         verboselog(space.machine(), 2, "mc68328_w: UBAUD = %04x\n", data);
1301         mc68328->regs.ubaud = data;
1302         break;
1303
1304      case 0x904:
1305         verboselog(space.machine(), 2, "mc68328_w: URX = %04x\n", data);
1306         break;
1307
1308      case 0x906:
1309         verboselog(space.machine(), 2, "mc68328_w: UTX = %04x\n", data);
1310         break;
1311
1312      case 0x908:
1313         verboselog(space.machine(), 2, "mc68328_w: UMISC = %04x\n", data);
1314         mc68328->regs.umisc = data;
1315         break;
1316
1317      case 0xa00:
1318         verboselog(space.machine(), 2, "mc68328_w: LSSA(16) = %04x\n", data);
1319         mc68328->regs.lssa &= ~(mem_mask << 16);
1320         mc68328->regs.lssa |= (data & mem_mask) << 16;
1321         verboselog(space.machine(), 3, "              Address: %08x\n", mc68328->regs.lssa);
1322         break;
1323
1324      case 0xa02:
1325         verboselog(space.machine(), 2, "mc68328_w: LSSA(0) = %04x\n", data);
1326         mc68328->regs.lssa &= 0xffff0000 | (~mem_mask);
1327         mc68328->regs.lssa |= data & mem_mask;
1328         verboselog(space.machine(), 3, "              Address: %08x\n", mc68328->regs.lssa);
1329         break;
1330
1331      case 0xa04:
1332         if( mem_mask & 0x00ff )
1333         {
1334            verboselog(space.machine(), 2, "mc68328_w: LVPW = %02x\n", data & 0x00ff);
1335            mc68328->regs.lvpw = data & 0x00ff;
1336            verboselog(space.machine(), 3, "              Page Width: %d or %d\n", (mc68328->regs.lvpw + 1) * ((mc68328->regs.lpicf & 0x01) ? 8 : 16));
1337         }
1338         else
1339         {
1340            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa04) = %02x\n", (data >> 8) & 0x00ff);
1341         }
1342         break;
1343
1344      case 0xa08:
1345         verboselog(space.machine(), 2, "mc68328_w: LXMAX = %04x\n", data);
1346         mc68328->regs.lxmax = data;
1347         verboselog(space.machine(), 3, "              Width: %d\n", (data & 0x03ff) + 1);
1348         break;
1349
1350      case 0xa0a:
1351         verboselog(space.machine(), 2, "mc68328_w: LYMAX = %04x\n", data);
1352         mc68328->regs.lymax = data;
1353         verboselog(space.machine(), 3, "              Height: %d\n", (data & 0x03ff) + 1);
1354         break;
1355
1356      case 0xa18:
1357         verboselog(space.machine(), 2, "mc68328_w: LCXP = %04x\n", data);
1358         mc68328->regs.lcxp = data;
1359         verboselog(space.machine(), 3, "              X Position: %d\n", data & 0x03ff);
1360         switch(mc68328->regs.lcxp >> 14)
1361         {
1362            case 0:
1363               verboselog(space.machine(), 3, "              Cursor Control: Transparent\n");
1364               break;
1365
1366            case 1:
1367               verboselog(space.machine(), 3, "              Cursor Control: Black\n");
1368               break;
1369
1370            case 2:
1371               verboselog(space.machine(), 3, "              Cursor Control: Reverse\n");
1372               break;
1373
1374            case 3:
1375               verboselog(space.machine(), 3, "              Cursor Control: Invalid\n");
1376               break;
1377         }
1378         break;
1379
1380      case 0xa1a:
1381         verboselog(space.machine(), 2, "mc68328_w: LCYP = %04x\n", data);
1382         mc68328->regs.lcyp = data;
1383         verboselog(space.machine(), 3, "              Y Position: %d\n", data & 0x01ff);
1384         break;
1385
1386      case 0xa1c:
1387         verboselog(space.machine(), 2, "mc68328_w: LCWCH = %04x\n", data);
1388         mc68328->regs.lcwch = data;
1389         verboselog(space.machine(), 3, "              Width:  %d\n", (data >> 8) & 0x1f);
1390         verboselog(space.machine(), 3, "              Height: %d\n", data & 0x1f);
1391         break;
1392
1393      case 0xa1e:
1394         if( mem_mask & 0x00ff )
1395         {
1396            verboselog(space.machine(), 2, "mc68328_w: LBLKC = %02x\n", data & 0x00ff);
1397            mc68328->regs.lblkc = data & 0x00ff;
1398            verboselog(space.machine(), 3, "              Blink Enable:  %d\n", mc68328->regs.lblkc >> 7);
1399            verboselog(space.machine(), 3, "              Blink Divisor: %d\n", mc68328->regs.lblkc & 0x7f);
1400         }
1401         else
1402         {
1403            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa1e) = %02x\n", (data >> 8) & 0x00ff);
1404         }
1405         break;
1406
1407      case 0xa20:
1408         if( mem_mask & 0x00ff )
1409         {
1410            verboselog(space.machine(), 2, "mc68328_w: LPOLCF = %02x\n", data & 0x00ff);
1411            mc68328->regs.lpolcf = data & 0x00ff;
1412            verboselog(space.machine(), 3, "              LCD Shift Clock Polarity: %s\n", (mc68328->regs.lpicf & 0x08) ? "Active positive edge of LCLK" : "Active negative edge of LCLK");
1413            verboselog(space.machine(), 3, "              First-line marker polarity: %s\n", (mc68328->regs.lpicf & 0x04) ? "Active Low" : "Active High");
1414            verboselog(space.machine(), 3, "              Line-pulse polarity: %s\n", (mc68328->regs.lpicf & 0x02) ? "Active Low" : "Active High");
1415            verboselog(space.machine(), 3, "              Pixel polarity: %s\n", (mc68328->regs.lpicf & 0x01) ? "Active Low" : "Active High");
1416         }
1417         else
1418         {
1419            verboselog(space.machine(), 2, "mc68328_w: LPICF = %02x\n", (data >> 8) & 0x00ff);
1420            mc68328->regs.lpicf = (data >> 8) & 0x00ff;
1421            switch((mc68328->regs.lpicf >> 1) & 0x03)
1422            {
1423               case 0:
1424                  verboselog(space.machine(), 3, "              Bus Size: 1-bit\n");
1425                  break;
1426
1427               case 1:
1428                  verboselog(space.machine(), 3, "              Bus Size: 2-bit\n");
1429                  break;
1430
1431               case 2:
1432                  verboselog(space.machine(), 3, "              Bus Size: 4-bit\n");
1433                  break;
1434
1435               case 3:
1436                  verboselog(space.machine(), 3, "              Bus Size: unused\n");
1437                  break;
1438            }
1439            verboselog(space.machine(), 3, "              Gray scale enable: %d\n", mc68328->regs.lpicf & 0x01);
1440         }
1441         break;
1442
1443      case 0xa22:
1444         if( mem_mask & 0x00ff )
1445         {
1446            verboselog(space.machine(), 2, "mc68328_w: LACDRC = %02x\n", data & 0x00ff);
1447            mc68328->regs.lacdrc = data & 0x00ff;
1448         }
1449         else
1450         {
1451            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa22) = %02x\n", (data >> 8) & 0x00ff);
1452         }
1453         break;
1454
1455      case 0xa24:
1456         if( mem_mask & 0x00ff )
1457         {
1458            verboselog(space.machine(), 2, "mc68328_w: LPXCD = %02x\n", data & 0x00ff);
1459            mc68328->regs.lpxcd = data & 0x00ff;
1460            verboselog(space.machine(), 3, "              Clock Divisor: %d\n", mc68328->regs.lpxcd + 1);
1461         }
1462         else
1463         {
1464            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa24) = %02x\n", (data >> 8) & 0x00ff);
1465         }
1466         break;
1467
1468      case 0xa26:
1469         if( mem_mask & 0x00ff )
1470         {
1471            verboselog(space.machine(), 2, "mc68328_w: LCKCON = %02x\n", data & 0x00ff);
1472            mc68328->regs.lckcon = data & 0x00ff;
1473            verboselog(space.machine(), 3, "              LCDC Enable: %d\n", (mc68328->regs.lckcon >> 7) & 0x01);
1474            verboselog(space.machine(), 3, "              DMA Burst Length: %d\n", ((mc68328->regs.lckcon >> 6) & 0x01) ? 16 : 8);
1475            verboselog(space.machine(), 3, "              DMA Bursting Clock Control: %d\n", ((mc68328->regs.lckcon >> 4) & 0x03) + 1);
1476            verboselog(space.machine(), 3, "              Bus Width: %d\n", ((mc68328->regs.lckcon >> 1) & 0x01) ? 8 : 16);
1477            verboselog(space.machine(), 3, "              Pixel Clock Divider Source: %s\n", (mc68328->regs.lckcon & 0x01) ? "PIX" : "SYS");
1478         }
1479         else
1480         {
1481            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa26) = %02x\n", (data >> 8) & 0x00ff);
1482         }
1483         break;
1484
1485      case 0xa28:
1486         if( mem_mask & 0x00ff )
1487         {
1488            verboselog(space.machine(), 2, "mc68328_w: LLBAR = %02x\n", data & 0x00ff);
1489            mc68328->regs.llbar = data & 0x00ff;
1490            verboselog(space.machine(), 3, "              Address: %d\n", (mc68328->regs.llbar & 0x7f) * ((mc68328->regs.lpicf & 0x01) ? 8 : 16));
1491         }
1492         else
1493         {
1494            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa28) = %02x\n", (data >> 8) & 0x00ff);
1495         }
1496         break;
1497
1498      case 0xa2a:
1499         if( mem_mask & 0x00ff )
1500         {
1501            verboselog(space.machine(), 2, "mc68328_w: LOTCR = %02x\n", data & 0x00ff);
1502         }
1503         else
1504         {
1505            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa2a) = %02x\n", (data >> 8) & 0x00ff);
1506         }
1507         break;
1508
1509      case 0xa2c:
1510         if( mem_mask & 0x00ff )
1511         {
1512            verboselog(space.machine(), 2, "mc68328_w: LPOSR = %02x\n", data & 0x00ff);
1513            mc68328->regs.lposr = data & 0x00ff;
1514            verboselog(space.machine(), 3, "              Byte Offset: %d\n", (mc68328->regs.lposr >> 3) & 0x01);
1515            verboselog(space.machine(), 3, "              Pixel Offset: %d\n", mc68328->regs.lposr & 0x07);
1516         }
1517         else
1518         {
1519            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa2c) = %02x\n", (data >> 8) & 0x00ff);
1520         }
1521         break;
1522
1523      case 0xa30:
1524         if( mem_mask & 0x00ff )
1525         {
1526            verboselog(space.machine(), 2, "mc68328_w: LFRCM = %02x\n", data & 0x00ff);
1527            mc68328->regs.lfrcm = data & 0x00ff;
1528            verboselog(space.machine(), 3, "              X Modulation: %d\n", (mc68328->regs.lfrcm >> 4) & 0x0f);
1529            verboselog(space.machine(), 3, "              Y Modulation: %d\n", mc68328->regs.lfrcm & 0x0f);
1530         }
1531         else
1532         {
1533            verboselog(space.machine(), 2, "mc68328_w: Unknown address (0xfffa30) = %02x\n", (data >> 8) & 0x00ff);
1534         }
1535         break;
1536
1537      case 0xa32:
1538         verboselog(space.machine(), 2, "mc68328_w: LGPMR = %04x\n", data);
1539         mc68328->regs.lgpmr = data;
1540         verboselog(space.machine(), 3, "              Palette 0: %d\n", (mc68328->regs.lgpmr >>  8) & 0x07);
1541         verboselog(space.machine(), 3, "              Palette 1: %d\n", (mc68328->regs.lgpmr >> 12) & 0x07);
1542         verboselog(space.machine(), 3, "              Palette 2: %d\n", (mc68328->regs.lgpmr >>  0) & 0x07);
1543         verboselog(space.machine(), 3, "              Palette 3: %d\n", (mc68328->regs.lgpmr >>  4) & 0x07);
1544         break;
1545
1546      case 0xb00:
1547         verboselog(space.machine(), 2, "mc68328_w: HMSR(0) = %04x\n", data);
1548         mc68328->regs.hmsr &= ~(mem_mask << 16);
1549         mc68328->regs.hmsr |= (data & mem_mask) << 16;
1550         mc68328->regs.hmsr &= 0x1f3f003f;
1551         break;
1552
1553      case 0xb02:
1554         verboselog(space.machine(), 2, "mc68328_w: HMSR(16) = %04x\n", data);
1555         mc68328->regs.hmsr &= 0xffff0000 | (~mem_mask);
1556         mc68328->regs.hmsr |= data & mem_mask;
1557         mc68328->regs.hmsr &= 0x1f3f003f;
1558         break;
1559
1560      case 0xb04:
1561         verboselog(space.machine(), 2, "mc68328_w: ALARM(0) = %04x\n", data);
1562         mc68328->regs.alarm &= ~(mem_mask << 16);
1563         mc68328->regs.alarm |= (data & mem_mask) << 16;
1564         mc68328->regs.alarm &= 0x1f3f003f;
1565         break;
1566
1567      case 0xb06:
1568         verboselog(space.machine(), 2, "mc68328_w: ALARM(16) = %04x\n", data);
1569         mc68328->regs.alarm &= 0xffff0000 | (~mem_mask);
1570         mc68328->regs.alarm |= data & mem_mask;
1571         mc68328->regs.alarm &= 0x1f3f003f;
1572         break;
1573
1574      case 0xb0c:
1575         verboselog(space.machine(), 2, "mc68328_w: RTCCTL = %04x\n", data);
1576         mc68328->regs.rtcctl = data & 0x00a0;
1577         break;
1578
1579      case 0xb0e:
1580         verboselog(space.machine(), 2, "mc68328_w: RTCISR = %04x\n", data);
1581         mc68328->regs.rtcisr &= ~data;
1582         if(mc68328->regs.rtcisr == 0)
1583         {
1584            mc68328_set_interrupt_line(device, INT_RTC, 0);
1585         }
1586         break;
1587
1588      case 0xb10:
1589         verboselog(space.machine(), 2, "mc68328_w: RTCIENR = %04x\n", data);
1590         mc68328->regs.rtcienr = data & 0x001f;
1591         break;
1592
1593      case 0xb12:
1594         verboselog(space.machine(), 2, "mc68328_w: STPWTCH = %04x\n", data);
1595         mc68328->regs.stpwtch = data & 0x003f;
1596         break;
1597
1598      default:
1599         verboselog(space.machine(), 0, "mc68328_w: Unknown address (0x%06x) = %04x (%04x)\n", 0xfff000 + address, data, mem_mask);
1600         break;
1601   }
1602}
1603
1604READ16_DEVICE_HANDLER( mc68328_r )
1605{
1606   mc68328_t* mc68328 = mc68328_get_safe_token( device );
1607   UINT16 temp16 = 0;
1608   UINT32 address = offset << 1;
1609
1610   switch(address)
1611   {
1612      case 0x000:
1613         if( mem_mask & 0x00ff )
1614         {
1615            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff001)\n", mem_mask);
1616         }
1617         else
1618         {
1619            verboselog(space.machine(), 2, "mc68328_r (%04x): SCR = %02x\n", mem_mask, mc68328->regs.scr);
1620            return mc68328->regs.scr << 8;
1621         }
1622         break;
1623
1624      case 0x100:
1625         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPBASEA = %04x\n", mem_mask, mc68328->regs.grpbasea);
1626         return mc68328->regs.grpbasea;
1627
1628      case 0x102:
1629         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPBASEB = %04x\n", mem_mask, mc68328->regs.grpbaseb);
1630         return mc68328->regs.grpbaseb;
1631
1632      case 0x104:
1633         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPBASEC = %04x\n", mem_mask, mc68328->regs.grpbasec);
1634         return mc68328->regs.grpbasec;
1635
1636      case 0x106:
1637         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPBASED = %04x\n", mem_mask, mc68328->regs.grpbased);
1638         return mc68328->regs.grpbased;
1639
1640      case 0x108:
1641         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPMASKA = %04x\n", mem_mask, mc68328->regs.grpmaska);
1642         return mc68328->regs.grpmaska;
1643
1644      case 0x10a:
1645         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPMASKB = %04x\n", mem_mask, mc68328->regs.grpmaskb);
1646         return mc68328->regs.grpmaskb;
1647
1648      case 0x10c:
1649         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPMASKC = %04x\n", mem_mask, mc68328->regs.grpmaskc);
1650         return mc68328->regs.grpmaskc;
1651
1652      case 0x10e:
1653         verboselog(space.machine(), 2, "mc68328_r (%04x): GRPMASKD = %04x\n", mem_mask, mc68328->regs.grpmaskd);
1654         return mc68328->regs.grpmaskd;
1655
1656      case 0x110:
1657         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA0(0) = %04x\n", mem_mask, mc68328->regs.csa0 & 0x0000ffff);
1658         return mc68328->regs.csa0 & 0x0000ffff;
1659
1660      case 0x112:
1661         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA0(16) = %04x\n", mem_mask, mc68328->regs.csa0 >> 16);
1662         return mc68328->regs.csa0 >> 16;
1663
1664      case 0x114:
1665         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA1(0) = %04x\n", mem_mask, mc68328->regs.csa1 & 0x0000ffff);
1666         return mc68328->regs.csa1 & 0x0000ffff;
1667
1668      case 0x116:
1669         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA1(16) = %04x\n", mem_mask, mc68328->regs.csa1 >> 16);
1670         return mc68328->regs.csa1 >> 16;
1671
1672      case 0x118:
1673         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA2(0) = %04x\n", mem_mask, mc68328->regs.csa2 & 0x0000ffff);
1674         return mc68328->regs.csa2 & 0x0000ffff;
1675
1676      case 0x11a:
1677         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA2(16) = %04x\n", mem_mask, mc68328->regs.csa2 >> 16);
1678         return mc68328->regs.csa2 >> 16;
1679
1680      case 0x11c:
1681         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA3(0) = %04x\n", mem_mask, mc68328->regs.csa3 & 0x0000ffff);
1682         return mc68328->regs.csa3 & 0x0000ffff;
1683
1684      case 0x11e:
1685         verboselog(space.machine(), 5, "mc68328_r (%04x): CSA3(16) = %04x\n", mem_mask, mc68328->regs.csa3 >> 16);
1686         return mc68328->regs.csa3 >> 16;
1687
1688      case 0x120:
1689         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB0(0) = %04x\n", mem_mask, mc68328->regs.csb0 & 0x0000ffff);
1690         return mc68328->regs.csb0 & 0x0000ffff;
1691
1692      case 0x122:
1693         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB0(16) = %04x\n", mem_mask, mc68328->regs.csb0 >> 16);
1694         return mc68328->regs.csb0 >> 16;
1695
1696      case 0x124:
1697         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB1(0) = %04x\n", mem_mask, mc68328->regs.csb1 & 0x0000ffff);
1698         return mc68328->regs.csb1 & 0x0000ffff;
1699
1700      case 0x126:
1701         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB1(16) = %04x\n", mem_mask, mc68328->regs.csb1 >> 16);
1702         return mc68328->regs.csb1 >> 16;
1703
1704      case 0x128:
1705         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB2(0) = %04x\n", mem_mask, mc68328->regs.csb2 & 0x0000ffff);
1706         return mc68328->regs.csb2 & 0x0000ffff;
1707
1708      case 0x12a:
1709         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB2(16) = %04x\n", mem_mask, mc68328->regs.csb2 >> 16);
1710         return mc68328->regs.csb2 >> 16;
1711
1712      case 0x12c:
1713         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB3(0) = %04x\n", mem_mask, mc68328->regs.csb3 & 0x0000ffff);
1714         return mc68328->regs.csb3 & 0x0000ffff;
1715
1716      case 0x12e:
1717         verboselog(space.machine(), 5, "mc68328_r (%04x): CSB3(16) = %04x\n", mem_mask, mc68328->regs.csb3 >> 16);
1718         return mc68328->regs.csb3 >> 16;
1719
1720      case 0x130:
1721         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC0(0) = %04x\n", mem_mask, mc68328->regs.csc0 & 0x0000ffff);
1722         return mc68328->regs.csc0 & 0x0000ffff;
1723
1724      case 0x132:
1725         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC0(16) = %04x\n", mem_mask, mc68328->regs.csc0 >> 16);
1726         return mc68328->regs.csc0 >> 16;
1727
1728      case 0x134:
1729         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC1(0) = %04x\n", mem_mask, mc68328->regs.csc1 & 0x0000ffff);
1730         return mc68328->regs.csc1 & 0x0000ffff;
1731
1732      case 0x136:
1733         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC1(16) = %04x\n", mem_mask, mc68328->regs.csc1 >> 16);
1734         return mc68328->regs.csc1 >> 16;
1735
1736      case 0x138:
1737         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC2(0) = %04x\n", mem_mask, mc68328->regs.csc2 & 0x0000ffff);
1738         return mc68328->regs.csc2 & 0x0000ffff;
1739
1740      case 0x13a:
1741         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC2(16) = %04x\n", mem_mask, mc68328->regs.csc2 >> 16);
1742         return mc68328->regs.csc2 >> 16;
1743
1744      case 0x13c:
1745         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC3(0) = %04x\n", mem_mask, mc68328->regs.csc3 & 0x0000ffff);
1746         return mc68328->regs.csc3 & 0x0000ffff;
1747
1748      case 0x13e:
1749         verboselog(space.machine(), 5, "mc68328_r (%04x): CSC3(16) = %04x\n", mem_mask, mc68328->regs.csc3 >> 16);
1750         return mc68328->regs.csc3 >> 16;
1751
1752      case 0x140:
1753         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD0(0) = %04x\n", mem_mask, mc68328->regs.csd0 & 0x0000ffff);
1754         return mc68328->regs.csd0 & 0x0000ffff;
1755
1756      case 0x142:
1757         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD0(16) = %04x\n", mem_mask, mc68328->regs.csd0 >> 16);
1758         return mc68328->regs.csd0 >> 16;
1759
1760      case 0x144:
1761         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD1(0) = %04x\n", mem_mask, mc68328->regs.csd1 & 0x0000ffff);
1762         return mc68328->regs.csd1 & 0x0000ffff;
1763
1764      case 0x146:
1765         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD1(16) = %04x\n", mem_mask, mc68328->regs.csd1 >> 16);
1766         return mc68328->regs.csd1 >> 16;
1767
1768      case 0x148:
1769         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD2(0) = %04x\n", mem_mask, mc68328->regs.csd2 & 0x0000ffff);
1770         return mc68328->regs.csd2 & 0x0000ffff;
1771
1772      case 0x14a:
1773         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD2(16) = %04x\n", mem_mask, mc68328->regs.csd2 >> 16);
1774         return mc68328->regs.csd2 >> 16;
1775
1776      case 0x14c:
1777         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD3(0) = %04x\n", mem_mask, mc68328->regs.csd3 & 0x0000ffff);
1778         return mc68328->regs.csd3 & 0x0000ffff;
1779
1780      case 0x14e:
1781         verboselog(space.machine(), 5, "mc68328_r (%04x): CSD3(16) = %04x\n", mem_mask, mc68328->regs.csd3 >> 16);
1782         return mc68328->regs.csd3 >> 16;
1783
1784      case 0x200:
1785         verboselog(space.machine(), 2, "mc68328_r (%04x): PLLCR = %04x\n", mem_mask, mc68328->regs.pllcr);
1786         return mc68328->regs.pllcr;
1787
1788      case 0x202:
1789         verboselog(space.machine(), 2, "mc68328_r (%04x): PLLFSR = %04x\n", mem_mask, mc68328->regs.pllfsr);
1790         mc68328->regs.pllfsr ^= 0x8000;
1791         return mc68328->regs.pllfsr;
1792
1793      case 0x206:
1794         if( mem_mask & 0x00ff )
1795         {
1796            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff206)\n", mem_mask);
1797         }
1798         else
1799         {
1800            verboselog(space.machine(), 2, "mc68328_r (%04x): PCTLR = %02x\n", mem_mask, mc68328->regs.pctlr);
1801            return mc68328->regs.pctlr << 8;
1802         }
1803         break;
1804
1805      case 0x300:
1806         if( mem_mask & 0x00ff )
1807         {
1808            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff301)\n", mem_mask);
1809         }
1810         else
1811         {
1812            verboselog(space.machine(), 2, "mc68328_r (%04x): IVR = %02x\n", mem_mask, mc68328->regs.ivr);
1813            return mc68328->regs.ivr << 8;
1814         }
1815         break;
1816
1817      case 0x302:
1818         verboselog(space.machine(), 2, "mc68328_r (%04x): ICR = %04x\n", mem_mask, mc68328->regs.icr);
1819         return mc68328->regs.icr;
1820
1821      case 0x304:
1822         verboselog(space.machine(), 2, "mc68328_r (%04x): IMR(16) = %04x\n", mem_mask, mc68328->regs.imr >> 16);
1823         return mc68328->regs.imr >> 16;
1824
1825      case 0x306:
1826         verboselog(space.machine(), 2, "mc68328_r (%04x): IMR(0) = %04x\n", mem_mask, mc68328->regs.imr & 0x0000ffff);
1827         return mc68328->regs.imr & 0x0000ffff;
1828
1829      case 0x308:
1830         verboselog(space.machine(), 2, "mc68328_r (%04x): IWR(16) = %04x\n", mem_mask, mc68328->regs.iwr >> 16);
1831         return mc68328->regs.iwr >> 16;
1832
1833      case 0x30a:
1834         verboselog(space.machine(), 2, "mc68328_r (%04x): IWR(0) = %04x\n", mem_mask, mc68328->regs.iwr & 0x0000ffff);
1835         return mc68328->regs.iwr & 0x0000ffff;
1836
1837      case 0x30c:
1838         verboselog(space.machine(), 2, "mc68328_r (%04x): ISR(16) = %04x\n", mem_mask, mc68328->regs.isr >> 16);
1839         return mc68328->regs.isr >> 16;
1840
1841      case 0x30e:
1842         verboselog(space.machine(), 2, "mc68328_r (%04x): ISR(0) = %04x\n", mem_mask, mc68328->regs.isr & 0x0000ffff);
1843         return mc68328->regs.isr & 0x0000ffff;
1844
1845      case 0x310:
1846         verboselog(space.machine(), 2, "mc68328_r (%04x): IPR(16) = %04x\n", mem_mask, mc68328->regs.ipr >> 16);
1847         return mc68328->regs.ipr >> 16;
1848
1849      case 0x312:
1850         verboselog(space.machine(), 2, "mc68328_r (%04x): IPR(0) = %04x\n", mem_mask, mc68328->regs.ipr & 0x0000ffff);
1851         return mc68328->regs.ipr & 0x0000ffff;
1852
1853      case 0x400:
1854         if( mem_mask & 0x00ff )
1855         {
1856            verboselog(space.machine(), 2, "mc68328_r (%04x): PADATA = %02x\n", mem_mask, mc68328->regs.padata);
1857            if(!mc68328->in_port_a.isnull())
1858            {
1859               return mc68328->in_port_a( 0 );
1860            }
1861            else
1862            {
1863               return mc68328->regs.padata;
1864            }
1865         }
1866         else
1867         {
1868            verboselog(space.machine(), 2, "mc68328_r (%04x): PADIR = %02x\n", mem_mask, mc68328->regs.padir);
1869            return mc68328->regs.padir << 8;
1870         }
1871         break;
1872
1873      case 0x402:
1874         if( mem_mask & 0x00ff )
1875         {
1876            verboselog(space.machine(), 2, "mc68328_r (%04x): PASEL = %02x\n", mem_mask, mc68328->regs.pasel);
1877            return mc68328->regs.pasel;
1878         }
1879         else
1880         {
1881            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff402)\n", mem_mask);
1882         }
1883         break;
1884
1885      case 0x408:
1886         if( mem_mask & 0x00ff )
1887         {
1888            verboselog(space.machine(), 2, "mc68328_r (%04x): PBDATA = %02x\n", mem_mask, mc68328->regs.pbdata);
1889            if(!mc68328->in_port_b.isnull())
1890            {
1891               return mc68328->in_port_b( 0 );
1892            }
1893            else
1894            {
1895               return mc68328->regs.pbdata;
1896            }
1897         }
1898         else
1899         {
1900            verboselog(space.machine(), 2, "mc68328_r (%04x): PBDIR = %02x\n", mem_mask, mc68328->regs.pbdir);
1901            return mc68328->regs.pbdir << 8;
1902         }
1903         break;
1904
1905      case 0x40a:
1906         if( mem_mask & 0x00ff )
1907         {
1908            verboselog(space.machine(), 2, "mc68328_r (%04x): PBSEL = %02x\n", mem_mask, mc68328->regs.pbsel);
1909            return mc68328->regs.pbsel;
1910         }
1911         else
1912         {
1913            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff40a)\n", mem_mask);
1914         }
1915         break;
1916
1917      case 0x410:
1918         if( mem_mask & 0x00ff )
1919         {
1920            verboselog(space.machine(), 2, "mc68328_r (%04x): PCDATA = %02x\n", mem_mask, mc68328->regs.pcdata);
1921            if(!mc68328->in_port_c.isnull())
1922            {
1923               return mc68328->in_port_c( 0 );
1924            }
1925            else
1926            {
1927               return mc68328->regs.pcdata;
1928            }
1929         }
1930         else
1931         {
1932            verboselog(space.machine(), 2, "mc68328_r (%04x): PCDIR = %02x\n", mem_mask, mc68328->regs.pcdir);
1933            return mc68328->regs.pcdir << 8;
1934         }
1935         break;
1936
1937      case 0x412:
1938         if( mem_mask & 0x00ff )
1939         {
1940            verboselog(space.machine(), 2, "mc68328_r (%04x): PCSEL = %02x\n", mem_mask, mc68328->regs.pcsel);
1941            return mc68328->regs.pcsel;
1942         }
1943         else
1944         {
1945            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff412)\n", mem_mask);
1946         }
1947         break;
1948
1949      case 0x418:
1950         if( mem_mask & 0x00ff )
1951         {
1952            verboselog(space.machine(), 2, "mc68328_r (%04x): PDDATA = %02x\n", mem_mask, mc68328->regs.pddata);
1953            if(!mc68328->in_port_d.isnull())
1954            {
1955               return mc68328->in_port_d( 0 );
1956            }
1957            else
1958            {
1959               return mc68328->regs.pddata;
1960            }
1961         }
1962         else
1963         {
1964            verboselog(space.machine(), 2, "mc68328_r (%04x): PDDIR = %02x\n", mem_mask, mc68328->regs.pddir);
1965            return mc68328->regs.pddir << 8;
1966         }
1967         break;
1968
1969      case 0x41a:
1970         if( mem_mask & 0x00ff )
1971         {
1972            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff41b)\n", mem_mask);
1973         }
1974         else
1975         {
1976            verboselog(space.machine(), 2, "mc68328_r (%04x): PDPUEN = %02x\n", mem_mask, mc68328->regs.pdpuen);
1977            return mc68328->regs.pdpuen << 8;
1978         }
1979         break;
1980
1981      case 0x41c:
1982         if( mem_mask & 0x00ff )
1983         {
1984            verboselog(space.machine(), 2, "mc68328_r (%04x): PDIRQEN = %02x\n", mem_mask, mc68328->regs.pdirqen);
1985            return mc68328->regs.pdirqen;
1986         }
1987         else
1988         {
1989            verboselog(space.machine(), 2, "mc68328_r (%04x): PDPOL = %02x\n", mem_mask, mc68328->regs.pdpol);
1990            return mc68328->regs.pdpol << 8;
1991         }
1992         break;
1993
1994      case 0x41e:
1995         if( mem_mask & 0x00ff )
1996         {
1997            verboselog(space.machine(), 2, "mc68328_r (%04x): PDIRQEDGE = %02x\n", mem_mask, mc68328->regs.pdirqedge);
1998            return mc68328->regs.pdirqedge;
1999         }
2000         else
2001         {
2002            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff41e)\n", mem_mask);
2003         }
2004         break;
2005
2006      case 0x420:
2007         if( mem_mask & 0x00ff )
2008         {
2009            verboselog(space.machine(), 2, "mc68328_r (%04x): PEDATA = %02x\n", mem_mask, mc68328->regs.pedata);
2010            if(!mc68328->in_port_e.isnull())
2011            {
2012               return mc68328->in_port_e( 0 );
2013            }
2014            else
2015            {
2016               return mc68328->regs.pedata;
2017            }
2018         }
2019         else
2020         {
2021            verboselog(space.machine(), 2, "mc68328_r (%04x): PEDIR = %02x\n", mem_mask, mc68328->regs.pedir);
2022            return mc68328->regs.pedir << 8;
2023         }
2024         break;
2025
2026      case 0x422:
2027         if( mem_mask & 0x00ff )
2028         {
2029            verboselog(space.machine(), 2, "mc68328_r (%04x): PESEL = %02x\n", mem_mask, mc68328->regs.pesel);
2030            return mc68328->regs.pesel;
2031         }
2032         else
2033         {
2034            verboselog(space.machine(), 2, "mc68328_r (%04x): PEPUEN = %02x\n", mem_mask, mc68328->regs.pepuen);
2035            return mc68328->regs.pepuen << 8;
2036         }
2037         break;
2038
2039      case 0x428:
2040         if( mem_mask & 0x00ff )
2041         {
2042            verboselog(space.machine(), 2, "mc68328_r (%04x): PFDATA = %02x\n", mem_mask, mc68328->regs.pfdata);
2043            if(!mc68328->in_port_f.isnull())
2044            {
2045               return mc68328->in_port_f( 0 );
2046            }
2047            else
2048            {
2049               return mc68328->regs.pfdata;
2050            }
2051         }
2052         else
2053         {
2054            verboselog(space.machine(), 2, "mc68328_r (%04x): PFDIR = %02x\n", mem_mask, mc68328->regs.pfdir);
2055            return mc68328->regs.pfdir << 8;
2056         }
2057         break;
2058
2059      case 0x42a:
2060         if( mem_mask & 0x00ff )
2061         {
2062            verboselog(space.machine(), 2, "mc68328_r (%04x): PFSEL = %02x\n", mem_mask, mc68328->regs.pfsel);
2063            return mc68328->regs.pfsel;
2064         }
2065         else
2066         {
2067            verboselog(space.machine(), 2, "mc68328_r (%04x): PFPUEN = %02x\n", mem_mask, mc68328->regs.pfpuen);
2068            return mc68328->regs.pfpuen << 8;
2069         }
2070         break;
2071
2072      case 0x430:
2073         if( mem_mask & 0x00ff )
2074         {
2075            verboselog(space.machine(), 2, "mc68328_r (%04x): PGDATA = %02x\n", mem_mask, mc68328->regs.pgdata);
2076            if(!mc68328->in_port_g.isnull())
2077            {
2078               return mc68328->in_port_g( 0 );
2079            }
2080            else
2081            {
2082               return mc68328->regs.pgdata;
2083            }
2084         }
2085         else
2086         {
2087            verboselog(space.machine(), 2, "mc68328_r (%04x): PGDIR = %02x\n", mem_mask, mc68328->regs.pgdir);
2088            return mc68328->regs.pgdir << 8;
2089         }
2090         break;
2091
2092      case 0x432:
2093         if( mem_mask & 0x00ff )
2094         {
2095            verboselog(space.machine(), 2, "mc68328_r (%04x): PGSEL = %02x\n", mem_mask, mc68328->regs.pgsel);
2096            return mc68328->regs.pgsel;
2097         }
2098         else
2099         {
2100            verboselog(space.machine(), 2, "mc68328_r (%04x): PGPUEN = %02x\n", mem_mask, mc68328->regs.pgpuen);
2101            return mc68328->regs.pgpuen << 8;
2102         }
2103         break;
2104
2105      case 0x438:
2106         if( mem_mask & 0x00ff )
2107         {
2108            verboselog(space.machine(), 2, "mc68328_r (%04x): PJDATA = %02x\n", mem_mask, mc68328->regs.pjdata);
2109            if(!mc68328->in_port_j.isnull())
2110            {
2111               return mc68328->in_port_j( 0 );
2112            }
2113            else
2114            {
2115               return mc68328->regs.pjdata;
2116            }
2117         }
2118         else
2119         {
2120            verboselog(space.machine(), 2, "mc68328_r (%04x): PJDIR = %02x\n", mem_mask, mc68328->regs.pjdir);
2121            return mc68328->regs.pjdir << 8;
2122         }
2123         break;
2124
2125      case 0x43a:
2126         if( mem_mask & 0x00ff )
2127         {
2128            verboselog(space.machine(), 2, "mc68328_r (%04x): PJSEL = %02x\n", mem_mask, mc68328->regs.pjsel);
2129            return mc68328->regs.pjsel;
2130         }
2131         else
2132         {
2133            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfff43a)\n", mem_mask);
2134         }
2135         break;
2136
2137      case 0x440:
2138         if( mem_mask & 0x00ff )
2139         {
2140            verboselog(space.machine(), 2, "mc68328_r (%04x): PKDATA = %02x\n", mem_mask, mc68328->regs.pkdata);
2141            if(!mc68328->in_port_k.isnull())
2142            {
2143               return mc68328->in_port_k( 0 );
2144            }
2145            else
2146            {
2147               return mc68328->regs.pkdata;
2148            }
2149         }
2150         else
2151         {
2152            verboselog(space.machine(), 2, "mc68328_r (%04x): PKDIR = %02x\n", mem_mask, mc68328->regs.pkdir);
2153            return mc68328->regs.pkdir << 8;
2154         }
2155         break;
2156
2157      case 0x442:
2158         if( mem_mask & 0x00ff )
2159         {
2160            verboselog(space.machine(), 2, "mc68328_r (%04x): PKSEL = %02x\n", mem_mask, mc68328->regs.pksel);
2161            return mc68328->regs.pksel;
2162         }
2163         else
2164         {
2165            verboselog(space.machine(), 2, "mc68328_r (%04x): PKPUEN = %02x\n", mem_mask, mc68328->regs.pkpuen);
2166            return mc68328->regs.pkpuen << 8;
2167         }
2168         break;
2169
2170      case 0x448:
2171         if( mem_mask & 0x00ff )
2172         {
2173            verboselog(space.machine(), 2, "mc68328_r (%04x): PMDATA = %02x\n", mem_mask, mc68328->regs.pmdata);
2174            if(!mc68328->in_port_m.isnull())
2175            {
2176               return mc68328->in_port_m( 0 );
2177            }
2178            else
2179            {
2180               return mc68328->regs.pmdata;
2181            }
2182         }
2183         else
2184         {
2185            verboselog(space.machine(), 2, "mc68328_r (%04x): PMDIR = %02x\n", mem_mask, mc68328->regs.pmdir);
2186            return mc68328->regs.pmdir << 8;
2187         }
2188         break;
2189
2190      case 0x44a:
2191         if( mem_mask & 0x00ff )
2192         {
2193            verboselog(space.machine(), 2, "mc68328_r (%04x): PMSEL = %02x\n", mem_mask, mc68328->regs.pmsel);
2194            return mc68328->regs.pmsel;
2195         }
2196         else
2197         {
2198            verboselog(space.machine(), 2, "mc68328_r (%04x): PMPUEN = %02x\n", mem_mask, mc68328->regs.pmpuen);
2199            return mc68328->regs.pmpuen << 8;
2200         }
2201         break;
2202
2203      case 0x500:
2204         verboselog(space.machine(), 2, "mc68328_r (%04x): PWMC = %04x\n", mem_mask, mc68328->regs.pwmc);
2205         temp16 = mc68328->regs.pwmc;
2206         if(mc68328->regs.pwmc & PWMC_PWMIRQ)
2207         {
2208            mc68328->regs.pwmc &= ~PWMC_PWMIRQ;
2209            mc68328_set_interrupt_line(device, INT_PWM, 0);
2210         }
2211         return temp16;
2212
2213      case 0x502:
2214         verboselog(space.machine(), 2, "mc68328_r (%04x): PWMP = %04x\n", mem_mask, mc68328->regs.pwmp);
2215         return mc68328->regs.pwmp;
2216
2217      case 0x504:
2218         verboselog(space.machine(), 2, "mc68328_r (%04x): PWMW = %04x\n", mem_mask, mc68328->regs.pwmw);
2219         return mc68328->regs.pwmw;
2220
2221      case 0x506:
2222         verboselog(space.machine(), 2, "mc68328_r (%04x): PWMCNT = %04x\n", mem_mask, mc68328->regs.pwmcnt);
2223         return mc68328->regs.pwmcnt;
2224
2225      case 0x600:
2226         verboselog(space.machine(), 2, "mc68328_r (%04x): TCTL1 = %04x\n", mem_mask, mc68328->regs.tctl[0]);
2227         return mc68328->regs.tctl[0];
2228
2229      case 0x602:
2230         verboselog(space.machine(), 2, "mc68328_r (%04x): TPRER1 = %04x\n", mem_mask, mc68328->regs.tprer[0]);
2231         return mc68328->regs.tprer[0];
2232
2233      case 0x604:
2234         verboselog(space.machine(), 2, "mc68328_r (%04x): TCMP1 = %04x\n", mem_mask, mc68328->regs.tcmp[0]);
2235         return mc68328->regs.tcmp[0];
2236
2237      case 0x606:
2238         verboselog(space.machine(), 2, "mc68328_r (%04x): TCR1 = %04x\n", mem_mask, mc68328->regs.tcr[0]);
2239         return mc68328->regs.tcr[0];
2240
2241      case 0x608:
2242         verboselog(space.machine(), 2, "mc68328_r (%04x): TCN1 = %04x\n", mem_mask, mc68328->regs.tcn[0]);
2243         return mc68328->regs.tcn[0];
2244
2245      case 0x60a:
2246         verboselog(space.machine(), 5, "mc68328_r (%04x): TSTAT1 = %04x\n", mem_mask, mc68328->regs.tstat[0]);
2247         mc68328->regs.tclear[0] |= mc68328->regs.tstat[0];
2248         return mc68328->regs.tstat[0];
2249
2250      case 0x60c:
2251         verboselog(space.machine(), 2, "mc68328_r (%04x): TCTL2 = %04x\n", mem_mask, mc68328->regs.tctl[1]);
2252         return mc68328->regs.tctl[1];
2253
2254      case 0x60e:
2255         verboselog(space.machine(), 2, "mc68328_r (%04x): TPREP2 = %04x\n", mem_mask, mc68328->regs.tprer[1]);
2256         return mc68328->regs.tprer[1];
2257
2258      case 0x610:
2259         verboselog(space.machine(), 2, "mc68328_r (%04x): TCMP2 = %04x\n", mem_mask, mc68328->regs.tcmp[1]);
2260         return mc68328->regs.tcmp[1];
2261
2262      case 0x612:
2263         verboselog(space.machine(), 2, "mc68328_r (%04x): TCR2 = %04x\n", mem_mask, mc68328->regs.tcr[1]);
2264         return mc68328->regs.tcr[1];
2265
2266      case 0x614:
2267         verboselog(space.machine(), 2, "mc68328_r (%04x): TCN2 = %04x\n", mem_mask, mc68328->regs.tcn[1]);
2268         return mc68328->regs.tcn[1];
2269
2270      case 0x616:
2271         verboselog(space.machine(), 2, "mc68328_r (%04x): TSTAT2 = %04x\n", mem_mask, mc68328->regs.tstat[1]);
2272         mc68328->regs.tclear[1] |= mc68328->regs.tstat[1];
2273         return mc68328->regs.tstat[1];
2274
2275      case 0x618:
2276         verboselog(space.machine(), 2, "mc68328_r (%04x): WCTLR = %04x\n", mem_mask, mc68328->regs.wctlr);
2277         return mc68328->regs.wctlr;
2278
2279      case 0x61a:
2280         verboselog(space.machine(), 2, "mc68328_r (%04x): WCMPR = %04x\n", mem_mask, mc68328->regs.wcmpr);
2281         return mc68328->regs.wcmpr;
2282
2283      case 0x61c:
2284         verboselog(space.machine(), 2, "mc68328_r (%04x): WCN = %04x\n", mem_mask, mc68328->regs.wcn);
2285         return mc68328->regs.wcn;
2286
2287      case 0x700:
2288         verboselog(space.machine(), 2, "mc68328_r (%04x): SPISR = %04x\n", mem_mask, mc68328->regs.spisr);
2289         return mc68328->regs.spisr;
2290
2291      case 0x800:
2292         verboselog(space.machine(), 2, "mc68328_r (%04x): SPIMDATA = %04x\n", mem_mask, mc68328->regs.spimdata);
2293         if(!mc68328->in_spim.isnull())
2294         {
2295            return mc68328->in_spim( 0, 0xffff );
2296         }
2297         return mc68328->regs.spimdata;
2298
2299      case 0x802:
2300         verboselog(space.machine(), 2, "mc68328_r (%04x): SPIMCONT = %04x\n", mem_mask, mc68328->regs.spimcont);
2301         if(mc68328->regs.spimcont & SPIM_XCH)
2302         {
2303            mc68328->regs.spimcont &= ~SPIM_XCH;
2304            mc68328->regs.spimcont |= SPIM_SPIMIRQ;
2305            return ((mc68328->regs.spimcont | SPIM_XCH) &~ SPIM_SPIMIRQ);
2306         }
2307         return mc68328->regs.spimcont;
2308
2309      case 0x900:
2310         verboselog(space.machine(), 2, "mc68328_r (%04x): USTCNT = %04x\n", mem_mask, mc68328->regs.ustcnt);
2311         return mc68328->regs.ustcnt;
2312
2313      case 0x902:
2314         verboselog(space.machine(), 2, "mc68328_r (%04x): UBAUD = %04x\n", mem_mask, mc68328->regs.ubaud);
2315         return mc68328->regs.ubaud;
2316
2317      case 0x904:
2318         verboselog(space.machine(), 5, "mc68328_r (%04x): URX = %04x\n", mem_mask, mc68328->regs.urx);
2319         return mc68328->regs.urx;
2320
2321      case 0x906:
2322         verboselog(space.machine(), 5, "mc68328_r (%04x): UTX = %04x\n", mem_mask, mc68328->regs.utx);
2323         return mc68328->regs.utx | UTX_FIFO_EMPTY | UTX_FIFO_HALF | UTX_TX_AVAIL;
2324
2325      case 0x908:
2326         verboselog(space.machine(), 2, "mc68328_r (%04x): UMISC = %04x\n", mem_mask, mc68328->regs.umisc);
2327         return mc68328->regs.umisc;
2328
2329      case 0xa00:
2330         verboselog(space.machine(), 2, "mc68328_r (%04x): LSSA(16) = %04x\n", mem_mask, mc68328->regs.lssa >> 16);
2331         return mc68328->regs.lssa >> 16;
2332
2333      case 0xa02:
2334         verboselog(space.machine(), 2, "mc68328_r (%04x): LSSA(0) = %04x\n", mem_mask, mc68328->regs.lssa & 0x0000ffff);
2335         return mc68328->regs.lssa & 0x0000ffff;
2336
2337      case 0xa04:
2338         if( mem_mask & 0x00ff )
2339         {
2340            verboselog(space.machine(), 2, "mc68328_r (%04x): LVPW = %02x\n", mem_mask, mc68328->regs.lvpw);
2341            return mc68328->regs.lvpw;
2342         }
2343         else
2344         {
2345            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa04)\n", mem_mask);
2346         }
2347         break;
2348
2349      case 0xa08:
2350         verboselog(space.machine(), 2, "mc68328_r (%04x): LXMAX = %04x\n", mem_mask, mc68328->regs.lxmax);
2351         return mc68328->regs.lxmax;
2352
2353      case 0xa0a:
2354         verboselog(space.machine(), 2, "mc68328_r (%04x): LYMAX = %04x\n", mem_mask, mc68328->regs.lymax);
2355         return mc68328->regs.lymax;
2356
2357      case 0xa18:
2358         verboselog(space.machine(), 2, "mc68328_r (%04x): LCXP = %04x\n", mem_mask, mc68328->regs.lcxp);
2359         return mc68328->regs.lcxp;
2360
2361      case 0xa1a:
2362         verboselog(space.machine(), 2, "mc68328_r (%04x): LCYP = %04x\n", mem_mask, mc68328->regs.lcyp);
2363         return mc68328->regs.lcyp;
2364
2365      case 0xa1c:
2366         verboselog(space.machine(), 2, "mc68328_r (%04x): LCWCH = %04x\n", mem_mask, mc68328->regs.lcwch);
2367         return mc68328->regs.lcwch;
2368
2369      case 0xa1e:
2370         if( mem_mask & 0x00ff )
2371         {
2372            verboselog(space.machine(), 2, "mc68328_r (%04x): LBLKC = %02x\n", mem_mask, mc68328->regs.lblkc);
2373            return mc68328->regs.lblkc;
2374         }
2375         else
2376         {
2377            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa1e)\n", mem_mask);
2378         }
2379         break;
2380
2381      case 0xa20:
2382         if( mem_mask & 0x00ff )
2383         {
2384            verboselog(space.machine(), 2, "mc68328_r (%04x): LPOLCF = %02x\n", mem_mask, mc68328->regs.lpolcf);
2385            return mc68328->regs.lpolcf;
2386         }
2387         else
2388         {
2389            verboselog(space.machine(), 2, "mc68328_r (%04x): LPICF = %02x\n", mem_mask, mc68328->regs.lpicf);
2390            return mc68328->regs.lpicf << 8;
2391         }
2392         break;
2393
2394      case 0xa22:
2395         if( mem_mask & 0x00ff )
2396         {
2397            verboselog(space.machine(), 2, "mc68328_r (%04x): LACDRC = %02x\n", mem_mask, mc68328->regs.lacdrc);
2398            return mc68328->regs.lacdrc;
2399         }
2400         else
2401         {
2402            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa22)\n", mem_mask);
2403         }
2404         break;
2405
2406      case 0xa24:
2407         if( mem_mask & 0x00ff )
2408         {
2409            verboselog(space.machine(), 2, "mc68328_r (%04x): LPXCD = %02x\n", mem_mask, mc68328->regs.lpxcd);
2410            return mc68328->regs.lpxcd;
2411         }
2412         else
2413         {
2414            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa24)\n", mem_mask);
2415         }
2416         break;
2417
2418      case 0xa26:
2419         if( mem_mask & 0x00ff )
2420         {
2421            verboselog(space.machine(), 2, "mc68328_r (%04x): LCKCON = %02x\n", mem_mask, mc68328->regs.lckcon);
2422            return mc68328->regs.lckcon;
2423         }
2424         else
2425         {
2426            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa26)\n", mem_mask);
2427         }
2428         break;
2429
2430      case 0xa28:
2431         if( mem_mask & 0x00ff )
2432         {
2433            verboselog(space.machine(), 2, "mc68328_r (%04x): LLBAR = %02x\n", mem_mask, mc68328->regs.llbar);
2434            return mc68328->regs.llbar;
2435         }
2436         else
2437         {
2438            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa28)\n", mem_mask);
2439         }
2440         break;
2441
2442      case 0xa2a:
2443         if( mem_mask & 0x00ff )
2444         {
2445            verboselog(space.machine(), 2, "mc68328_r (%04x): LOTCR = %02x\n", mem_mask, mc68328->regs.lotcr);
2446            return mc68328->regs.lotcr;
2447         }
2448         else
2449         {
2450            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa2a)\n", mem_mask);
2451         }
2452         break;
2453
2454      case 0xa2c:
2455         if( mem_mask & 0x00ff )
2456         {
2457            verboselog(space.machine(), 2, "mc68328_r (%04x): LPOSR = %02x\n", mem_mask, mc68328->regs.lposr);
2458            return mc68328->regs.lposr;
2459         }
2460         else
2461         {
2462            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa2c)\n", mem_mask);
2463         }
2464         break;
2465
2466      case 0xa30:
2467         if( mem_mask & 0x00ff )
2468         {
2469            verboselog(space.machine(), 2, "mc68328_r (%04x): LFRCM = %02x\n", mem_mask, mc68328->regs.lfrcm);
2470            return mc68328->regs.lfrcm;
2471         }
2472         else
2473         {
2474            verboselog(space.machine(), 2, "mc68328_r (%04x): Unknown address (0xfffa30)\n", mem_mask);
2475         }
2476         break;
2477
2478      case 0xa32:
2479         verboselog(space.machine(), 2, "mc68328_r (%04x): LGPMR = %04x\n", mem_mask, mc68328->regs.lgpmr);
2480         return mc68328->regs.lgpmr;
2481
2482      case 0xb00:
2483         verboselog(space.machine(), 2, "mc68328_r (%04x): HMSR(0) = %04x\n", mem_mask, mc68328->regs.hmsr & 0x0000ffff);
2484         return mc68328->regs.hmsr & 0x0000ffff;
2485
2486      case 0xb02:
2487         verboselog(space.machine(), 2, "mc68328_r (%04x): HMSR(16) = %04x\n", mem_mask, mc68328->regs.hmsr >> 16);
2488         return mc68328->regs.hmsr >> 16;
2489
2490      case 0xb04:
2491         verboselog(space.machine(), 2, "mc68328_r (%04x): ALARM(0) = %04x\n", mem_mask, mc68328->regs.alarm & 0x0000ffff);
2492         return mc68328->regs.alarm & 0x0000ffff;
2493
2494      case 0xb06:
2495         verboselog(space.machine(), 2, "mc68328_r (%04x): ALARM(16) = %04x\n", mem_mask, mc68328->regs.alarm >> 16);
2496         return mc68328->regs.alarm >> 16;
2497
2498      case 0xb0c:
2499         verboselog(space.machine(), 2, "mc68328_r (%04x): RTCCTL = %04x\n", mem_mask, mc68328->regs.rtcctl);
2500         return mc68328->regs.rtcctl;
2501
2502      case 0xb0e:
2503         verboselog(space.machine(), 2, "mc68328_r (%04x): RTCISR = %04x\n", mem_mask, mc68328->regs.rtcisr);
2504         return mc68328->regs.rtcisr;
2505
2506      case 0xb10:
2507         verboselog(space.machine(), 2, "mc68328_r (%04x): RTCIENR = %04x\n", mem_mask, mc68328->regs.rtcienr);
2508         return mc68328->regs.rtcienr;
2509
2510      case 0xb12:
2511         verboselog(space.machine(), 2, "mc68328_r (%04x): STPWTCH = %04x\n", mem_mask, mc68328->regs.stpwtch);
2512         return mc68328->regs.stpwtch;
2513
2514      default:
2515         verboselog(space.machine(), 0, "mc68328_r (%04x): Unknown address (0x%06x)\n", mem_mask, 0xfff000 + address);
2516         break;
2517   }
2518   return 0;
2519}
2520
2521static DEVICE_RESET( mc68328 )
2522{
2523   mc68328_t* mc68328 = mc68328_get_safe_token( device );
2524
2525   mc68328->regs.scr = 0x0c;
2526   mc68328->regs.grpbasea = 0x0000;
2527   mc68328->regs.grpbaseb = 0x0000;
2528   mc68328->regs.grpbasec = 0x0000;
2529   mc68328->regs.grpbased = 0x0000;
2530   mc68328->regs.grpmaska = 0x0000;
2531   mc68328->regs.grpmaskb = 0x0000;
2532   mc68328->regs.grpmaskc = 0x0000;
2533   mc68328->regs.grpmaskd = 0x0000;
2534   mc68328->regs.csa0 = 0x00010006;
2535   mc68328->regs.csa1 = 0x00010006;
2536   mc68328->regs.csa2 = 0x00010006;
2537   mc68328->regs.csa3 = 0x00010006;
2538   mc68328->regs.csb0 = 0x00010006;
2539   mc68328->regs.csb1 = 0x00010006;
2540   mc68328->regs.csb2 = 0x00010006;
2541   mc68328->regs.csb3 = 0x00010006;
2542   mc68328->regs.csc0 = 0x00010006;
2543   mc68328->regs.csc1 = 0x00010006;
2544   mc68328->regs.csc2 = 0x00010006;
2545   mc68328->regs.csc3 = 0x00010006;
2546   mc68328->regs.csd0 = 0x00010006;
2547   mc68328->regs.csd1 = 0x00010006;
2548   mc68328->regs.csd2 = 0x00010006;
2549   mc68328->regs.csd3 = 0x00010006;
2550
2551   mc68328->regs.pllcr = 0x2400;
2552   mc68328->regs.pllfsr = 0x0123;
2553   mc68328->regs.pctlr = 0x1f;
2554
2555   mc68328->regs.ivr = 0x00;
2556   mc68328->regs.icr = 0x0000;
2557   mc68328->regs.imr = 0x00ffffff;
2558   mc68328->regs.iwr = 0x00ffffff;
2559   mc68328->regs.isr = 0x00000000;
2560   mc68328->regs.ipr = 0x00000000;
2561
2562   mc68328->regs.padir = 0x00;
2563   mc68328->regs.padata = 0x00;
2564   mc68328->regs.pasel = 0x00;
2565   mc68328->regs.pbdir = 0x00;
2566   mc68328->regs.pbdata = 0x00;
2567   mc68328->regs.pbsel = 0x00;
2568   mc68328->regs.pcdir = 0x00;
2569   mc68328->regs.pcdata = 0x00;
2570   mc68328->regs.pcsel = 0x00;
2571   mc68328->regs.pddir = 0x00;
2572   mc68328->regs.pddata = 0x00;
2573   mc68328->regs.pdpuen = 0xff;
2574   mc68328->regs.pdpol = 0x00;
2575   mc68328->regs.pdirqen = 0x00;
2576   mc68328->regs.pddataedge = 0x00;
2577   mc68328->regs.pdirqedge = 0x00;
2578   mc68328->regs.pedir = 0x00;
2579   mc68328->regs.pedata = 0x00;
2580   mc68328->regs.pepuen = 0x80;
2581   mc68328->regs.pesel = 0x80;
2582   mc68328->regs.pfdir = 0x00;
2583   mc68328->regs.pfdata = 0x00;
2584   mc68328->regs.pfpuen = 0xff;
2585   mc68328->regs.pfsel = 0xff;
2586   mc68328->regs.pgdir = 0x00;
2587   mc68328->regs.pgdata = 0x00;
2588   mc68328->regs.pgpuen = 0xff;
2589   mc68328->regs.pgsel = 0xff;
2590   mc68328->regs.pjdir = 0x00;
2591   mc68328->regs.pjdata = 0x00;
2592   mc68328->regs.pjsel = 0x00;
2593   mc68328->regs.pkdir = 0x00;
2594   mc68328->regs.pkdata = 0x00;
2595   mc68328->regs.pkpuen = 0xff;
2596   mc68328->regs.pksel = 0xff;
2597   mc68328->regs.pmdir = 0x00;
2598   mc68328->regs.pmdata = 0x00;
2599   mc68328->regs.pmpuen = 0xff;
2600   mc68328->regs.pmsel = 0xff;
2601
2602   mc68328->regs.pwmc = 0x0000;
2603   mc68328->regs.pwmp = 0x0000;
2604   mc68328->regs.pwmw = 0x0000;
2605   mc68328->regs.pwmcnt = 0x0000;
2606
2607   mc68328->regs.tctl[0] = mc68328->regs.tctl[1] = 0x0000;
2608   mc68328->regs.tprer[0] = mc68328->regs.tprer[1] = 0x0000;
2609   mc68328->regs.tcmp[0] = mc68328->regs.tcmp[1] = 0xffff;
2610   mc68328->regs.tcr[0] = mc68328->regs.tcr[1] = 0x0000;
2611   mc68328->regs.tcn[0] = mc68328->regs.tcn[1] = 0x0000;
2612   mc68328->regs.tstat[0] = mc68328->regs.tstat[1] = 0x0000;
2613   mc68328->regs.wctlr = 0x0000;
2614   mc68328->regs.wcmpr = 0xffff;
2615   mc68328->regs.wcn = 0x0000;
2616
2617   mc68328->regs.spisr = 0x0000;
2618
2619   mc68328->regs.spimdata = 0x0000;
2620   mc68328->regs.spimcont = 0x0000;
2621
2622   mc68328->regs.ustcnt = 0x0000;
2623   mc68328->regs.ubaud = 0x003f;
2624   mc68328->regs.urx = 0x0000;
2625   mc68328->regs.utx = 0x0000;
2626   mc68328->regs.umisc = 0x0000;
2627
2628   mc68328->regs.lssa = 0x00000000;
2629   mc68328->regs.lvpw = 0xff;
2630   mc68328->regs.lxmax = 0x03ff;
2631   mc68328->regs.lymax = 0x01ff;
2632   mc68328->regs.lcxp = 0x0000;
2633   mc68328->regs.lcyp = 0x0000;
2634   mc68328->regs.lcwch = 0x0101;
2635   mc68328->regs.lblkc = 0x7f;
2636   mc68328->regs.lpicf = 0x00;
2637   mc68328->regs.lpolcf = 0x00;
2638   mc68328->regs.lacdrc = 0x00;
2639   mc68328->regs.lpxcd = 0x00;
2640   mc68328->regs.lckcon = 0x40;
2641   mc68328->regs.llbar = 0x3e;
2642   mc68328->regs.lotcr = 0x3f;
2643   mc68328->regs.lposr = 0x00;
2644   mc68328->regs.lfrcm = 0xb9;
2645   mc68328->regs.lgpmr = 0x1073;
2646
2647   mc68328->regs.hmsr = 0x00000000;
2648   mc68328->regs.alarm = 0x00000000;
2649   mc68328->regs.rtcctl = 0x00;
2650   mc68328->regs.rtcisr = 0x00;
2651   mc68328->regs.rtcienr = 0x00;
2652   mc68328->regs.stpwtch = 0x00;
2653
2654   mc68328->rtc->adjust(attotime::from_hz(1), 0, attotime::from_hz(1));
2655}
2656
2657static void mc68328_register_state_save(device_t *device)
2658{
2659   mc68328_t* mc68328 = mc68328_get_safe_token( device );
2660
2661   state_save_register_global(device->machine(), mc68328->regs.scr);
2662   state_save_register_global(device->machine(), mc68328->regs.grpbasea);
2663   state_save_register_global(device->machine(), mc68328->regs.grpbaseb);
2664   state_save_register_global(device->machine(), mc68328->regs.grpbasec);
2665   state_save_register_global(device->machine(), mc68328->regs.grpbased);
2666   state_save_register_global(device->machine(), mc68328->regs.grpmaska);
2667   state_save_register_global(device->machine(), mc68328->regs.grpmaskb);
2668   state_save_register_global(device->machine(), mc68328->regs.grpmaskc);
2669   state_save_register_global(device->machine(), mc68328->regs.grpmaskd);
2670   state_save_register_global(device->machine(), mc68328->regs.csa0);
2671   state_save_register_global(device->machine(), mc68328->regs.csa1);
2672   state_save_register_global(device->machine(), mc68328->regs.csa2);
2673   state_save_register_global(device->machine(), mc68328->regs.csa3);
2674   state_save_register_global(device->machine(), mc68328->regs.csb0);
2675   state_save_register_global(device->machine(), mc68328->regs.csb1);
2676   state_save_register_global(device->machine(), mc68328->regs.csb2);
2677   state_save_register_global(device->machine(), mc68328->regs.csb3);
2678   state_save_register_global(device->machine(), mc68328->regs.csc0);
2679   state_save_register_global(device->machine(), mc68328->regs.csc1);
2680   state_save_register_global(device->machine(), mc68328->regs.csc2);
2681   state_save_register_global(device->machine(), mc68328->regs.csc3);
2682   state_save_register_global(device->machine(), mc68328->regs.csd0);
2683   state_save_register_global(device->machine(), mc68328->regs.csd1);
2684   state_save_register_global(device->machine(), mc68328->regs.csd2);
2685   state_save_register_global(device->machine(), mc68328->regs.csd3);
2686
2687   state_save_register_global(device->machine(), mc68328->regs.pllcr);
2688   state_save_register_global(device->machine(), mc68328->regs.pllfsr);
2689   state_save_register_global(device->machine(), mc68328->regs.pctlr);
2690
2691   state_save_register_global(device->machine(), mc68328->regs.ivr);
2692   state_save_register_global(device->machine(), mc68328->regs.icr);
2693   state_save_register_global(device->machine(), mc68328->regs.imr);
2694   state_save_register_global(device->machine(), mc68328->regs.iwr);
2695   state_save_register_global(device->machine(), mc68328->regs.isr);
2696   state_save_register_global(device->machine(), mc68328->regs.ipr);
2697
2698   state_save_register_global(device->machine(), mc68328->regs.padir);
2699   state_save_register_global(device->machine(), mc68328->regs.padata);
2700   state_save_register_global(device->machine(), mc68328->regs.pasel);
2701   state_save_register_global(device->machine(), mc68328->regs.pbdir);
2702   state_save_register_global(device->machine(), mc68328->regs.pbdata);
2703   state_save_register_global(device->machine(), mc68328->regs.pbsel);
2704   state_save_register_global(device->machine(), mc68328->regs.pcdir);
2705   state_save_register_global(device->machine(), mc68328->regs.pcdata);
2706   state_save_register_global(device->machine(), mc68328->regs.pcsel);
2707   state_save_register_global(device->machine(), mc68328->regs.pddir);
2708   state_save_register_global(device->machine(), mc68328->regs.pddata);
2709   state_save_register_global(device->machine(), mc68328->regs.pdpuen);
2710   state_save_register_global(device->machine(), mc68328->regs.pdpol);
2711   state_save_register_global(device->machine(), mc68328->regs.pdirqen);
2712   state_save_register_global(device->machine(), mc68328->regs.pddataedge);
2713   state_save_register_global(device->machine(), mc68328->regs.pdirqedge);
2714   state_save_register_global(device->machine(), mc68328->regs.pedir);
2715   state_save_register_global(device->machine(), mc68328->regs.pedata);
2716   state_save_register_global(device->machine(), mc68328->regs.pepuen);
2717   state_save_register_global(device->machine(), mc68328->regs.pesel);
2718   state_save_register_global(device->machine(), mc68328->regs.pfdir);
2719   state_save_register_global(device->machine(), mc68328->regs.pfdata);
2720   state_save_register_global(device->machine(), mc68328->regs.pfpuen);
2721   state_save_register_global(device->machine(), mc68328->regs.pfsel);
2722   state_save_register_global(device->machine(), mc68328->regs.pgdir);
2723   state_save_register_global(device->machine(), mc68328->regs.pgdata);
2724   state_save_register_global(device->machine(), mc68328->regs.pgpuen);
2725   state_save_register_global(device->machine(), mc68328->regs.pgsel);
2726   state_save_register_global(device->machine(), mc68328->regs.pjdir);
2727   state_save_register_global(device->machine(), mc68328->regs.pjdata);
2728   state_save_register_global(device->machine(), mc68328->regs.pjsel);
2729   state_save_register_global(device->machine(), mc68328->regs.pkdir);
2730   state_save_register_global(device->machine(), mc68328->regs.pkdata);
2731   state_save_register_global(device->machine(), mc68328->regs.pkpuen);
2732   state_save_register_global(device->machine(), mc68328->regs.pksel);
2733   state_save_register_global(device->machine(), mc68328->regs.pmdir);
2734   state_save_register_global(device->machine(), mc68328->regs.pmdata);
2735   state_save_register_global(device->machine(), mc68328->regs.pmpuen);
2736   state_save_register_global(device->machine(), mc68328->regs.pmsel);
2737
2738   state_save_register_global(device->machine(), mc68328->regs.pwmc);
2739   state_save_register_global(device->machine(), mc68328->regs.pwmp);
2740   state_save_register_global(device->machine(), mc68328->regs.pwmw);
2741   state_save_register_global(device->machine(), mc68328->regs.pwmcnt);
2742
2743   state_save_register_global(device->machine(), mc68328->regs.tctl[0]);
2744   state_save_register_global(device->machine(), mc68328->regs.tctl[1]);
2745   state_save_register_global(device->machine(), mc68328->regs.tprer[0]);
2746   state_save_register_global(device->machine(), mc68328->regs.tprer[1]);
2747   state_save_register_global(device->machine(), mc68328->regs.tcmp[0]);
2748   state_save_register_global(device->machine(), mc68328->regs.tcmp[1]);
2749   state_save_register_global(device->machine(), mc68328->regs.tcr[0]);
2750   state_save_register_global(device->machine(), mc68328->regs.tcr[1]);
2751   state_save_register_global(device->machine(), mc68328->regs.tcn[0]);
2752   state_save_register_global(device->machine(), mc68328->regs.tcn[1]);
2753   state_save_register_global(device->machine(), mc68328->regs.tstat[0]);
2754   state_save_register_global(device->machine(), mc68328->regs.tstat[1]);
2755   state_save_register_global(device->machine(), mc68328->regs.wctlr);
2756   state_save_register_global(device->machine(), mc68328->regs.wcmpr);
2757   state_save_register_global(device->machine(), mc68328->regs.wcn);
2758
2759   state_save_register_global(device->machine(), mc68328->regs.spisr);
2760
2761   state_save_register_global(device->machine(), mc68328->regs.spimdata);
2762   state_save_register_global(device->machine(), mc68328->regs.spimcont);
2763
2764   state_save_register_global(device->machine(), mc68328->regs.ustcnt);
2765   state_save_register_global(device->machine(), mc68328->regs.ubaud);
2766   state_save_register_global(device->machine(), mc68328->regs.urx);
2767   state_save_register_global(device->machine(), mc68328->regs.utx);
2768   state_save_register_global(device->machine(), mc68328->regs.umisc);
2769
2770   state_save_register_global(device->machine(), mc68328->regs.lssa);
2771   state_save_register_global(device->machine(), mc68328->regs.lvpw);
2772   state_save_register_global(device->machine(), mc68328->regs.lxmax);
2773   state_save_register_global(device->machine(), mc68328->regs.lymax);
2774   state_save_register_global(device->machine(), mc68328->regs.lcxp);
2775   state_save_register_global(device->machine(), mc68328->regs.lcyp);
2776   state_save_register_global(device->machine(), mc68328->regs.lcwch);
2777   state_save_register_global(device->machine(), mc68328->regs.lblkc);
2778   state_save_register_global(device->machine(), mc68328->regs.lpicf);
2779   state_save_register_global(device->machine(), mc68328->regs.lpolcf);
2780   state_save_register_global(device->machine(), mc68328->regs.lacdrc);
2781   state_save_register_global(device->machine(), mc68328->regs.lpxcd);
2782   state_save_register_global(device->machine(), mc68328->regs.lckcon);
2783   state_save_register_global(device->machine(), mc68328->regs.llbar);
2784   state_save_register_global(device->machine(), mc68328->regs.lotcr);
2785   state_save_register_global(device->machine(), mc68328->regs.lposr);
2786   state_save_register_global(device->machine(), mc68328->regs.lfrcm);
2787   state_save_register_global(device->machine(), mc68328->regs.lgpmr);
2788
2789   state_save_register_global(device->machine(), mc68328->regs.hmsr);
2790   state_save_register_global(device->machine(), mc68328->regs.alarm);
2791   state_save_register_global(device->machine(), mc68328->regs.rtcctl);
2792   state_save_register_global(device->machine(), mc68328->regs.rtcisr);
2793   state_save_register_global(device->machine(), mc68328->regs.rtcienr);
2794   state_save_register_global(device->machine(), mc68328->regs.stpwtch);
2795}
2796
2797static DEVICE_START( mc68328 )
2798{
2799   mc68328_t* mc68328 = mc68328_get_safe_token( device );
2800
2801   mc68328->iface = (const mc68328_interface*)device->static_config();
2802
2803   mc68328->out_port_a.resolve(mc68328->iface->out_port_a_func, *device);
2804   mc68328->out_port_b.resolve(mc68328->iface->out_port_b_func, *device);
2805   mc68328->out_port_c.resolve(mc68328->iface->out_port_c_func, *device);
2806   mc68328->out_port_d.resolve(mc68328->iface->out_port_d_func, *device);
2807   mc68328->out_port_e.resolve(mc68328->iface->out_port_e_func, *device);
2808   mc68328->out_port_f.resolve(mc68328->iface->out_port_f_func, *device);
2809   mc68328->out_port_g.resolve(mc68328->iface->out_port_g_func, *device);
2810   mc68328->out_port_j.resolve(mc68328->iface->out_port_j_func, *device);
2811   mc68328->out_port_k.resolve(mc68328->iface->out_port_k_func, *device);
2812   mc68328->out_port_m.resolve(mc68328->iface->out_port_m_func, *device);
2813
2814   mc68328->in_port_a.resolve(mc68328->iface->in_port_a_func, *device);
2815   mc68328->in_port_b.resolve(mc68328->iface->in_port_b_func, *device);
2816   mc68328->in_port_c.resolve(mc68328->iface->in_port_c_func, *device);
2817   mc68328->in_port_d.resolve(mc68328->iface->in_port_d_func, *device);
2818   mc68328->in_port_e.resolve(mc68328->iface->in_port_e_func, *device);
2819   mc68328->in_port_f.resolve(mc68328->iface->in_port_f_func, *device);
2820   mc68328->in_port_g.resolve(mc68328->iface->in_port_g_func, *device);
2821   mc68328->in_port_j.resolve(mc68328->iface->in_port_j_func, *device);
2822   mc68328->in_port_k.resolve(mc68328->iface->in_port_k_func, *device);
2823   mc68328->in_port_m.resolve(mc68328->iface->in_port_m_func, *device);
2824
2825   mc68328->out_pwm.resolve(mc68328->iface->out_pwm_func, *device);
2826
2827   mc68328->out_spim.resolve(mc68328->iface->out_spim_func, *device);
2828   mc68328->in_spim.resolve(mc68328->iface->in_spim_func, *device);
2829
2830   mc68328->gptimer[0] = device->machine().scheduler().timer_alloc(FUNC(mc68328_timer1_hit));
2831   mc68328->gptimer[1] = device->machine().scheduler().timer_alloc(FUNC(mc68328_timer2_hit));
2832   mc68328->rtc = device->machine().scheduler().timer_alloc(FUNC(mc68328_rtc_tick));
2833   mc68328->pwm = device->machine().scheduler().timer_alloc(FUNC(mc68328_pwm_transition));
2834
2835   mc68328_register_state_save(device);
2836}
2837
2838const device_type MC68328 = &device_creator<mc68328_device>;
2839
2840mc68328_device::mc68328_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
2841   : device_t(mconfig, MC68328, "Motorola MC68328 (DragonBall) Integrated Processor", tag, owner, clock)
2842{
2843   m_token = global_alloc_clear(mc68328_t);
2844}
2845
2846//-------------------------------------------------
2847//  device_config_complete - perform any
2848//  operations now that the configuration is
2849//  complete
2850//-------------------------------------------------
2851
2852void mc68328_device::device_config_complete()
2853{
2854}
2855
2856//-------------------------------------------------
2857//  device_start - device-specific startup
2858//-------------------------------------------------
2859
2860void mc68328_device::device_start()
2861{
2862   DEVICE_START_NAME( mc68328 )(this);
2863}
2864
2865//-------------------------------------------------
2866//  device_reset - device-specific reset
2867//-------------------------------------------------
2868
2869void mc68328_device::device_reset()
2870{
2871   DEVICE_RESET_NAME( mc68328 )(this);
2872}
trunk/src/mess/machine/mc68328.h
r21684r21685
1/**********************************************************************
2
3    Motorola 68328 ("DragonBall") System-on-a-Chip private data
4
5    By MooglyGuy
6    contact mooglyguy@gmail.com with licensing and usage questions.
7
8**********************************************************************/
9
10#ifndef __MC68328_PRIVATE_H_
11#define __MC68328_PRIVATE_H_
12
13struct mc68328_regs_t
14{
15   // $(FF)FFF000
16   UINT8   scr;        // System Control Register
17   UINT8   unused0[255];
18
19   // $(FF)FFF100
20   UINT16  grpbasea;   // Chip Select Group A Base Register
21   UINT16  grpbaseb;   // Chip Select Group B Base Register
22   UINT16  grpbasec;   // Chip Select Group C Base Register
23   UINT16  grpbased;   // Chip Select Group D Base Register
24   UINT16  grpmaska;   // Chip Select Group A Mask Register
25   UINT16  grpmaskb;   // Chip Select Group B Mask Register
26   UINT16  grpmaskc;   // Chip Select Group C Mask Register
27   UINT16  grpmaskd;   // Chip Select Group D Mask Register
28   UINT32  csa0;       // Group A Chip Select 0 Register
29   UINT32  csa1;       // Group A Chip Select 1 Register
30   UINT32  csa2;       // Group A Chip Select 2 Register
31   UINT32  csa3;       // Group A Chip Select 3 Register
32   UINT32  csb0;       // Group B Chip Select 0 Register
33   UINT32  csb1;       // Group B Chip Select 1 Register
34   UINT32  csb2;       // Group B Chip Select 2 Register
35   UINT32  csb3;       // Group B Chip Select 3 Register
36   UINT32  csc0;       // Group C Chip Select 0 Register
37   UINT32  csc1;       // Group C Chip Select 1 Register
38   UINT32  csc2;       // Group C Chip Select 2 Register
39   UINT32  csc3;       // Group C Chip Select 3 Register
40   UINT32  csd0;       // Group D Chip Select 0 Register
41   UINT32  csd1;       // Group D Chip Select 1 Register
42   UINT32  csd2;       // Group D Chip Select 2 Register
43   UINT32  csd3;       // Group D Chip Select 3 Register
44   UINT8   unused1[176];
45
46   // $(FF)FFF200
47   UINT16  pllcr;      // PLL Control Register
48   UINT16  pllfsr;     // PLL Frequency Select Register
49   UINT8   pad2[3];
50   UINT8   pctlr;      // Power Control Register
51   UINT8   unused3[248];
52
53   // $(FF)FFF300
54   UINT8   ivr;        // Interrupt Vector Register
55   UINT8   unused4[1];
56   UINT16  icr;        // Interrupt Control Register
57   UINT32  imr;        // Interrupt Mask Register
58   UINT32  iwr;        // Interrupt Wakeup Enable Register
59   UINT32  isr;        // Interrupt Status Register
60   UINT32  ipr;        // Interrupt Pending Register
61   UINT8   unused5[236];
62
63   // $(FF)FFF400
64   UINT8   padir;      // Port A Direction Register
65   UINT8   padata;     // Port A Data Register
66   UINT8   unused6[1];
67   UINT8   pasel;      // Port A Select Register
68   UINT8   unused7[4];
69
70   UINT8   pbdir;      // Port B Direction Register
71   UINT8   pbdata;     // Port B Data Register
72   UINT8   unused8[1];
73   UINT8   pbsel;      // Port B Select Register
74   UINT8   unused9[4];
75
76   UINT8   pcdir;      // Port C Direction Register
77   UINT8   pcdata;     // Port C Data Register
78   UINT8   unused10[1];
79   UINT8   pcsel;      // Port C Select Register
80   UINT8   unused11[4];
81
82   UINT8   pddir;      // Port D Direction Register
83   UINT8   pddata;     // Port D Data Register
84   UINT8   pdpuen;     // Port D Pullup Enable Register
85   UINT8   unused12[1];
86   UINT8   pdpol;      // Port D Polarity Register
87   UINT8   pdirqen;    // Port D IRQ Enable Register
88   UINT8   pddataedge; // Port D Data Edge Level
89   UINT8   pdirqedge;  // Port D IRQ Edge Register
90
91   UINT8   pedir;      // Port E Direction Register
92   UINT8   pedata;     // Port E Data Register
93   UINT8   pepuen;     // Port E Pullup Enable Register
94   UINT8   pesel;      // Port E Select Register
95   UINT8   unused14[4];
96
97   UINT8   pfdir;      // Port F Direction Register
98   UINT8   pfdata;     // Port F Data Register
99   UINT8   pfpuen;     // Port F Pullup Enable Register
100   UINT8   pfsel;      // Port F Select Register
101   UINT8   unused15[4];
102
103   UINT8   pgdir;      // Port G Direction Register
104   UINT8   pgdata;     // Port G Data Register
105   UINT8   pgpuen;     // Port G Pullup Enable Register
106   UINT8   pgsel;      // Port G Select Register
107   UINT8   unused16[4];
108
109   UINT8   pjdir;      // Port J Direction Register
110   UINT8   pjdata;     // Port J Data Register
111   UINT8   unused17[1];
112   UINT8   pjsel;      // Port J Select Register
113   UINT8   unused18[4];
114   UINT8   pkdir;      // Port K Direction Register
115   UINT8   pkdata;     // Port K Data Register
116   UINT8   pkpuen;     // Port K Pullup Enable Register
117   UINT8   pksel;      // Port K Select Register
118   UINT8   unused19[4];
119
120   UINT8   pmdir;      // Port M Direction Register
121   UINT8   pmdata;     // Port M Data Register
122   UINT8   pmpuen;     // Port M Pullup Enable Register
123   UINT8   pmsel;      // Port M Select Register
124   UINT8   unused20[180];
125
126   // $(FF)FFF500
127   UINT16  pwmc;       // PWM Control Register
128   UINT16  pwmp;       // PWM Period Register
129   UINT16  pwmw;       // PWM Width Register
130   UINT16  pwmcnt;     // PWN Counter
131   UINT8   unused21[248];
132
133   // $(FF)FFF600
134   UINT16  tctl[2];    // Timer Control Register
135   UINT16  tprer[2];   // Timer Prescaler Register
136   UINT16  tcmp[2];    // Timer Compare Register
137   UINT16  tcr[2];     // Timer Capture Register
138   UINT16  tcn[2];     // Timer Counter
139   UINT16  tstat[2];   // Timer Status
140   UINT16  wctlr;      // Watchdog Control Register
141   UINT16  wcmpr;      // Watchdog Compare Register
142   UINT16  wcn;        // Watchdog Counter
143   UINT8   tclear[2];  // Timer Clearable Status
144   UINT8   unused22[224];
145
146   // $(FF)FFF700
147   UINT16  spisr;      // SPIS Register
148   UINT8   unused23[254];
149
150   // $(FF)FFF800
151   UINT16  spimdata;   // SPIM Data Register
152   UINT16  spimcont;   // SPIM Control/Status Register
153   UINT8   unused24[252];
154
155   // $(FF)FFF900
156   UINT16  ustcnt;     // UART Status/Control Register
157   UINT16  ubaud;      // UART Baud Control Register
158   UINT16  urx;        // UART RX Register
159   UINT16  utx;        // UART TX Register
160   UINT16  umisc;      // UART Misc Register
161   UINT8   unused25[246];
162
163   // $(FF)FFFA00
164   UINT32  lssa;       // Screen Starting Address Register
165   UINT8   unused26[1];
166   UINT8   lvpw;       // Virtual Page Width Register
167   UINT8   unused27[2];
168   UINT16  lxmax;      // Screen Width Register
169   UINT16  lymax;      // Screen Height Register
170   UINT8   unused28[12];
171   UINT16  lcxp;       // Cursor X Position
172   UINT16  lcyp;       // Cursor Y Position
173   UINT16  lcwch;      // Cursor Width & Height Register
174   UINT8   unused29[1];
175   UINT8   lblkc;      // Blink Control Register
176   UINT8   lpicf;      // Panel Interface Config Register
177   UINT8   lpolcf;     // Polarity Config Register
178   UINT8   unused30[1];
179   UINT8   lacdrc;     // ACD (M) Rate Control Register
180   UINT8   unused31[1];
181   UINT8   lpxcd;      // Pixel Clock Divider Register
182   UINT8   unused32[1];
183   UINT8   lckcon;     // Clocking Control Register
184   UINT8   unused33[1];
185   UINT8   llbar;      // Last Buffer Address Register
186   UINT8   unused34[1];
187   UINT8   lotcr;      // Octet Terminal Count Register
188   UINT8   unused35[1];
189   UINT8   lposr;      // Panning Offset Register
190   UINT8   unused36[3];
191   UINT8   lfrcm;      // Frame Rate Control Modulation Register
192   UINT16  lgpmr;      // Gray Palette Mapping Register
193   UINT8   unused37[204];
194
195   // $(FF)FFFB00
196   UINT32  hmsr;       // RTC Hours Minutes Seconds Register
197   UINT32  alarm;      // RTC Alarm Register
198   UINT8   unused38[4];
199   UINT16  rtcctl;     // RTC Control Register
200   UINT16  rtcisr;     // RTC Interrupt Status Register
201   UINT16  rtcienr;    // RTC Interrupt Enable Register
202   UINT16  stpwtch;    // Stopwatch Minutes
203   UINT8   unused42[1260];
204};
205
206struct mc68328_t
207{
208   const mc68328_interface* iface;
209
210   mc68328_regs_t regs;
211
212   emu_timer *gptimer[2];
213   emu_timer *rtc;
214   emu_timer *pwm;
215
216   devcb_resolved_write8  out_port_a;    /* 8-bit output */
217   devcb_resolved_write8  out_port_b;    /* 8-bit output */
218   devcb_resolved_write8  out_port_c;    /* 8-bit output */
219   devcb_resolved_write8  out_port_d;    /* 8-bit output */
220   devcb_resolved_write8  out_port_e;    /* 8-bit output */
221   devcb_resolved_write8  out_port_f;    /* 8-bit output */
222   devcb_resolved_write8  out_port_g;    /* 8-bit output */
223   devcb_resolved_write8  out_port_j;    /* 8-bit output */
224   devcb_resolved_write8  out_port_k;    /* 8-bit output */
225   devcb_resolved_write8  out_port_m;    /* 8-bit output */
226
227   devcb_resolved_read8   in_port_a;     /* 8-bit input */
228   devcb_resolved_read8   in_port_b;     /* 8-bit input */
229   devcb_resolved_read8   in_port_c;     /* 8-bit input */
230   devcb_resolved_read8   in_port_d;     /* 8-bit input */
231   devcb_resolved_read8   in_port_e;     /* 8-bit input */
232   devcb_resolved_read8   in_port_f;     /* 8-bit input */
233   devcb_resolved_read8   in_port_g;     /* 8-bit input */
234   devcb_resolved_read8   in_port_j;     /* 8-bit input */
235   devcb_resolved_read8   in_port_k;     /* 8-bit input */
236   devcb_resolved_read8   in_port_m;     /* 8-bit input */
237
238   devcb_resolved_write8  out_pwm;       /* 1-bit output */
239
240   devcb_resolved_write16 out_spim;      /* 16-bit output */
241   devcb_resolved_read16  in_spim;       /* 16-bit input */
242};
243
244#define SCR_BETO                0x80
245#define SCR_WPV                 0x40
246#define SCR_PRV                 0x20
247#define SCR_BETEN               0x10
248#define SCR_SO                  0x08
249#define SCR_DMAP                0x04
250#define SCR_WDTH8               0x01
251
252#define ICR_POL6                0x0100
253#define ICR_POL3                0x0200
254#define ICR_POL2                0x0400
255#define ICR_POL1                0x0800
256#define ICR_ET6                 0x1000
257#define ICR_ET3                 0x2000
258#define ICR_ET2                 0x4000
259#define ICR_ET1                 0x8000
260
261#define INT_SPIM                0x000001
262#define INT_TIMER2              0x000002
263#define INT_UART                0x000004
264#define INT_WDT                 0x000008
265#define INT_RTC                 0x000010
266#define INT_RESERVED            0x000020
267#define INT_KB                  0x000040
268#define INT_PWM                 0x000080
269#define INT_INT0                0x000100
270#define INT_INT1                0x000200
271#define INT_INT2                0x000400
272#define INT_INT3                0x000800
273#define INT_INT4                0x001000
274#define INT_INT5                0x002000
275#define INT_INT6                0x004000
276#define INT_INT7                0x008000
277#define INT_KBDINTS             0x00ff00
278#define INT_IRQ1                0x010000
279#define INT_IRQ2                0x020000
280#define INT_IRQ3                0x040000
281#define INT_IRQ6                0x080000
282#define INT_PEN                 0x100000
283#define INT_SPIS                0x200000
284#define INT_TIMER1              0x400000
285#define INT_IRQ7                0x800000
286
287#define INT_M68K_LINE1          (INT_IRQ1)
288#define INT_M68K_LINE2          (INT_IRQ2)
289#define INT_M68K_LINE3          (INT_IRQ3)
290#define INT_M68K_LINE4          (INT_INT0 | INT_INT1 | INT_INT2 | INT_INT3 | INT_INT4 | INT_INT5 | INT_INT6 | INT_INT7 | \
291                           INT_PWM | INT_KB | INT_RTC | INT_WDT | INT_UART | INT_TIMER2 | INT_SPIM)
292#define INT_M68K_LINE5          (INT_PEN)
293#define INT_M68K_LINE6          (INT_IRQ6 | INT_TIMER1 | INT_SPIS)
294#define INT_M68K_LINE7          (INT_IRQ7)
295#define INT_M68K_LINE67         (INT_M68K_LINE6 | INT_M68K_LINE7)
296#define INT_M68K_LINE567        (INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7)
297#define INT_M68K_LINE4567       (INT_M68K_LINE4 | INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7)
298#define INT_M68K_LINE34567      (INT_M68K_LINE3 | INT_M68K_LINE4 | INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7)
299#define INT_M68K_LINE234567     (INT_M68K_LINE2 | INT_M68K_LINE3 | INT_M68K_LINE4 | INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7)
300
301#define INT_IRQ1_SHIFT          0x000001
302#define INT_IRQ2_SHIFT          0x000002
303#define INT_IRQ3_SHIFT          0x000004
304#define INT_IRQ6_SHIFT          0x000008
305#define INT_PEN_SHIFT           0x000010
306#define INT_SPIS_SHIFT          0x000020
307#define INT_TIMER1_SHIFT        0x000040
308#define INT_IRQ7_SHIFT          0x000080
309
310#define INT_ACTIVE              1
311#define INT_INACTIVE            0
312
313#define GRPBASE_BASE_ADDR       0xfff0
314#define GRPBASE_VALID           0x0001
315
316#define GRPMASK_BASE_MASK       0xfff0
317
318#define CSAB_COMPARE            0xff000000
319#define CSAB_BSW                0x00010000
320#define CSAB_MASK               0x0000ff00
321#define CSAB_RO                 0x00000008
322#define CSAB_WAIT               0x00000007
323
324#define CSCD_COMPARE            0xfff00000
325#define CSCD_BSW                0x00010000
326#define CSCD_MASK               0x0000fff0
327#define CSCD_RO                 0x00000008
328#define CSCD_WAIT               0x00000007
329
330#define PLLCR_PIXCLK_SEL        0x3800
331#define PLLCR_PIXCLK_SEL_DIV2       0x0000
332#define PLLCR_PIXCLK_SEL_DIV4       0x0800
333#define PLLCR_PIXCLK_SEL_DIV8       0x1000
334#define PLLCR_PIXCLK_SEL_DIV16      0x1800
335#define PLLCR_PIXCLK_SEL_DIV1_0     0x2000
336#define PLLCR_PIXCLK_SEL_DIV1_1     0x2800
337#define PLLCR_PIXCLK_SEL_DIV1_2     0x3000
338#define PLLCR_PIXCLK_SEL_DIV1_3     0x3800
339#define PLLCR_SYSCLK_SEL        0x0700
340#define PLLCR_SYSCLK_SEL_DIV2       0x0000
341#define PLLCR_SYSCLK_SEL_DIV4       0x0100
342#define PLLCR_SYSCLK_SEL_DIV8       0x0200
343#define PLLCR_SYSCLK_SEL_DIV16      0x0300
344#define PLLCR_SYSCLK_SEL_DIV1_0     0x0400
345#define PLLCR_SYSCLK_SEL_DIV1_1     0x0500
346#define PLLCR_SYSCLK_SEL_DIV1_2     0x0600
347#define PLLCR_SYSCLK_SEL_DIV1_3     0x0700
348#define PLLCR_CLKEN             0x0010
349#define PLLCR_DISPLL            0x0008
350
351#define PLLFSR_CLK32            0x8000
352#define PLLFSR_PROT             0x4000
353#define PLLFSR_QCNT             0x0f00
354#define PLLFSR_PCNT             0x00ff
355
356#define PCTLR_PC_EN             0x80
357#define PCTLR_STOP              0x40
358#define PCTLR_WIDTH             0x1f
359
360#define CXP_CC                  0xc000
361#define CXP_CC_XLU                  0x0000
362#define CXP_CC_BLACK                0x4000
363#define CXP_CC_INVERSE              0x8000
364#define CXP_CC_INVALID              0xc000
365#define CXP_MASK                0x03ff
366
367#define CYP_MASK                0x01ff
368
369#define CWCH_CW                 0x1f00
370#define CWCH_CH                 0x001f
371
372#define BLKC_BKEN               0x80
373#define BLKC_BD                 0x7f
374
375#define LPICF_PBSIZ             0x06
376#define LPICF_PBSIZ_1               0x00
377#define LPICF_PBSIZ_2               0x02
378#define LPICF_PBSIZ_4               0x04
379#define LPICF_PBSIZ_INVALID         0x06
380
381#define LPOLCF_LCKPOL           0x08
382#define LPOLCF_FLMPOL           0x04
383#define LPOLCF_LPPOL            0x02
384#define LPOLCF_PIXPOL           0x01
385
386#define LACDRC_MASK             0x0f
387
388#define LPXCD_MASK              0x3f
389
390#define LCKCON_LCDC_EN          0x80
391#define LCKCON_LCDON            0x80
392#define LCKCON_DMA16            0x40
393#define LCKCON_WS               0x30
394#define LCKCON_WS_1                 0x00
395#define LCKCON_WS_2                 0x10
396#define LCKCON_WS_3                 0x20
397#define LCKCON_WS_4                 0x30
398#define LCKCON_DWIDTH           0x02
399#define LCKCON_PCDS             0x01
400
401#define LBAR_MASK               0x7f
402
403#define LPOSR_BOS               0x08
404#define LPOSR_POS               0x07
405
406#define LFRCM_XMOD              0xf0
407#define LFRCM_YMOD              0x0f
408
409#define LGPMR_PAL1              0x7000
410#define LGPMR_PAL0              0x0700
411#define LGPMR_PAL3              0x0070
412#define LGPMR_PAL2              0x0007
413
414#define RTCHMSR_HOURS           0x1f000000
415#define RTCHMSR_MINUTES         0x003f0000
416#define RTCHMSR_SECONDS         0x0000003f
417
418#define RTCCTL_38_4             0x0020
419#define RTCCTL_ENABLE           0x0080
420
421#define RTCINT_STOPWATCH        0x0001
422#define RTCINT_MINUTE           0x0002
423#define RTCINT_ALARM            0x0004
424#define RTCINT_DAY              0x0008
425#define RTCINT_SECOND           0x0010
426
427#define RTCSTPWTCH_MASK         0x003f
428
429#define TCTL_TEN                0x0001
430#define TCTL_TEN_ENABLE             0x0001
431#define TCTL_CLKSOURCE          0x000e
432#define TCTL_CLKSOURCE_STOP         0x0000
433#define TCTL_CLKSOURCE_SYSCLK       0x0002
434#define TCTL_CLKSOURCE_SYSCLK16     0x0004
435#define TCTL_CLKSOURCE_TIN          0x0006
436#define TCTL_CLKSOURCE_32KHZ4       0x0008
437#define TCTL_CLKSOURCE_32KHZ5       0x000a
438#define TCTL_CLKSOURCE_32KHZ6       0x000c
439#define TCTL_CLKSOURCE_32KHZ7       0x000e
440#define TCTL_IRQEN              0x0010
441#define TCTL_IRQEN_ENABLE           0x0010
442#define TCTL_OM                 0x0020
443#define TCTL_OM_ACTIVELOW           0x0000
444#define TCTL_OM_TOGGLE              0x0020
445#define TCTL_CAPTURE            0x00c0
446#define TCTL_CAPTURE_NOINT          0x0000
447#define TCTL_CAPTURE_RISING         0x0040
448#define TCTL_CAPTURE_FALLING        0x0080
449#define TCTL_CAPTURE_BOTH           0x00c0
450#define TCTL_FRR                0x0100
451#define TCTL_FRR_RESTART            0x0000
452#define TCTL_FRR_FREERUN            0x0100
453
454#define TSTAT_COMP              0x0001
455#define TSTAT_CAPT              0x0002
456
457#define WCTLR_WDRST             0x0008
458#define WCTLR_LOCK              0x0004
459#define WCTLR_FI                0x0002
460#define WCTLR_WDEN              0x0001
461
462#define USTCNT_UART_EN          0x8000
463#define USTCNT_RX_EN            0x4000
464#define USTCNT_TX_EN            0x2000
465#define USTCNT_RX_CLK_CONT      0x1000
466#define USTCNT_PARITY_EN        0x0800
467#define USTCNT_ODD_EVEN         0x0400
468#define USTCNT_STOP_BITS        0x0200
469#define USTCNT_8_7              0x0100
470#define USTCNT_GPIO_DELTA_EN    0x0080
471#define USTCNT_CTS_DELTA_EN     0x0040
472#define USTCNT_RX_FULL_EN       0x0020
473#define USTCNT_RX_HALF_EN       0x0010
474#define USTCNT_RX_RDY_EN        0x0008
475#define USTCNT_TX_EMPTY_EN      0x0004
476#define USTCNT_TX_HALF_EN       0x0002
477#define USTCNT_TX_AVAIL_EN      0x0001
478
479#define UBAUD_GPIO_DELTA        0x8000
480#define UBAUD_GPIO              0x4000
481#define UBAUD_GPIO_DIR          0x2000
482#define UBAUD_GPIO_SRC          0x1000
483#define UBAUD_BAUD_SRC          0x0800
484#define UBAUD_DIVIDE            0x0700
485#define UBAUD_DIVIDE_1              0x0000
486#define UBAUD_DIVIDE_2              0x0100
487#define UBAUD_DIVIDE_4              0x0200
488#define UBAUD_DIVIDE_8              0x0300
489#define UBAUD_DIVIDE_16             0x0400
490#define UBAUD_DIVIDE_32             0x0500
491#define UBAUD_DIVIDE_64             0x0600
492#define UBAUD_DIVIDE_128            0x0700
493#define UBAUD_PRESCALER         0x00ff
494
495#define URX_FIFO_FULL           0x8000
496#define URX_FIFO_HALF           0x4000
497#define URX_DATA_READY          0x2000
498#define URX_OVRUN               0x0800
499#define URX_FRAME_ERROR         0x0400
500#define URX_BREAK               0x0200
501#define URX_PARITY_ERROR        0x0100
502
503#define UTX_FIFO_EMPTY          0x8000
504#define UTX_FIFO_HALF           0x4000
505#define UTX_TX_AVAIL            0x2000
506#define UTX_SEND_BREAK          0x1000
507#define UTX_IGNORE_CTS          0x0800
508#define UTX_CTS_STATUS          0x0200
509#define UTX_CTS_DELTA           0x0100
510
511#define UMISC_CLK_SRC           0x4000
512#define UMISC_FORCE_PERR        0x2000
513#define UMISC_LOOP              0x1000
514#define UMISC_RTS_CONT          0x0080
515#define UMISC_RTS               0x0040
516#define UMISC_IRDA_ENABLE       0x0020
517#define UMISC_IRDA_LOOP         0x0010
518
519#define SPIS_SPIS_IRQ           0x8000
520#define SPIS_IRQEN              0x4000
521#define SPIS_ENPOL              0x2000
522#define SPIS_DATA_RDY           0x1000
523#define SPIS_OVRWR              0x0800
524#define SPIS_PHA                0x0400
525#define SPIS_POL                0x0200
526#define SPIS_SPISEN             0x0100
527
528#define SPIM_CLOCK_COUNT        0x000f
529#define SPIM_POL                0x0010
530#define SPIM_POL_HIGH               0x0000
531#define SPIM_POL_LOW                0x0010
532#define SPIM_PHA                0x0020
533#define SPIM_PHA_NORMAL             0x0000
534#define SPIM_PHA_OPPOSITE           0x0020
535#define SPIM_IRQEN              0x0040
536#define SPIM_SPIMIRQ            0x0080
537#define SPIM_XCH                0x0100
538#define SPIM_XCH_IDLE               0x0000
539#define SPIM_XCH_INIT               0x0100
540#define SPIM_SPMEN              0x0200
541#define SPIM_SPMEN_DISABLE          0x0000
542#define SPIM_SPMEN_ENABLE           0x0200
543#define SPIM_RATE               0xe000
544#define SPIM_RATE_4                 0x0000
545#define SPIM_RATE_8                 0x2000
546#define SPIM_RATE_16                0x4000
547#define SPIM_RATE_32                0x6000
548#define SPIM_RATE_64                0x8000
549#define SPIM_RATE_128               0xa000
550#define SPIM_RATE_256               0xc000
551#define SPIM_RATE_512               0xe000
552
553#define PWMC_PWMIRQ             0x8000
554#define PWMC_IRQEN              0x4000
555#define PWMC_LOAD               0x0100
556#define PWMC_PIN                0x0080
557#define PWMC_POL                0x0040
558#define PWMC_PWMEN              0x0010
559#define PWMC_CLKSEL             0x0007
560
561INLINE mc68328_t* mc68328_get_safe_token( device_t *device )
562{
563   assert( device != NULL );
564   assert( device->type() == MC68328 );
565   return (mc68328_t*) downcast<mc68328_device *>(device)->token();
566}
567
568#endif // __MC68328_PRIVATE_H_
trunk/src/mess/machine/at45dbxx.c
r21684r21685
1/*
2
3    Atmel Serial DataFlash
4
5    (c) 2001-2007 Tim Schuerewegen
6
7    AT45DB041 -  528 KByte
8    AT45DB081 - 1056 KByte
9    AT45DB161 - 2112 KByte
10
11*/
12
13#include "at45dbxx.h"
14
15#define LOG_LEVEL  1
16#define _logerror(level,x)  do { if (LOG_LEVEL > level) logerror x; } while (0)
17
18#define FLASH_CMD_52  0x52
19#define FLASH_CMD_57  0x57
20#define FLASH_CMD_60  0x60
21#define FLASH_CMD_82  0x82
22
23#define FLASH_MODE_XX  0 // unknown
24#define FLASH_MODE_SI  1 // input
25#define FLASH_MODE_SO  2 // output
26
27
28//**************************************************************************
29//  GLOBAL VARIABLES
30//**************************************************************************
31
32// device type definition
33const device_type AT45DB041 = &device_creator<at45db041_device>;
34const device_type AT45DB081 = &device_creator<at45db081_device>;
35const device_type AT45DB161 = &device_creator<at45db161_device>;
36
37
38//**************************************************************************
39//  LIVE DEVICE
40//**************************************************************************
41
42//-------------------------------------------------
43//  at45db041_device - constructor
44//-------------------------------------------------
45
46at45db041_device::at45db041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
47   : device_t(mconfig, AT45DB041, "AT45DB041", tag, owner, clock),
48   device_nvram_interface(mconfig, *this)
49{
50}
51
52
53at45db041_device::at45db041_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
54   : device_t(mconfig, type, name, tag, owner, clock),
55   device_nvram_interface(mconfig, *this)
56{
57}
58
59
60at45db081_device::at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
61   : at45db041_device(mconfig, AT45DB081, "AT45DB081", tag, owner, clock)
62{
63}
64
65
66at45db161_device::at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
67   : at45db041_device(mconfig, AT45DB161, "AT45DB161", tag, owner, clock)
68{
69}
70
71
72//-------------------------------------------------
73//  device_start - device-specific startup
74//-------------------------------------------------
75
76void at45db041_device::device_start()
77{
78   m_size = num_pages() * page_size();
79   m_data = auto_alloc_array(machine(), UINT8, m_size);
80   m_buffer1 = auto_alloc_array(machine(), UINT8, page_size());
81   m_buffer2 = auto_alloc_array(machine(), UINT8, page_size());
82
83   // data
84   save_pointer(NAME(m_data), m_size);
85   // pins
86   save_item(NAME(m_pin.cs));
87   save_item(NAME(m_pin.sck));
88   save_item(NAME(m_pin.si));
89   save_item(NAME(m_pin.so));
90   save_item(NAME(m_pin.wp));
91   save_item(NAME(m_pin.reset));
92   save_item(NAME(m_pin.busy));
93}
94
95
96//-------------------------------------------------
97//  device_reset - device-specific reset
98//-------------------------------------------------
99
100void at45db041_device::device_reset()
101{
102   _logerror( 1, ("at45dbxx_reset\n"));
103   // mode
104   m_mode = FLASH_MODE_SI;
105   // command
106   memset(&m_cmd.data[0], 0, sizeof(m_cmd.data));
107   m_cmd.size = 0;
108   // input/output
109   m_io.data = NULL;
110   m_io.size = 0;
111   m_io.pos  = 0;
112   // pins
113   m_pin.cs    = 0;
114   m_pin.sck   = 0;
115   m_pin.si    = 0;
116   m_pin.so    = 0;
117   m_pin.wp    = 0;
118   m_pin.reset = 0;
119   m_pin.busy  = 0;
120   // output
121   m_so_byte = 0;
122   m_so_bits = 0;
123   // input
124   m_si_byte = 0;
125   m_si_bits = 0;
126}
127
128
129//-------------------------------------------------
130//  nvram_default - called to initialize NVRAM to
131//  its default state
132//-------------------------------------------------
133
134void at45db041_device::nvram_default()
135{
136   memset(m_data, 0xff, m_size);
137
138   if (region() != NULL)
139   {
140      UINT32 bytes = region()->bytes();
141      if (bytes > m_size)
142         bytes = m_size;
143
144      memcpy(m_data, region()->base(), bytes);
145   }
146}
147
148//-------------------------------------------------
149//  nvram_read - called to read NVRAM from the
150//  .nv file
151//-------------------------------------------------
152
153void at45db041_device::nvram_read(emu_file &file)
154{
155   file.read(m_data, m_size);
156}
157
158//-------------------------------------------------
159//  nvram_write - called to write NVRAM to the
160//  .nv file
161//-------------------------------------------------
162
163void at45db041_device::nvram_write(emu_file &file)
164{
165   file.write(m_data, m_size);
166}
167
168UINT8 at45db041_device::read_byte()
169{
170   UINT8 data;
171   // check mode
172   if ((m_mode != FLASH_MODE_SO) || (!m_io.data)) return 0;
173   // read byte
174   data = m_io.data[m_io.pos++];
175   _logerror( 2, ("at45dbxx_read_byte (%02X) (%03d/%03d)\n", data, m_io.pos, m_io.size));
176   if (m_io.pos == m_io.size) m_io.pos = 0;
177   return data;
178}
179
180void at45db041_device::flash_set_io(UINT8* data, UINT32 size, UINT32 pos)
181{
182   m_io.data = data;
183   m_io.size = size;
184   m_io.pos  = pos;
185}
186
187UINT32 at45db041_device::flash_get_page_addr()
188{
189   return ((m_cmd.data[1] & 0x0F) << 7) | ((m_cmd.data[2] & 0xFE) >> 1);
190}
191
192UINT32 at45db041_device::flash_get_byte_addr()
193{
194   return ((m_cmd.data[2] & 0x01) << 8) | ((m_cmd.data[3] & 0xFF) >> 0);
195}
196
197UINT32 at45db081_device::flash_get_page_addr()
198{
199   return ((m_cmd.data[1] & 0x1F) << 7) | ((m_cmd.data[2] & 0xFE) >> 1);
200}
201
202UINT32 at45db161_device::flash_get_page_addr()
203{
204   return ((m_cmd.data[1] & 0x3F) << 6) | ((m_cmd.data[2] & 0xFC) >> 2);
205}
206
207UINT32 at45db161_device::flash_get_byte_addr()
208{
209   return ((m_cmd.data[2] & 0x03) << 8) | ((m_cmd.data[3] & 0xFF) >> 0);
210}
211
212void at45db041_device::write_byte(UINT8 data)
213{
214   // check mode
215   if (m_mode != FLASH_MODE_SI) return;
216   // process byte
217   if (m_cmd.size < 8)
218   {
219      UINT8 opcode;
220      _logerror( 2, ("at45dbxx_write_byte (%02X)\n", data));
221      // add to command buffer
222      m_cmd.data[m_cmd.size++] = data;
223      // check opcode
224      opcode = m_cmd.data[0];
225      switch (opcode)
226      {
227         // status register read
228         case FLASH_CMD_57 :
229         {
230            // 8 bits command
231            if (m_cmd.size == 1)
232            {
233               _logerror( 1, ("at45dbxx opcode %02X - status register read\n", opcode));
234               m_status = (m_status & 0xC7) | device_id(); // 80 = busy / 40 = compare fail
235               flash_set_io(&m_status, 1, 0);
236               m_mode = FLASH_MODE_SO;
237               m_cmd.size = 8;
238            }
239         }
240         break;
241         // main memory page to buffer 1 compare
242         case FLASH_CMD_60 :
243         {
244            // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits don't care
245            if (m_cmd.size == 4)
246            {
247               UINT32 page;
248               UINT8 comp;
249               page = flash_get_page_addr();
250               _logerror( 1, ("at45dbxx opcode %02X - main memory page to buffer 1 compare [%04X]\n", opcode, page));
251               comp = memcmp( m_data + page * page_size(), m_buffer1, page_size()) == 0 ? 0 : 1;
252               if (comp) m_status |= 0x40; else m_status &= ~0x40;
253               _logerror( 1, ("at45dbxx page compare %s\n", comp ? "failure" : "success"));
254               m_mode = FLASH_MODE_SI;
255               m_cmd.size = 8;
256            }
257         }
258         break;
259         // main memory page read
260         case FLASH_CMD_52 :
261         {
262            // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address + 32 bits don't care
263            if (m_cmd.size == 8)
264            {
265               UINT32 page, byte;
266               page = flash_get_page_addr();
267               byte = flash_get_byte_addr();
268               _logerror( 1, ("at45dbxx opcode %02X - main memory page read [%04X/%04X]\n", opcode, page, byte));
269               flash_set_io(m_data + page * page_size(), page_size(), byte);
270               m_mode = FLASH_MODE_SO;
271               m_cmd.size = 8;
272            }
273         }
274         break;
275         // main memory page program through buffer 1
276         case FLASH_CMD_82 :
277         {
278            // 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address
279            if (m_cmd.size == 4)
280            {
281               UINT32 page, byte;
282               page = flash_get_page_addr();
283               byte = flash_get_byte_addr();
284               _logerror( 1, ("at45dbxx opcode %02X - main memory page program through buffer 1 [%04X/%04X]\n",opcode, page, byte));
285               flash_set_io(m_buffer1, page_size(), byte);
286               memset( m_buffer1, 0xFF, page_size());
287               m_mode = FLASH_MODE_SI;
288               m_cmd.size = 8;
289            }
290         }
291         break;
292         // other
293         default :
294         {
295            _logerror( 1, ("at45dbxx opcode %02X - unknown\n", opcode));
296            m_cmd.data[0] = 0;
297            m_cmd.size = 0;
298         }
299         break;
300      }
301   }
302   else
303   {
304      _logerror( 2, ("at45dbxx_write_byte (%02X) (%03d/%03d)\n", data, m_io.pos + 1, m_io.size));
305      // store byte
306      m_io.data[m_io.pos] = data;
307      m_io.pos++;
308      if (m_io.pos == m_io.size) m_io.pos = 0;
309   }
310}
311
312READ_LINE_MEMBER(at45db041_device::so_r)
313{
314   if (m_pin.cs == 0) return 0;
315   return m_pin.so;
316}
317
318WRITE_LINE_MEMBER(at45db041_device::si_w)
319{
320   if (m_pin.cs == 0) return;
321   m_pin.si = state;
322}
323
324WRITE_LINE_MEMBER(at45db041_device::cs_w)
325{
326   // check if changed
327   if (m_pin.cs == state) return;
328   // cs low-to-high
329   if (state != 0)
330   {
331      // complete program command
332      if ((m_cmd.size >= 4) && (m_cmd.data[0] == FLASH_CMD_82))
333      {
334         UINT32 page, byte;
335         page = flash_get_page_addr();
336         byte = flash_get_byte_addr();
337         _logerror( 1, ("at45dbxx - program data stored in buffer 1 into selected page in main memory [%04X/%04X]\n", page, byte));
338         memcpy( m_data + page * page_size(), m_buffer1, page_size());
339      }
340      // reset
341      at45db041_device::device_reset();
342   }
343   // save cs
344   m_pin.cs = state;
345}
346
347WRITE_LINE_MEMBER(at45db041_device::sck_w)
348{
349   // check if changed
350   if (m_pin.sck == state) return;
351   // sck high-to-low
352   if (state == 0)
353   {
354      // output (part 1)
355      if (m_so_bits == 8)
356      {
357         m_so_bits = 0;
358         m_so_byte = read_byte();
359      }
360      // input
361      if (m_pin.si) m_si_byte = m_si_byte | (1 << m_si_bits);
362      m_si_bits++;
363      if (m_si_bits == 8)
364      {
365         m_si_bits = 0;
366         write_byte(m_si_byte);
367         m_si_byte = 0;
368      }
369      // output (part 2)
370      m_pin.so = (m_so_byte >> m_so_bits) & 1;
371      m_so_bits++;
372   }
373   // save sck
374   m_pin.sck = state;
375}
trunk/src/mess/machine/at45dbxx.h
r21684r21685
1/*
2
3    Atmel Serial DataFlash
4
5    (c) 2001-2007 Tim Schuerewegen
6
7    AT45DB041 -  528 KByte
8    AT45DB081 - 1056 KByte
9    AT45DB161 - 2112 KByte
10
11*/
12
13#ifndef _AT45DBXX_H_
14#define _AT45DBXX_H_
15
16#include "emu.h"
17
18
19//**************************************************************************
20//  INTERFACE CONFIGURATION MACROS
21//**************************************************************************
22
23#define MCFG_AT45DB041_ADD(_tag) \
24   MCFG_DEVICE_ADD(_tag, AT45DB041, 0)
25
26#define MCFG_AT45DB081_ADD(_tag) \
27   MCFG_DEVICE_ADD(_tag, AT45DB081, 0)
28
29#define MCFG_AT45DB161_ADD(_tag) \
30   MCFG_DEVICE_ADD(_tag, AT45DB161, 0)
31
32
33// ======================> at45db041_device
34
35class at45db041_device : public device_t,
36                     public device_nvram_interface
37{
38public:
39   at45db041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
40   at45db041_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
41
42   DECLARE_WRITE_LINE_MEMBER(cs_w);
43   DECLARE_WRITE_LINE_MEMBER(sck_w);
44   DECLARE_WRITE_LINE_MEMBER(si_w);
45   DECLARE_READ_LINE_MEMBER(so_r);
46
47   UINT8 *get_ptr() {  return m_data;  }
48
49protected:
50   // device-level overrides
51   virtual void device_start();
52   virtual void device_reset();
53
54   // device_nvram_interface overrides
55   virtual void nvram_default();
56   virtual void nvram_read(emu_file &file);
57   virtual void nvram_write(emu_file &file);
58
59protected:
60   virtual int num_pages() const { return 2048; }
61   virtual int page_size() const { return 264; }
62   virtual UINT8 device_id() const { return 0x18; }
63
64   UINT8 read_byte();
65   void flash_set_io(UINT8* data, UINT32 size, UINT32 pos);
66   virtual UINT32 flash_get_page_addr();
67   virtual UINT32 flash_get_byte_addr();
68   void write_byte(UINT8 data);
69
70   // internal state
71   UINT8 *     m_data;
72   UINT32      m_size;
73   UINT8       m_mode;
74   UINT8       m_status;
75   UINT8 *     m_buffer1;
76   UINT8 *     m_buffer2;
77   UINT8       m_si_byte;
78   UINT8       m_si_bits;
79   UINT8       m_so_byte;
80   UINT8       m_so_bits;
81
82   struct AT45DBXX_PINS
83   {
84      int cs;    // chip select
85      int sck;   // serial clock
86      int si;    // serial input
87      int so;    // serial output
88      int wp;    // write protect
89      int reset; // reset
90      int busy;  // busy
91   } m_pin;
92
93   struct AT45DBXX_IO
94   {
95      UINT8 *data;
96      UINT32 size;
97      UINT32 pos;
98   } m_io;
99
100   struct AT45DBXX_CMD
101   {
102      UINT8 data[8];
103      UINT8 size;
104   } m_cmd;
105};
106
107// ======================> at45db081_device
108
109class at45db081_device : public at45db041_device
110{
111public:
112   at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
113
114protected:
115   virtual int num_pages() const { return 4096; }
116   virtual int page_size() const { return 264;  }
117   virtual UINT8 device_id() const { return 0x20; }
118
119   virtual UINT32 flash_get_page_addr();
120};
121
122// ======================> at45db161_device
123
124class at45db161_device : public at45db041_device
125{
126public:
127   at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
128
129protected:
130   virtual int num_pages() const { return 4096; }
131   virtual int page_size() const { return 528;  }
132   virtual UINT8 device_id() const { return 0x28; }
133
134   virtual UINT32 flash_get_page_addr();
135   virtual UINT32 flash_get_byte_addr();
136};
137
138
139// device type definition
140extern const device_type AT45DB041;
141extern const device_type AT45DB081;
142extern const device_type AT45DB161;
143
144#endif
trunk/src/mess/machine/at29040a.c
r21684r21685
1/*
2    Atmel at29c040a flash EEPROM
3
4    512k*8 FEEPROM, organized in pages of 256 bytes.
5
6    References:
7    Datasheets were found on Atmel's site (www.atmel.com)
8
9    Raphael Nabet 2003
10
11    September 2010: Rewritten as device
12    February 2012: Rewritten as class
13*/
14
15#include "at29040a.h"
16
17#define VERBOSE 2
18#define LOG logerror
19
20#define FEEPROM_SIZE        0x80000
21#define SECTOR_SIZE         0x00100
22#define BOOT_BLOCK_SIZE     0x04000
23
24#define ADDRESS_MASK        0x7ffff
25#define SECTOR_ADDRESS_MASK 0x7ff00
26#define BYTE_ADDRESS_MASK   0x000ff
27
28#define PRG_TIMER 1
29
30#define VERSION 0
31
32/*
33    Constructor.
34*/
35at29040a_device::at29040a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
36: device_t(mconfig, AT29040A, "ATMEL 29040A 512K*8 FEEPROM", tag, owner, clock),
37   device_nvram_interface(mconfig, *this)
38{
39}
40
41//-------------------------------------------------
42//  nvram_default - called to initialize NVRAM to
43//  its default state
44//-------------------------------------------------
45
46void at29040a_device::nvram_default()
47{
48   memset(m_eememory, 0, FEEPROM_SIZE+2);
49}
50
51//-------------------------------------------------
52//  nvram_read - called to read NVRAM from the
53//  .nv file
54//-------------------------------------------------
55
56void at29040a_device::nvram_read(emu_file &file)
57{
58   file.read(m_eememory, FEEPROM_SIZE+2);
59}
60
61//-------------------------------------------------
62//  nvram_write - called to write NVRAM to the
63//  .nv file
64//-------------------------------------------------
65
66void at29040a_device::nvram_write(emu_file &file)
67{
68   m_eememory[0] = VERSION;
69   file.write(m_eememory, FEEPROM_SIZE+2);
70}
71
72/*
73    programming timer callback
74*/
75void at29040a_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
76{
77   switch (m_pgm)
78   {
79   case PGM_1:
80      /* programming cycle timeout */
81      if (VERBOSE>7) LOG("at29040a: Programming cycle timeout\n");
82      m_pgm = PGM_0;
83      break;
84
85   case PGM_2:
86      /* programming cycle start */
87      if (VERBOSE>7) LOG("at29040a: Sector write start\n");
88      m_pgm = PGM_3;
89      /* max delay 10ms, typical delay 5 to 7 ms */
90      m_programming_timer->adjust(attotime::from_msec(5));
91      break;
92
93   case PGM_3:
94      /* programming cycle end */
95      memcpy(m_eememory + 2 + (m_programming_last_offset & ~0xff), m_programming_buffer, SECTOR_SIZE);
96      if (VERBOSE>7) LOG("at29040a: Sector write completed at location %04x + 2\n", (m_programming_last_offset & ~0xff));
97      if (m_enabling_sdb)
98      {
99         m_sdp = true;
100      }
101      if (m_disabling_sdb)
102      {
103         m_sdp = false;
104      }
105      if (VERBOSE>7) LOG("at29040a: Software data protection = %d\n", m_sdp);
106
107      m_pgm = PGM_0;
108      m_enabling_sdb = false;
109      m_disabling_sdb = false;
110
111      break;
112
113   default:
114      if (VERBOSE>1) LOG("internal error in %s %d\n", __FILE__, __LINE__);
115      break;
116   }
117}
118
119void at29040a_device::sync_flags()
120{
121   if (m_lower_bbl) m_eememory[1] |= 0x04;
122   else m_eememory[1] &= ~0x04;
123
124   if (m_higher_bbl) m_eememory[1] |= 0x02;
125   else m_eememory[1] &= ~0x02;
126
127   if (m_sdp) m_eememory[1] |= 0x01;
128   else m_eememory[1] &= ~0x01;
129}
130
131/*
132    read a byte from FEEPROM
133*/
134READ8_MEMBER( at29040a_device::read )
135{
136   int reply;
137
138   offset &= ADDRESS_MASK;
139
140   /* reading in the midst of any command sequence cancels it (right???) */
141   m_cmd = CMD_0;
142   m_long_sequence = false;
143   // m_higher_bbl = true;         // who says that?
144
145   sync_flags();
146
147   /* reading before the start of a programming cycle cancels it (right???) */
148   if (m_pgm == PGM_1)
149   {
150      // attempt to access a locked out boot block: cancel programming
151      // command if necessary
152      m_pgm = PGM_0;
153      m_enabling_sdb = false;
154      m_disabling_sdb = false;
155      m_programming_timer->adjust(attotime::never);
156   }
157
158   if (m_id_mode)
159   {
160      switch (offset)
161      {
162      case 0x00000:
163         reply = 0x1f;       // Manufacturer code
164         break;
165
166      case 0x00001:
167         reply = 0xa4;       // Device code
168         break;
169
170      case 0x00002:
171         reply = m_lower_bbl? 0xff : 0xfe;
172         break;
173
174      case 0x7fff2:
175         reply = m_higher_bbl? 0xff : 0xfe;
176         break;
177
178      default:
179         reply = 0;
180         break;
181      }
182   }
183   else if ((m_pgm == PGM_2) || (m_pgm == PGM_3))
184   {
185      if (m_pgm == PGM_2)
186      {   // DATA* polling starts the programming cycle (right???)
187         m_pgm = PGM_3;
188         /* max delay 10ms, typical delay 5 to 7 ms */
189         m_programming_timer->adjust(attotime::from_msec(5));
190      }
191
192      reply = m_toggle_bit? 0x02 : 0x00;
193      m_toggle_bit = !m_toggle_bit;
194
195      if ((offset == m_programming_last_offset) && (! (m_programming_buffer[m_programming_last_offset & 0xff] & 0x01)))
196         reply |= 0x01;
197   }
198   else
199      reply = m_eememory[offset+2];
200
201   if (VERBOSE>7) LOG("at29040a: %05x -> %02x\n", offset, reply);
202
203   return reply;
204}
205
206/*
207    Write a byte to FEEPROM
208*/
209WRITE8_MEMBER( at29040a_device::write )
210{
211   offset &= ADDRESS_MASK;
212   if (VERBOSE>7) LOG("at29040a: %05x <- %02x\n", offset, data);
213
214   /* The special CFI commands assume a smaller address space according */
215   /* to the specification ("address format A14-A0") */
216   offs_t cfi_offset = offset & 0x7fff;
217
218   if (m_enabling_bbl)
219   {
220      if (VERBOSE>7) LOG("at29040a: Enabling boot block lockout\n");
221      m_enabling_bbl = false;
222
223      if ((offset == 0x00000) && (data == 0x00))
224      {
225         if (VERBOSE>7) LOG("at29040a: Enabling lower boot block lockout\n");
226         m_lower_bbl = true;
227         sync_flags();
228         return;
229      }
230      else
231      {
232         if ((offset == 0x7ffff) && (data == 0xff))
233         {
234            if (VERBOSE>7) LOG("at29040a: Enabling higher boot block lockout\n");
235            m_higher_bbl = true;
236            sync_flags();
237            return;
238         }
239         else
240         {
241            if (VERBOSE>1) LOG("at29040a: Invalid boot block specification: %05x/%02x\n", offset, data);
242         }
243      }
244   }
245
246   switch (m_cmd)
247   {
248   case CMD_0:
249      if ((cfi_offset == 0x5555) && (data == 0xaa))
250      {
251         if (VERBOSE>7) LOG("at29040a: Command sequence started\n");
252         m_cmd = CMD_1;
253      }
254      else
255      {
256         m_cmd = CMD_0;
257         m_long_sequence = false;
258      }
259      break;
260
261   case CMD_1:
262      if ((cfi_offset == 0x2aaa) && (data == 0x55))
263      {
264         m_cmd = CMD_2;
265      }
266      else
267      {
268         m_cmd = CMD_0;
269         m_long_sequence = false;
270         if (VERBOSE>7) LOG("at29040a: Command sequence aborted\n");
271      }
272      break;
273
274   case CMD_2:
275      if (cfi_offset == 0x5555)
276      {
277         if (!m_long_sequence)
278            if (VERBOSE>7) LOG("at29040a: Command sequence completed\n");
279
280         m_pgm = PGM_0;
281         m_enabling_sdb = false;
282         m_disabling_sdb = false;
283         m_programming_timer->adjust(attotime::never);
284
285         /* process command */
286         switch (data)
287         {
288         case 0x10:
289            /*  Software chip erase */
290            if (m_long_sequence)
291            {
292               if (m_lower_bbl || m_higher_bbl)
293               {
294                  if (VERBOSE>1) LOG("at29040a: Chip erase sequence deactivated due to previous boot block lockout.\n");
295               }
296               else
297               {
298                  if (VERBOSE>7) LOG("at29040a: Erase chip\n");
299                  memset(m_eememory+2, 0xff, FEEPROM_SIZE);
300               }
301            }
302            break;
303
304         case 0x20:
305            /* Software data protection disable */
306            if (VERBOSE>7) LOG("at29040a: Software data protection disable\n");
307            // The complete sequence is aa-55-80-aa-55-20
308            // so we need a 80 before, else the sequence is invalid
309            if (m_long_sequence)
310            {
311               m_pgm = PGM_1;
312               m_disabling_sdb = true;
313               /* set command timeout (right???) */
314               //m_programming_timer->adjust(attotime::from_usec(150), id, 0.);
315            }
316            break;
317
318         case 0x40:
319            /* Boot block lockout enable */
320            // Complete sequence is aa-55-80-aa-55-40
321            if (VERBOSE>7) LOG("at29040a: Boot block lockout enable\n");
322            if (m_long_sequence) m_enabling_bbl = true;
323            break;
324
325         case 0x80:
326            m_long_sequence = true;
327            break;
328
329         case 0x90:
330            /* Software product identification entry */
331            if (VERBOSE>7) LOG("at29040a: Identification mode (start)\n");
332            m_id_mode = true;
333            break;
334
335         case 0xa0:
336            /* Software data protection enable */
337            if (VERBOSE>7) LOG("at29040a: Software data protection enable\n");
338            m_pgm = PGM_1;
339            m_enabling_sdb = true;
340            /* set command timeout (right???) */
341            //m_programming_timer->adjust(attotime::from_usec(150), id, 0.);
342            break;
343
344         case 0xf0:
345            /* Software product identification exit */
346            if (VERBOSE>7) LOG("at29040a: Identification mode (end)\n");
347            m_id_mode = false;
348            break;
349         }
350         m_cmd = CMD_0;
351         if (data != 0x80) m_long_sequence = false;
352
353         /* return, because we don't want to write the EEPROM with the command byte */
354         return;
355      }
356      else
357      {
358         m_cmd = CMD_0;
359         m_long_sequence = false;
360      }
361   }
362   if ((m_pgm == PGM_2)
363         && ((offset & ~0xff) != (m_programming_last_offset & ~0xff)))
364   {
365      /* cancel current programming cycle */
366      if (VERBOSE>7) LOG("at29040a: invalid sector change (from %05x to %05x); cancel programming cycle\n",(offset & ~0xff), (m_programming_last_offset & ~0xff));
367      m_pgm = PGM_0;
368      m_enabling_sdb = false;
369      m_disabling_sdb = false;
370      m_programming_timer->adjust(attotime::never);
371   }
372
373   if (((m_pgm == PGM_0) && !m_sdp)  // write directly
374      || (m_pgm == PGM_1))          // write after unlocking
375   {
376      if (((offset < BOOT_BLOCK_SIZE) && m_lower_bbl)
377         || ((offset >= FEEPROM_SIZE-BOOT_BLOCK_SIZE) && m_higher_bbl))
378      {
379         // attempt to access a locked out boot block: cancel programming
380         // command if necessary
381         if (VERBOSE>7) LOG("at29040a: attempt to access a locked out boot block: offset = %05x, lowblock=%d, highblock=%d\n", offset, m_lower_bbl, m_higher_bbl);
382
383         m_pgm = PGM_0;
384         m_enabling_sdb = false;
385         m_disabling_sdb = false;
386      }
387      else
388      {   /* enter programming mode */
389         if (VERBOSE>7) LOG("at29040a: enter programming mode (m_pgm=%d)\n", m_pgm);
390         memset(m_programming_buffer, 0xff, SECTOR_SIZE);
391         m_pgm = PGM_2;
392      }
393   }
394   if (m_pgm == PGM_2)
395   {
396      /* write data to programming buffer */
397      if (VERBOSE>7) LOG("at29040a: Write data to programming buffer\n");
398      m_programming_buffer[offset & 0xff] = data;
399      m_programming_last_offset = offset;
400      m_programming_timer->adjust(attotime::from_usec(150));  // next byte must be written before the timer expires
401   }
402}
403
404void at29040a_device::device_start(void)
405{
406   m_programming_buffer = (UINT8*)malloc(SECTOR_SIZE);
407   m_programming_timer = timer_alloc(PRG_TIMER);
408
409   m_eememory = (UINT8*)malloc(FEEPROM_SIZE+2);
410}
411
412void at29040a_device::device_stop(void)
413{
414   free(m_programming_buffer);
415   free(m_eememory);
416}
417
418void at29040a_device::device_reset(void)
419{
420   if (m_eememory[0] != VERSION)
421   {
422      if (VERBOSE>1) LOG("AT29040A: Warning: Version mismatch; expected %d but found %d for %s. Resetting.\n", VERSION, m_eememory[0], tag());
423      m_eememory[0] = 0;
424      m_eememory[1] = 0;
425   }
426
427   m_lower_bbl =   ((m_eememory[1] & 0x04)!=0);
428   m_higher_bbl =  ((m_eememory[1] & 0x02)!=0);
429   m_sdp =         ((m_eememory[1] & 0x01)!=0);
430
431   if (VERBOSE>7) LOG("at29040a (%s): LowerBBL = %d, HigherBBL = %d, SoftDataProt = %d\n", tag(), m_lower_bbl, m_higher_bbl, m_sdp);
432
433   m_id_mode = false;
434   m_cmd = CMD_0;
435   m_enabling_bbl = false;
436   m_long_sequence = false;
437   m_pgm = PGM_0;
438   m_enabling_sdb = false;
439   m_disabling_sdb = false;
440   m_toggle_bit = false;
441   m_programming_last_offset = 0;
442}
443
444const device_type AT29040A = &device_creator<at29040a_device>;
trunk/src/mess/machine/at29040a.h
r21684r21685
1/*
2    ATMEL 29040a
3
4    Michael Zapf
5    September 2010: Rewritten as device
6    February 2012: Rewritten as class
7*/
8
9#ifndef __AT29040__
10#define __AT29040__
11
12#include "emu.h"
13
14extern const device_type AT29040A;
15
16/*
17    at29c40a state
18
19    Command states (CMD_0 is the initial state):
20    CMD_0: default state
21    CMD_1: state after writing aa to 5555
22    CMD_2: state after writing 55 to 2aaa
23
24    Programming states (s_programming_0 is the initial state):
25    PGM_0: default state
26    PGM_1: a program and enable/disable lock command has been executed, but programming has not actually started.
27    PGM_2: the programming buffer is being written to
28    PGM_3: the programming buffer is being burnt to flash ROM
29*/
30enum  s_cmd_t
31{
32   CMD_0 = 0x0,
33   CMD_1 = 0x1,
34   CMD_2 = 0x2
35};
36
37enum  s_pgm_t
38{
39   PGM_0 = 0x0,
40   PGM_1 = 0x1,
41   PGM_2 = 0x2,
42   PGM_3 = 0x3
43};
44
45class at29040a_device : public device_t, public device_nvram_interface
46{
47public:
48   at29040a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
49   DECLARE_READ8_MEMBER( read );
50   DECLARE_WRITE8_MEMBER( write );
51
52protected:
53   virtual void device_start(void);
54   virtual void device_reset(void);
55   virtual void device_stop(void);
56   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
57
58   void nvram_default();
59   void nvram_read(emu_file &file);
60   void nvram_write(emu_file &file);
61
62private:
63   void        sync_flags(void);
64
65   UINT8*      m_eememory;
66
67   bool        m_lower_bbl;        /* set when lower boot block lockout is enabled */
68   bool        m_higher_bbl;       /* set when upper boot block lockout is enabled */
69   bool        m_sdp;              /* set when in software data protect mode */
70
71   bool        m_id_mode;          /* set when in chip id mode */
72   s_cmd_t     m_cmd;              /* command state */
73   bool        m_enabling_bbl;     /* set when a boot block lockout command is expecting its parameter */
74   bool        m_long_sequence;    /* set if 0x80 command has just been executed (some command require this prefix) */
75   s_pgm_t     m_pgm;              /* programming state */
76   bool        m_enabling_sdb;     /* set when a sdp enable command is in progress */
77   bool        m_disabling_sdb;    /* set when a sdp disable command is in progress */
78   bool        m_dirty;            /* set when the memory contents should be set */
79   bool        m_toggle_bit;       // indicates flashing in progress (toggles for each query)
80   UINT8*      m_programming_buffer;
81   int         m_programming_last_offset;
82   emu_timer*  m_programming_timer;
83};
84
85#define MCFG_AT29040A_ADD(_tag )    \
86   MCFG_DEVICE_ADD(_tag, AT29040A, 0)
87
88#endif
trunk/src/mess/machine/er59256.c
r21684r21685
1/*********************************************************************
2
3    er59256.c
4
5    Microchip ER59256 serial eeprom.
6
7
8*********************************************************************/
9
10#include "emu.h"
11#include "er59256.h"
12
13/* LOGLEVEL 0=no logging, 1=just commands and data, 2=everything ! */
14
15#define LOGLEVEL            0
16
17#define LOG(level,...)      if(LOGLEVEL>=level) logerror(__VA_ARGS__)
18#define LOG_BITS(bits)      logerror("CS=%d CK=%d DI=%d DO=%d", (bits&CS_MASK) ? 1 : 0, (bits&CK_MASK) ? 1 : 0, (bits&DI_MASK) ? 1 : 0, (bits&DO_MASK) ? 1 : 0)
19
20/***************************************************************************
21    TYPE DEFINITIONS
22***************************************************************************/
23
24struct er59256_t
25{
26   /* The actual memory */
27   UINT16  eerom[EEROM_WORDS];
28
29   /* Bits as they appear on the io pins, current state */
30   UINT8   io_bits;
31
32   /* Bits as they appear on the io pins, previous state */
33   UINT8   old_io_bits;
34
35
36   /* the 16 bit shift in/out reg */
37   UINT16  in_shifter;
38   UINT32  out_shifter;
39
40   /* Count of bits received since last CS low->high */
41   UINT8   bitcount;
42
43   /* Command & addresss */
44   UINT8   command;
45
46   /* Write enable and write in progress flags */
47   UINT8   flags;
48};
49
50/***************************************************************************
51    FUNCTION PROTOTYPES
52************************************************************************/
53
54static void decode_command(er59256_t *er59256);
55
56/***************************************************************************
57    INLINE FUNCTIONS
58***************************************************************************/
59
60INLINE er59256_t *get_token(device_t *device)
61{
62   assert(device->type() == ER59256);
63   return (er59256_t *) downcast<er59256_device *>(device)->token();
64}
65
66
67/***************************************************************************
68    IMPLEMENTATION
69***************************************************************************/
70
71void er59256_preload_rom(device_t *device, const UINT16 *rom_data, int count)
72{
73   er59256_t *er59256 = get_token(device);
74   int WordNo;
75
76   logerror("Preloading %d words of data\n",count);
77
78   if(count>EEROM_WORDS)
79      memcpy(&er59256->eerom,rom_data,count*2);
80   else
81      memcpy(&er59256->eerom,rom_data,EEROM_WORDS*2);
82
83   for(WordNo=0;WordNo<EEROM_WORDS;WordNo++)
84      logerror("%04X ",er59256->eerom[WordNo]);
85
86   logerror("\n");
87}
88
89UINT8 er59256_data_loaded(device_t *device)
90{
91   er59256_t *er59256 = get_token(device);
92
93   return (er59256->flags & FLAG_DATA_LOADED) ? 1 : 0;
94}
95
96/*-------------------------------------------------
97    DEVICE_START( er59256 )
98-------------------------------------------------*/
99
100static DEVICE_START( er59256 )
101{
102   er59256_t *er59256 = get_token(device);
103
104   memset(er59256, 0x00, sizeof(er59256_t));
105
106   // Start with rom defaulted to erased
107   memset(&er59256->eerom, 0xFF, EEROM_WORDS*2);
108
109   er59256->command=CMD_INVALID;
110
111   er59256->flags&= ~FLAG_DATA_LOADED;
112}
113
114static DEVICE_STOP( er59256 )
115{
116   /* Save contents of eerom */
117}
118
119void er59256_set_iobits(device_t *device, UINT8 newbits)
120{
121   er59256_t *er59256 = get_token(device);
122   //UINT32  bit;
123
124   // Make sure we only apply valid bits
125   newbits&=ALL_MASK;
126
127   if(LOGLEVEL>1)
128   {
129      logerror("er59256:newbits=%02X : ",newbits);
130      LOG_BITS(newbits);
131      logerror(" io_bits=%02X : ",er59256->io_bits);
132      LOG_BITS(er59256->io_bits);
133      logerror(" old_io_bits=%02X : ",er59256->old_io_bits);
134      LOG_BITS(er59256->old_io_bits);
135      logerror(" bitcount=%d, in_shifter=%04X, out_shifter=%05X, flags=%02X\n",er59256->bitcount,er59256->in_shifter,er59256->out_shifter,er59256->flags);
136   }
137   // Only do anything if the inputs have changed
138   if((newbits&IN_MASK)!=(er59256->io_bits&IN_MASK))
139   {
140      // save the current state, then set the new one, remembering to preserve data out
141      er59256->old_io_bits=er59256->io_bits;
142      er59256->io_bits=(newbits & ~DO_MASK) | (er59256->old_io_bits&DO_MASK);
143
144      if(CS_RISE(er59256))
145      {
146         er59256->flags&=~FLAG_START_BIT;
147         er59256->command=CMD_INVALID;
148      }
149
150      if(LOGLEVEL>1)
151      {
152         if(CK_RISE(er59256)) logerror("er59256:CK rise\n");
153         if(CS_RISE(er59256)) logerror("er59256:CS rise\n");
154         if(CK_FALL(er59256)) logerror("er59256:CK fall\n");
155         if(CS_FALL(er59256)) logerror("er59256:CS fall\n");
156      }
157
158      if(CK_RISE(er59256) && CS_VALID(er59256))
159      {
160         if((STARTED(er59256)==0) && (GET_DI(er59256)==1))
161         {
162            er59256->bitcount=0;
163            er59256->flags|=FLAG_START_BIT;
164         }
165         else
166         {
167            SHIFT_IN(er59256);
168            er59256->bitcount++;
169
170            if(er59256->bitcount==CMD_BITLEN)
171               decode_command(er59256);
172
173            if((er59256->bitcount==WRITE_BITLEN) && ((er59256->command & CMD_MASK)==CMD_WRITE))
174            {
175               er59256->eerom[er59256->command & ADDR_MASK]=er59256->in_shifter;
176               LOG(1,"er59256:write[%02X]=%04X\n",(er59256->command & ADDR_MASK),er59256->in_shifter);
177               er59256->command=CMD_INVALID;
178            }
179            LOG(1,"out_shifter=%05X, io_bits=%02X\n",er59256->out_shifter,er59256->io_bits);
180            SHIFT_OUT(er59256);
181         }
182
183         LOG(2,"io_bits:out=%02X\n",er59256->io_bits);
184      }
185   }
186}
187
188UINT8 er59256_get_iobits(device_t *device)
189{
190   er59256_t *er59256 = get_token(device);
191
192   return er59256->io_bits;
193}
194
195
196static void decode_command(er59256_t *er59256)
197{
198   er59256->out_shifter=0x0000;
199   er59256->command=(er59256->in_shifter & (CMD_MASK | ADDR_MASK));
200
201   switch(er59256->command & CMD_MASK)
202   {
203      case CMD_READ   : er59256->out_shifter=er59256->eerom[er59256->command & ADDR_MASK];
204                     LOG(1,"er59256:read[%02X]=%04X\n",(er59256->command&ADDR_MASK),er59256->eerom[er59256->command & ADDR_MASK]);
205                     break;
206      case CMD_WRITE  : break;
207      case CMD_ERASE  : if (WRITE_ENABLED(er59256)) er59256->eerom[er59256->command & ADDR_MASK]=0xFF;
208                     LOG(1,"er59256:erase[%02X]\n",(er59256->command&ADDR_MASK));
209                     break;
210      case CMD_EWEN   : er59256->flags|=FLAG_WRITE_EN;
211                     LOG(1,"er59256:erase/write enabled\n");
212                     break;
213      case CMD_EWDS   : er59256->flags&=~FLAG_WRITE_EN;
214                     LOG(1,"er59256:erase/write disabled\n");
215                     break;
216      case CMD_ERAL   : if (WRITE_ENABLED(er59256)) memset(&er59256->eerom, 0xFF, EEROM_WORDS*2);
217                     LOG(1,"er59256:erase all\n");
218                     break;
219   }
220
221   if ((er59256->command & CMD_MASK)!=CMD_WRITE)
222      er59256->command=CMD_INVALID;
223}
224
225const device_type ER59256 = &device_creator<er59256_device>;
226
227er59256_device::er59256_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
228   : device_t(mconfig, ER59256, "Microchip ER59256 serial eeprom.", tag, owner, clock)
229{
230   m_token = global_alloc_clear(er59256_t);
231}
232
233//-------------------------------------------------
234//  device_config_complete - perform any
235//  operations now that the configuration is
236//  complete
237//-------------------------------------------------
238
239void er59256_device::device_config_complete()
240{
241}
242
243//-------------------------------------------------
244//  device_start - device-specific startup
245//-------------------------------------------------
246
247void er59256_device::device_start()
248{
249   DEVICE_START_NAME( er59256 )(this);
250}
251
252//-------------------------------------------------
253//  device_stop - device-specific stop
254//-------------------------------------------------
255
256void er59256_device::device_stop()
257{
258   DEVICE_STOP_NAME( er59256 )(this);
259}
trunk/src/mess/machine/er59256.h
r21684r21685
1/*********************************************************************
2
3    er59256.h
4
5    Microchip ER59256 serial eeprom.
6
7
8*********************************************************************/
9
10#ifndef _ER59256_H_
11#define _ER59256_H_
12
13/***************************************************************************
14    MACROS
15***************************************************************************/
16
17class er59256_device : public device_t
18{
19public:
20   er59256_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
21   ~er59256_device() { global_free(m_token); }
22
23   // access to legacy token
24   void *token() const { assert(m_token != NULL); return m_token; }
25protected:
26   // device-level overrides
27   virtual void device_config_complete();
28   virtual void device_start();
29   virtual void device_stop();
30private:
31   // internal state
32   void *m_token;
33};
34
35extern const device_type ER59256;
36
37
38#define MCFG_ER59256_ADD(_tag)  \
39   MCFG_DEVICE_ADD((_tag), ER59256, 0)
40
41/***************************************************************************
42    CONSTANTS
43***************************************************************************/
44
45#define EEROM_WORDS         0x10
46
47#define CK_SHIFT            0x00
48#define DI_SHIFT            0x01
49#define DO_SHIFT            0x02
50#define CS_SHIFT            0x03
51
52#define CK_MASK             (1<<CK_SHIFT)
53#define DI_MASK             (1<<DI_SHIFT)
54#define DO_MASK             (1<<DO_SHIFT)
55#define CS_MASK             (1<<CS_SHIFT)
56
57#define ALL_MASK            (CK_MASK | DI_MASK | DO_MASK | CS_MASK)
58#define IN_MASK             (CK_MASK | DI_MASK | CS_MASK)
59
60#define GET_CK(eep)         ((eep->io_bits & CK_MASK) >> CK_SHIFT)
61#define GET_DI(eep)         ((eep->io_bits & DI_MASK) >> DI_SHIFT)
62#define GET_DO(eep)         ((eep->io_bits & DO_MASK) >> DO_SHIFT)
63#define GET_CS(eep)         ((eep->io_bits & CS_MASK) >> CS_SHIFT)
64
65#define SET_CK(eep,data)    eep->io_bits=((eep->io_bits & ~CK_MASK) | ((data & 0x01) << CK_SHIFT))
66#define SET_DI(eep,data)    eep->io_bits=((eep->io_bits & ~DI_MASK) | ((data & 0x01) << DI_SHIFT))
67#define SET_DO(eep,data)    eep->io_bits=((eep->io_bits & ~DO_MASK) | ((data & 0x01) << DO_SHIFT))
68#define SET_CS(eep,data)    eep->io_bits=((eep->io_bits & ~CS_MASK) | ((data & 0x01) << CS_SHIFT))
69
70#define CK_RISE(eep)        ((eep->io_bits & CK_MASK) & ~(eep->old_io_bits & CK_MASK))
71#define CS_RISE(eep)        ((eep->io_bits & CS_MASK) & ~(eep->old_io_bits & CS_MASK))
72#define CS_VALID(eep)       ((eep->io_bits & CS_MASK) & (eep->old_io_bits & CS_MASK))
73
74#define CK_FALL(eep)        (~(eep->io_bits & CK_MASK) & (eep->old_io_bits & CK_MASK))
75#define CS_FALL(eep)        (~(eep->io_bits & CS_MASK) & (eep->old_io_bits & CS_MASK))
76
77
78#define SHIFT_IN(eep)       eep->in_shifter=(eep->in_shifter<<1) | GET_DI(eep)
79#define SHIFT_OUT(eep)      SET_DO(eep,(eep->out_shifter & 0x10000)>>16); eep->out_shifter=(eep->out_shifter<<1)
80
81#define CMD_READ            0x80
82#define CMD_WRITE           0x40
83#define CMD_ERASE           0xC0
84#define CMD_EWEN            0x30
85#define CMD_EWDS            0x00
86#define CMD_ERAL            0x20
87#define CMD_INVALID         0xF0
88
89#define CMD_MASK            0xF0
90#define ADDR_MASK           0x0F
91
92// CMD_BITLEN is 1 start bit plus 4 command bits plus 4 address bits
93#define CMD_BITLEN          8
94#define DATA_BITLEN         16
95#define WRITE_BITLEN        CMD_BITLEN+DATA_BITLEN
96
97#define FLAG_WRITE_EN       0x01
98#define FLAG_START_BIT      0x02
99#define FLAG_DATA_LOADED    0x04
100
101#define WRITE_ENABLED(eep)  ((eep->flags & FLAG_WRITE_EN) ? 1 : 0)
102#define STARTED(eep)        ((eep->flags & FLAG_START_BIT) ? 1 : 0)
103
104/***************************************************************************
105    FUNCTION PROTOTYPES
106***************************************************************************/
107
108void er59256_set_iobits(device_t *device, UINT8 newbits);
109UINT8 er59256_get_iobits(device_t *device);
110void er59256_preload_rom(device_t *device, const UINT16 *rom_data, int count);
111UINT8 er59256_data_loaded(device_t *device);
112#endif
trunk/src/mess/machine/74145.c
r21684r21685
1/*****************************************************************************
2 *
3 * machine/74145.c
4 *
5 * BCD-to-Decimal decoder
6 *
7 *        __ __
8 *     0-|  v  |-VCC
9 *     1-|     |-A
10 *     2-|     |-B
11 *     3-|     |-C
12 *     4-|     |-D
13 *     5-|     |-9
14 *     6-|     |-8
15 *   GND-|_____|-7
16 *
17 *
18 * Truth table
19 *  _______________________________
20 * | Inputs  | Outputs             |
21 * | D C B A | 0 1 2 3 4 5 6 7 8 9 |
22 * |-------------------------------|
23 * | L L L L | L H H H H H H H H H |
24 * | L L L H | H L H H H H H H H H |
25 * | L L H L | H H L H H H H H H H |
26 * | L L H H | H H H L H H H H H H |
27 * | L H L L | H H H H L H H H H H |
28 * |-------------------------------|
29 * | L H L H | H H H H H L H H H H |
30 * | L H H L | H H H H H H L H H H |
31 * | L H H H | H H H H H H H L H H |
32 * | H L L L | H H H H H H H H L H |
33 * | H L L H | H H H H H H H H H L |
34 * |-------------------------------|
35 * | H L H L | H H H H H H H H H H |
36 * | H L H H | H H H H H H H H H H |
37 * | H H L L | H H H H H H H H H H |
38 * | H H L H | H H H H H H H H H H |
39 * | H H H L | H H H H H H H H H H |
40 * | H H H H | H H H H H H H H H H |
41 *  -------------------------------
42 *
43 ****************************************************************************/
44
45#include "emu.h"
46#include "74145.h"
47#include "coreutil.h"
48
49/*****************************************************************************
50    GLOBAL VARIABLES
51*****************************************************************************/
52
53const ttl74145_interface default_ttl74145 =
54{
55   DEVCB_NULL,
56   DEVCB_NULL,
57   DEVCB_NULL,
58   DEVCB_NULL,
59   DEVCB_NULL,
60   DEVCB_NULL,
61   DEVCB_NULL,
62   DEVCB_NULL,
63   DEVCB_NULL,
64   DEVCB_NULL
65};
66
67
68const device_type TTL74145 = &device_creator<ttl74145_device>;
69
70/***************************************************************************
71    DEVICE INTERFACE
72***************************************************************************/
73//-------------------------------------------------
74//  ttl74145_device - constructor
75//-------------------------------------------------
76
77ttl74145_device::ttl74145_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
78   : device_t(mconfig, TTL74145, "TTL74145", tag, owner, clock)
79   , m_number(0)
80{
81}
82
83
84//-------------------------------------------------
85//  device_start - device-specific startup
86//-------------------------------------------------
87
88void ttl74145_device::device_start()
89{
90   /* resolve callbacks */
91   m_output_line_0_func.resolve(m_output_line_0_cb, *this);
92   m_output_line_1_func.resolve(m_output_line_1_cb, *this);
93   m_output_line_2_func.resolve(m_output_line_2_cb, *this);
94   m_output_line_3_func.resolve(m_output_line_3_cb, *this);
95   m_output_line_4_func.resolve(m_output_line_4_cb, *this);
96   m_output_line_5_func.resolve(m_output_line_5_cb, *this);
97   m_output_line_6_func.resolve(m_output_line_6_cb, *this);
98   m_output_line_7_func.resolve(m_output_line_7_cb, *this);
99   m_output_line_8_func.resolve(m_output_line_8_cb, *this);
100   m_output_line_9_func.resolve(m_output_line_9_cb, *this);
101
102   // register for state saving
103   save_item(NAME(m_number));
104}
105
106//-------------------------------------------------
107//  device_config_complete - perform any
108//  operations now that the configuration is
109//  complete
110//-------------------------------------------------
111
112void ttl74145_device::device_config_complete()
113{
114   // inherit a copy of the static data
115   const ttl74145_interface *intf = reinterpret_cast<const ttl74145_interface *>(static_config());
116   if (intf != NULL)
117      *static_cast<ttl74145_interface *>(this) = *intf;
118
119   // or initialize to defaults if none provided
120   else
121   {
122      memset(&m_output_line_0_cb, 0, sizeof(m_output_line_0_cb));
123      memset(&m_output_line_1_cb, 0, sizeof(m_output_line_1_cb));
124      memset(&m_output_line_2_cb, 0, sizeof(m_output_line_2_cb));
125      memset(&m_output_line_3_cb, 0, sizeof(m_output_line_3_cb));
126      memset(&m_output_line_4_cb, 0, sizeof(m_output_line_4_cb));
127      memset(&m_output_line_5_cb, 0, sizeof(m_output_line_5_cb));
128      memset(&m_output_line_6_cb, 0, sizeof(m_output_line_6_cb));
129      memset(&m_output_line_7_cb, 0, sizeof(m_output_line_7_cb));
130      memset(&m_output_line_8_cb, 0, sizeof(m_output_line_8_cb));
131      memset(&m_output_line_9_cb, 0, sizeof(m_output_line_9_cb));
132   }
133}
134
135//-------------------------------------------------
136//  device_start - device-specific reset
137//-------------------------------------------------
138
139void ttl74145_device::device_reset()
140{
141   m_number = 0;
142}
143
144/***************************************************************************
145    IMPLEMENTATION
146***************************************************************************/
147
148void ttl74145_device::write(UINT8 data)
149{
150   /* decode number */
151   UINT16 new_number = bcd_2_dec(data & 0x0f);
152
153   /* call output callbacks if the number changed */
154   if (new_number != m_number)
155   {
156      m_output_line_0_func(new_number == 0);
157      m_output_line_1_func(new_number == 1);
158      m_output_line_2_func(new_number == 2);
159      m_output_line_3_func(new_number == 3);
160      m_output_line_4_func(new_number == 4);
161      m_output_line_5_func(new_number == 5);
162      m_output_line_6_func(new_number == 6);
163      m_output_line_7_func(new_number == 7);
164      m_output_line_8_func(new_number == 8);
165      m_output_line_9_func(new_number == 9);
166   }
167
168   /* update state */
169   m_number = new_number;
170}
171
172
173UINT16 ttl74145_device::read()
174{
175   return (1 << m_number) & 0x3ff;
176}
trunk/src/mess/machine/74145.h
r21684r21685
1/***************************************************************************
2
3    TTL74145
4
5    BCD-to-Decimal decoder
6
7***************************************************************************/
8
9#ifndef __TTL74145_H__
10#define __TTL74145_H__
11
12//**************************************************************************
13//  INTERFACE CONFIGURATION MACROS
14//**************************************************************************
15#define MCFG_TTL74145_ADD(_tag, _intf) \
16   MCFG_DEVICE_ADD(_tag, TTL74145, 0) \
17   MCFG_DEVICE_CONFIG(_intf)
18
19
20//**************************************************************************
21//  TYPE DEFINITIONS
22//**************************************************************************
23
24// ======================> ttl74145_interface
25
26struct ttl74145_interface
27{
28   devcb_write_line m_output_line_0_cb;
29   devcb_write_line m_output_line_1_cb;
30   devcb_write_line m_output_line_2_cb;
31   devcb_write_line m_output_line_3_cb;
32   devcb_write_line m_output_line_4_cb;
33   devcb_write_line m_output_line_5_cb;
34   devcb_write_line m_output_line_6_cb;
35   devcb_write_line m_output_line_7_cb;
36   devcb_write_line m_output_line_8_cb;
37   devcb_write_line m_output_line_9_cb;
38};
39
40// ======================> ttl74145_device
41
42class ttl74145_device :  public device_t,
43                  public ttl74145_interface
44{
45public:
46   // construction/destruction
47   ttl74145_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
48
49   UINT16 read();
50   void write(UINT8 data);
51protected:
52   // device-level overrides
53   virtual void device_start();
54   virtual void device_reset();
55   virtual void device_config_complete();
56
57private:
58   devcb_resolved_write_line   m_output_line_0_func;
59   devcb_resolved_write_line   m_output_line_1_func;
60   devcb_resolved_write_line   m_output_line_2_func;
61   devcb_resolved_write_line   m_output_line_3_func;
62   devcb_resolved_write_line   m_output_line_4_func;
63   devcb_resolved_write_line   m_output_line_5_func;
64   devcb_resolved_write_line   m_output_line_6_func;
65   devcb_resolved_write_line   m_output_line_7_func;
66   devcb_resolved_write_line   m_output_line_8_func;
67   devcb_resolved_write_line   m_output_line_9_func;
68
69   /* decoded number */
70   UINT16 m_number;
71};
72
73// device type definition
74extern const device_type TTL74145;
75
76//**************************************************************************
77//  DEFAULT INTERFACES
78//**************************************************************************
79
80extern const ttl74145_interface default_ttl74145;
81
82
83#endif /* TTL74145 */
trunk/src/mess/machine/pcf8593.c
r21684r21685
1/*********************************************************************
2
3    Philips PCF8593 CMOS clock/calendar circuit
4
5    (c) 2001-2007 Tim Schuerewegen
6
7*********************************************************************/
8
9#include "pcf8593.h"
10
11
12/***************************************************************************
13    PARAMETERS/CONSTANTS/MACROS
14***************************************************************************/
15
16#define LOG_LEVEL  1
17#define _logerror(level,x)  do { if (LOG_LEVEL > level) logerror x; } while (0)
18
19// get/set date
20#define RTC_GET_DATE_YEAR       ((m_data[5] >> 6) & 3)
21#define RTC_SET_DATE_YEAR(x)    m_data[5] = (m_data[5] & 0x3F) | (((x) % 4) << 6)
22#define RTC_GET_DATE_MONTH      bcd_to_integer( m_data[6])
23#define RTC_SET_DATE_MONTH(x)   m_data[6] = convert_to_bcd( x)
24#define RTC_GET_DATE_DAY        (bcd_to_integer( m_data[5] & 0x3F))
25#define RTC_SET_DATE_DAY(x)     m_data[5] = (m_data[5] & 0xC0) | convert_to_bcd( x)
26
27// get/set time
28#define RTC_GET_TIME_HOUR       bcd_to_integer( m_data[4])
29#define RTC_SET_TIME_HOUR(x)    m_data[4] = convert_to_bcd( x)
30#define RTC_GET_TIME_MINUTE     bcd_to_integer( m_data[3])
31#define RTC_SET_TIME_MINUTE(x)  m_data[3] = convert_to_bcd( x)
32#define RTC_GET_TIME_SECOND     bcd_to_integer( m_data[2])
33#define RTC_SET_TIME_SECOND(x)  m_data[2] = convert_to_bcd( x)
34
35
36//**************************************************************************
37//  GLOBAL VARIABLES
38//**************************************************************************
39
40const device_type PCF8593 = &device_creator<pcf8593_device>;
41
42
43//-------------------------------------------------
44//  pcf8593_device - constructor
45//-------------------------------------------------
46
47pcf8593_device::pcf8593_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
48   : device_t(mconfig, PCF8593, "PCF8593 RTC", tag, owner, clock),
49      device_rtc_interface(mconfig, *this),
50      device_nvram_interface(mconfig, *this)
51{
52}
53
54
55//-------------------------------------------------
56//  device_start - device-specific startup
57//-------------------------------------------------
58
59void pcf8593_device::device_start()
60{
61   _logerror( 0, ("pcf8593_init\n"));
62   memset(m_register, 0, sizeof(m_register));
63   m_timer = timer_alloc(TIMER_UPDATE_COUNTER);
64   m_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
65}
66
67//-------------------------------------------------
68//  device_reset - device-specific reset
69//-------------------------------------------------
70
71void pcf8593_device::device_reset()
72{
73   _logerror( 0, ("pcf8593_reset\n"));
74   m_pin_scl = 1;
75   m_pin_sda = 1;
76   m_active  = FALSE;
77   m_inp     = 0;
78   m_mode    = RTC_MODE_RECV;
79   m_bits    = 0;
80   m_pos     = 0;
81   clear_buffer_rx();
82   set_time(true, RTC_GET_DATE_YEAR, RTC_GET_DATE_MONTH, RTC_GET_DATE_DAY, 0, RTC_GET_TIME_HOUR, RTC_GET_TIME_MINUTE, RTC_GET_TIME_SECOND);
83}
84
85
86//-------------------------------------------------
87//  device_timer - handler timer events
88//-------------------------------------------------
89
90void pcf8593_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
91{
92   switch(id)
93   {
94      case TIMER_UPDATE_COUNTER:
95         _logerror( 2, ("pcf8593_timer_callback (%d)\n", param));
96         // check if counting is enabled
97         if (!(m_data[0] & 0x80))
98            advance_seconds();
99         break;
100   }
101}
102
103
104//-------------------------------------------------
105//  rtc_clock_updated -
106//-------------------------------------------------
107
108void pcf8593_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
109{
110   RTC_SET_TIME_SECOND(second);
111   RTC_SET_TIME_MINUTE(minute);
112   RTC_SET_TIME_HOUR(hour);
113   RTC_SET_DATE_DAY(day);
114   RTC_SET_DATE_MONTH(month);
115   RTC_SET_DATE_YEAR(year);
116}
117
118
119//-------------------------------------------------
120//  nvram_default - called to initialize NVRAM to
121//  its default state
122//-------------------------------------------------
123
124void pcf8593_device::nvram_default()
125{
126   memset(m_data, 0, sizeof(m_data));
127}
128
129//-------------------------------------------------
130//  nvram_read - called to read NVRAM from the
131//  .nv file
132//-------------------------------------------------
133
134void pcf8593_device::nvram_read(emu_file &file)
135{
136   file.read(m_data, sizeof(m_data));
137}
138
139
140//-------------------------------------------------
141//  nvram_write - called to write NVRAM to the
142//  .nv file
143//-------------------------------------------------
144
145void pcf8593_device::nvram_write(emu_file &file)
146{
147   file.write(m_data, sizeof(m_data));
148}
149
150
151
152/*-------------------------------------------------
153    pcf8593_pin_scl
154-------------------------------------------------*/
155
156WRITE_LINE_MEMBER(pcf8593_device::scl_w)
157{
158   // send bit
159   if ((m_active) && (!m_pin_scl) && (state))
160   {
161      switch (m_mode)
162      {
163         // HOST -> RTC
164         case RTC_MODE_RECV :
165         {
166            // get bit
167            if (m_pin_sda) m_data_recv[m_data_recv_index] = m_data_recv[m_data_recv_index] | (0x80 >> m_bits);
168            m_bits++;
169            // bit 9 = end
170            if (m_bits > 8)
171            {
172               _logerror( 2, ("pcf8593_write_byte(%02X)\n", m_data_recv[m_data_recv_index]));
173               // enter receive mode when 1st byte = 0xA3
174               if ((m_data_recv[0] == 0xA3) && (m_data_recv_index == 0))
175               {
176                  m_mode = RTC_MODE_SEND;
177               }
178               // A2 + xx = "read from pos xx" command
179               if ((m_data_recv[0] == 0xA2) && (m_data_recv_index == 1))
180               {
181                  m_pos = m_data_recv[1];
182               }
183               // A2 + xx + .. = write byte
184               if ((m_data_recv[0] == 0xA2) && (m_data_recv_index >= 2))
185               {
186                  UINT8 rtc_pos, rtc_val;
187                  rtc_pos = m_data_recv[1] + (m_data_recv_index - 2);
188                  rtc_val = m_data_recv[m_data_recv_index];
189                  //if (rtc_pos == 0) rtc_val = rtc_val & 3; // what is this doing here?
190                  m_data[rtc_pos] = rtc_val;
191                  set_time(false, RTC_GET_DATE_YEAR, RTC_GET_DATE_MONTH, RTC_GET_DATE_DAY, 0, RTC_GET_TIME_HOUR, RTC_GET_TIME_MINUTE, RTC_GET_TIME_SECOND);
192               }
193               // next byte
194               m_bits = 0;
195               m_data_recv_index++;
196            }
197         }
198         break;
199         // RTC -> HOST
200         case RTC_MODE_SEND :
201         {
202            // set bit
203            m_inp = (m_data[m_pos] >> (7 - m_bits)) & 1;
204            m_bits++;
205            // bit 9 = end
206            if (m_bits > 8)
207            {
208               _logerror( 2, ("pcf8593_read_byte(%02X)\n", m_data[m_pos]));
209               // end ?
210               if (m_pin_sda)
211               {
212                  _logerror( 2, ("pcf8593 end\n"));
213                  m_mode = RTC_MODE_RECV;
214                  clear_buffer_rx();
215               }
216               // next byte
217               m_bits = 0;
218               m_pos++;
219            }
220         }
221         break;
222      }
223   }
224   // save scl
225   m_pin_scl = state;
226}
227
228
229
230/*-------------------------------------------------
231    pcf8593_pin_sda_w
232-------------------------------------------------*/
233
234WRITE_LINE_MEMBER(pcf8593_device::sda_w)
235{
236   // clock is high
237   if (m_pin_scl)
238   {
239      // log init I2C
240      if (state) _logerror( 1, ("pcf8593 init i2c\n"));
241      // start condition (high to low when clock is high)
242      if ((!state) && (m_pin_sda))
243      {
244         _logerror( 1, ("pcf8593 start condition\n"));
245         m_active          = TRUE;
246         m_bits            = 0;
247         m_data_recv_index = 0;
248         clear_buffer_rx();
249         //m_pos = 0;
250      }
251      // stop condition (low to high when clock is high)
252      if ((state) && (!m_pin_sda))
253      {
254         _logerror( 1, ("pcf8593 stop condition\n"));
255         m_active = FALSE;
256      }
257   }
258   // save sda
259   m_pin_sda = state;
260}
261
262
263
264/*-------------------------------------------------
265    pcf8593_pin_sda_r
266-------------------------------------------------*/
267
268READ_LINE_MEMBER(pcf8593_device::sda_r)
269{
270   return m_inp;
271}
272
273
274
275/*-------------------------------------------------
276    pcf8593_clear_buffer_rx
277-------------------------------------------------*/
278
279void pcf8593_device::clear_buffer_rx()
280{
281   memset(&m_data_recv[0], 0, sizeof( m_data_recv));
282   m_data_recv_index = 0;
283}
trunk/src/mess/machine/pcf8593.h
r21684r21685
1/*********************************************************************
2
3    Philips PCF8593 CMOS clock/calendar circuit
4
5    (c) 2001-2007 Tim Schuerewegen
6
7*********************************************************************/
8
9#ifndef __PCF8593_H__
10#define __PCF8593_H__
11
12#include "emu.h"
13
14
15//**************************************************************************
16//  INTERFACE CONFIGURATION MACROS
17//**************************************************************************
18
19#define MCFG_PCF8593_ADD(_tag) \
20   MCFG_DEVICE_ADD(_tag, PCF8593, 0)
21
22#define MCFG_PCF8593_REMOVE(_tag) \
23   MCFG_DEVICE_REMOVE(_tag)
24
25
26// ======================> pcf8593_device
27
28class pcf8593_device :  public device_t,
29                  public device_rtc_interface,
30                  public device_nvram_interface
31{
32public:
33   pcf8593_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
34
35   DECLARE_WRITE_LINE_MEMBER(scl_w);
36   DECLARE_WRITE_LINE_MEMBER(sda_w);
37   DECLARE_READ_LINE_MEMBER(sda_r);
38
39protected:
40   // device-level overrides
41   virtual void device_start();
42   virtual void device_reset();
43   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
44
45   // device_rtc_interface overrides
46   virtual bool rtc_feature_y2k() { return true; }
47   virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second);
48
49   // device_nvram_interface overrides
50   virtual void nvram_default();
51   virtual void nvram_read(emu_file &file);
52   virtual void nvram_write(emu_file &file);
53
54private:
55   void clear_buffer_rx();
56
57   static const device_timer_id TIMER_UPDATE_COUNTER = 0;
58
59   // internal state
60   UINT8       m_data[16];
61   int         m_pin_scl;
62   int         m_pin_sda;
63   int         m_inp;
64   int         m_active;
65   int         m_bits;
66   UINT8       m_data_recv_index;
67   UINT8       m_data_recv[50];
68   UINT8       m_mode;
69   UINT8       m_pos;
70   emu_timer * m_timer;
71   enum        { RTC_MODE_NONE, RTC_MODE_SEND, RTC_MODE_RECV };
72};
73
74// device type definition
75extern const device_type PCF8593;
76
77#endif /* __PCF8593_H__ */
trunk/src/mess/machine/mm58274c.c
r21684r21685
1/***************************************************************************
2
3    mm58274c.c
4
5    mm58274c emulation
6
7    Reference:
8    * National Semiconductor MM58274C Microprocessor Compatible Real Time Clock
9        <http://www.national.com/ds/MM/MM58274C.pdf>
10
11    Todo:
12    * Clock initialization will only work with the BwG: we need to provide
13      a way to customize it.
14    * Save the config to NVRAM?
15    * Support interrupt pin output
16
17    Raphael Nabet, 2002
18
19***************************************************************************/
20
21#include "emu.h"
22#include "mm58274c.h"
23
24struct mm58274c_t
25{
26   const mm58274c_interface *intf;
27
28   int status;     /* status register (*read* from address 0 = control register) */
29   int control;    /* control register (*write* to address 0) */
30
31   int clk_set;    /* clock setting register */
32   int int_ctl;    /* interrupt control register */
33
34
35   int wday;       /* day of the week (1-7 (1=day1 as set in init)) */
36   int years1;     /* years (BCD: 0-99) */
37   int years2;
38   int months1;    /* months (BCD: 1-12) */
39   int months2;
40   int days1;      /* days (BCD: 1-31) */
41   int days2;
42   int hours1;     /* hours (BCD : 0-23) */
43   int hours2;
44   int minutes1;   /* minutes (BCD : 0-59) */
45   int minutes2;
46   int seconds1;   /* seconds (BCD : 0-59) */
47   int seconds2;
48   int tenths;     /* tenths of second (BCD : 0-9) */
49
50   emu_timer *increment_rtc;
51   emu_timer *interrupt_timer;
52};
53
54enum
55{
56   st_dcf = 0x8,       /* data-changed flag */
57   st_if = 0x1,        /* interrupt flag */
58
59   ctl_test = 0x8,     /* test mode (0=normal, 1=test) (not emulated) */
60   ctl_clkstop = 0x4,  /* clock start/stop (0=run, 1=stop) */
61   ctl_intsel = 0x2,   /* interrupt select (0=clock setting register, 1=interrupt register) */
62   ctl_intstop = 0x1,  /* interrupt start stop (0=interrupt run, 1=interrupt stop) */
63
64   clk_set_leap = 0xc,     /* leap year counter (0 indicates a leap year) */
65   clk_set_leap_inc = 0x4, /* leap year increment */
66   clk_set_pm = 0x2,       /* am/pm indicator (0 = am, 1 = pm, 0 in 24-hour mode) */
67   clk_set_24 = 0x1,       /* 12/24-hour select bit (1= 24-hour mode) */
68
69   int_ctl_rpt = 0x8,      /* 1 for repeated interrupt */
70   int_ctl_dly = 0x7       /* 0 no interrupt, 1 = .1 second, 2=.5, 3=1, 4=5, 5=10, 6=30, 7=60 */
71};
72
73
74INLINE mm58274c_t *get_safe_token(device_t *device)
75{
76   assert(device != NULL);
77   assert(device->type() == MM58274C);
78
79   return (mm58274c_t *)downcast<mm58274c_device *>(device)->token();
80}
81
82static attotime interrupt_period_table(int val)
83{
84   switch(val)
85   {
86      case 0: return attotime::from_msec(0);
87      case 1: return attotime::from_msec(100);
88      case 2: return attotime::from_msec(500);
89      case 3: return attotime::from_seconds(1);
90      case 4: return attotime::from_seconds(5);
91      case 5: return attotime::from_seconds(10);
92      case 6: return attotime::from_seconds(30);
93      case 7: return attotime::from_seconds(60);
94      default: fatalerror("out of range\n");
95   }
96};
97
98READ8_DEVICE_HANDLER( mm58274c_r )
99{
100   mm58274c_t *mm58274c = get_safe_token(device);
101   int reply;
102
103   offset &= 0xf;
104
105   switch (offset)
106   {
107   case 0x0:   /* Control Register */
108      reply = mm58274c->status;
109      mm58274c->status = 0;
110      break;
111
112   case 0x1:   /* Tenths of Seconds */
113      reply = mm58274c->tenths;
114      break;
115
116   case 0x2:   /* Units Seconds */
117      reply = mm58274c->seconds2;
118      break;
119
120   case 0x3:   /* Tens Seconds */
121      reply = mm58274c->seconds1;
122      break;
123
124   case 0x04:  /* Units Minutes */
125      reply = mm58274c->minutes2;
126      break;
127
128   case 0x5:   /* Tens Minutes */
129      reply = mm58274c->minutes1;
130      break;
131
132   case 0x6:   /* Units Hours */
133      reply = mm58274c->hours2;
134      break;
135
136   case 0x7:   /* Tens Hours */
137      reply = mm58274c->hours1;
138      break;
139
140   case 0x8:   /* Units Days */
141      reply = mm58274c->days2;
142      break;
143
144   case 0x9:   /* Tens Days */
145      reply = mm58274c->days1;
146      break;
147
148   case 0xA:   /* Units Months */
149      reply = mm58274c->months2;
150      break;
151
152   case 0xB:   /* Tens Months */
153      reply = mm58274c->months1;
154      break;
155
156   case 0xC:   /* Units Years */
157      reply = mm58274c->years2;
158      break;
159
160   case 0xD:   /* Tens Years */
161      reply = mm58274c->years1;
162      break;
163
164   case 0xE:   /* Day of Week */
165      reply = mm58274c->wday;
166      break;
167
168   case 0xF:   /* Clock Setting & Interrupt Registers */
169      if (mm58274c->control & ctl_intsel)
170         /* interrupt register */
171         reply = mm58274c->int_ctl;
172      else
173      {   /* clock setting register */
174         if (mm58274c->clk_set & clk_set_24)
175            /* 24-hour mode */
176            reply = mm58274c->clk_set & ~clk_set_pm;
177         else
178            /* 12-hour mode */
179            reply = mm58274c->clk_set;
180      }
181      break;
182
183   default:
184      reply = 0;
185      break;
186   }
187
188   return reply;
189}
190
191
192WRITE8_DEVICE_HANDLER (mm58274c_w)
193{
194   mm58274c_t *mm58274c = get_safe_token(device);
195
196   offset &= 0xf;
197   data &= 0xf;
198
199   switch (offset)
200   {
201   case 0x0:   /* Control Register (test mode and interrupt not emulated) */
202      if ((! (mm58274c->control & ctl_intstop)) && (data & ctl_intstop))
203         /* interrupt stop */
204         mm58274c->interrupt_timer->enable(0);
205      else if ((mm58274c->control & ctl_intstop) && (! (data & ctl_intstop)))
206      {
207         /* interrupt run */
208         attotime period = interrupt_period_table(mm58274c->int_ctl & int_ctl_dly);
209
210         mm58274c->interrupt_timer->adjust(period, 0, mm58274c->int_ctl & int_ctl_rpt ? period : attotime::zero);
211      }
212      if (data & ctl_clkstop)
213         /* stopping the clock clears the tenth counter */
214         mm58274c->tenths = 0;
215      mm58274c->control = data;
216      break;
217
218   case 0x1:   /* Tenths of Seconds: cannot be written */
219      break;
220
221   case 0x2:   /* Units Seconds */
222      mm58274c->seconds2 = data;
223      break;
224
225   case 0x3:   /* Tens Seconds */
226      mm58274c->seconds1 = data;
227      break;
228
229   case 0x4:   /* Units Minutes */
230      mm58274c->minutes2 = data;
231      break;
232
233   case 0x5:   /* Tens Minutes */
234      mm58274c->minutes1 = data;
235      break;
236
237   case 0x6:   /* Units Hours */
238      mm58274c->hours2 = data;
239      break;
240
241   case 0x7:   /* Tens Hours */
242      mm58274c->hours1 = data;
243      break;
244
245   case 0x8:   /* Units Days */
246      mm58274c->days2 = data;
247      break;
248
249   case 0x9:   /* Tens Days */
250      mm58274c->days1 = data;
251      break;
252
253   case 0xA:   /* Units Months */
254      mm58274c->months2 = data;
255      break;
256
257   case 0xB:   /* Tens Months */
258      mm58274c->months1 = data;
259      break;
260
261   case 0xC:   /* Units Years */
262      mm58274c->years2 = data;
263      break;
264
265   case 0xD:   /* Tens Years */
266      mm58274c->years1 = data;
267      break;
268
269   case 0xE:   /* Day of Week */
270      mm58274c->wday = data;
271      break;
272
273   case 0xF:   /* Clock Setting & Interrupt Registers */
274      if (mm58274c->control & ctl_intsel)
275      {
276         /* interrupt register (not emulated) */
277         mm58274c->int_ctl = data;
278         if (! (mm58274c->control & ctl_intstop))
279         {
280            /* interrupt run */
281            attotime period = interrupt_period_table(mm58274c->int_ctl & int_ctl_dly);
282
283            mm58274c->interrupt_timer->adjust(period, 0, mm58274c->int_ctl & int_ctl_rpt ? period : attotime::zero);
284         }
285      }
286      else
287      {
288         /* clock setting register */
289         mm58274c->clk_set = data;
290         #if 0
291            if (mm58274c->clk_set & clk_set_24)
292               /* 24-hour mode */
293               mm58274c->clk_set &= ~clk_set_pm;
294         #endif
295      }
296      break;
297   }
298}
299
300
301/*
302    Set RTC interrupt flag
303*/
304static TIMER_CALLBACK(rtc_interrupt_callback)
305{
306   device_t *device = (device_t *)ptr;
307   mm58274c_t *mm58274c = get_safe_token(device);
308   mm58274c->status |= st_if;
309}
310
311
312/*
313    Increment RTC clock (timed interrupt every 1/10s)
314*/
315
316static TIMER_CALLBACK(increment_rtc)
317{
318   device_t *device = (device_t *)ptr;
319   mm58274c_t *mm58274c = get_safe_token(device);
320   if (! (mm58274c->control & ctl_clkstop))
321   {
322      mm58274c->status |= st_dcf;
323
324      if ((++mm58274c->tenths) == 10)
325      {
326         mm58274c->tenths = 0;
327
328         if ((++mm58274c->seconds2) == 10)
329         {
330            mm58274c->seconds2 = 0;
331
332            if ((++mm58274c->seconds1) == 6)
333            {
334               mm58274c->seconds1 = 0;
335
336               if ((++mm58274c->minutes2) == 10)
337               {
338                  mm58274c->minutes2 = 0;
339
340                  if ((++mm58274c->minutes1) == 6)
341                  {
342                     mm58274c->minutes1 = 0;
343
344                     if ((++mm58274c->hours2) == 10)
345                     {
346                        mm58274c->hours2 = 0;
347
348                        mm58274c->hours1++;
349                     }
350
351                     /* handle wrap-around */
352                     if ((! (mm58274c->clk_set & clk_set_24))
353                           && ((mm58274c->hours1*10 + mm58274c->hours2) == 12))
354                     {
355                        mm58274c->clk_set ^= clk_set_pm;
356                     }
357                     if ((! (mm58274c->clk_set & clk_set_24))
358                           && ((mm58274c->hours1*10 + mm58274c->hours2) == 13))
359                     {
360                        mm58274c->hours1 = 0;
361                        mm58274c->hours2 = 1;
362                     }
363
364                     if ((mm58274c->clk_set & clk_set_24)
365                        && ((mm58274c->hours1*10 + mm58274c->hours2) == 24))
366                     {
367                        mm58274c->hours1 = mm58274c->hours2 = 0;
368                     }
369
370                     /* increment day if needed */
371                     if ((mm58274c->clk_set & clk_set_24)
372                        ? ((mm58274c->hours1*10 + mm58274c->hours2) == 0)
373                        : (((mm58274c->hours1*10 + mm58274c->hours2) == 12)
374                           && (! (mm58274c->clk_set & clk_set_pm))))
375                     {
376                        int days_in_month;
377
378                        if ((++mm58274c->days2) == 10)
379                        {
380                           mm58274c->days2 = 0;
381
382                           mm58274c->days1++;
383                        }
384
385                        if ((++mm58274c->wday) == 8)
386                           mm58274c->wday = 1;
387
388                        {
389                           static const int days_in_month_array[] =
390                           {
391                              31,28,31, 30,31,30,
392                              31,31,30, 31,30,31
393                           };
394
395                           if (((mm58274c->months1*10 + mm58274c->months2) != 2) || (mm58274c->clk_set & clk_set_leap))
396                              days_in_month = days_in_month_array[mm58274c->months1*10 + mm58274c->months2 - 1];
397                           else
398                              days_in_month = 29;
399                        }
400
401
402                        if ((mm58274c->days1*10 + mm58274c->days2) == days_in_month+1)
403                        {
404                           mm58274c->days1 = 0;
405                           mm58274c->days2 = 1;
406
407                           if ((++mm58274c->months2) == 10)
408                           {
409                              mm58274c->months2 = 0;
410
411                              mm58274c->months1++;
412                           }
413
414                           if ((mm58274c->months1*10 + mm58274c->months2) == 13)
415                           {
416                              mm58274c->months1 = 0;
417                              mm58274c->months2 = 1;
418
419                              mm58274c->clk_set = (mm58274c->clk_set & ~clk_set_leap)
420                                             | ((mm58274c->clk_set + clk_set_leap_inc) & clk_set_leap);
421
422                              if ((++mm58274c->years2) == 10)
423                              {
424                                 mm58274c->years2 = 0;
425
426                                 if ((++mm58274c->years1) == 10)
427                                    mm58274c->years1 = 0;
428                              }
429                           }
430                        }
431                     }
432                  }
433               }
434            }
435         }
436      }
437   }
438}
439
440/* Device Interface */
441
442static DEVICE_START( mm58274c )
443{
444   mm58274c_t *mm58274c = get_safe_token(device);
445
446   // validate arguments
447   assert(device != NULL);
448   assert(device->tag() != NULL);
449   assert(device->static_config() != NULL);
450
451   mm58274c->intf = (const mm58274c_interface*)device->static_config();
452   // register for state saving
453   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->status);
454   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->control);
455   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->clk_set);
456   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->int_ctl);
457   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->wday);
458   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->years1);
459   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->years2);
460   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->months1);
461   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->months2);
462   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->days1);
463   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->days2);
464   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->hours1);
465   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->hours2);
466   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->minutes1);
467   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->minutes2);
468   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->seconds1);
469   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->seconds2);
470   state_save_register_item(device->machine(), "mm58274c", device->tag(), 0, mm58274c->tenths);
471
472   mm58274c->increment_rtc = device->machine().scheduler().timer_alloc(FUNC(increment_rtc), ((void*)device));
473   mm58274c->increment_rtc->adjust(attotime::zero, 0, attotime::from_msec(100));
474   mm58274c->interrupt_timer = device->machine().scheduler().timer_alloc(FUNC(rtc_interrupt_callback), ((void*)device));
475}
476
477
478static DEVICE_RESET( mm58274c )
479{
480   mm58274c_t *mm58274c = get_safe_token(device);
481   system_time systime;
482
483   /* get the current date/time from the core */
484   device->machine().current_datetime(systime);
485
486   mm58274c->clk_set = systime.local_time.year & 3 << 2;
487   if (mm58274c->intf->mode24)
488      mm58274c->clk_set |= clk_set_24;
489
490   /* The clock count starts on 1st January 1900 */
491   mm58274c->wday = 1 + ((systime.local_time.weekday - mm58274c->intf->day1)%7);
492   mm58274c->years1 = (systime.local_time.year / 10) % 10;
493   mm58274c->years2 = systime.local_time.year % 10;
494   mm58274c->months1 = (systime.local_time.month + 1) / 10;
495   mm58274c->months2 = (systime.local_time.month + 1) % 10;
496   mm58274c->days1 = systime.local_time.mday / 10;
497   mm58274c->days2 = systime.local_time.mday % 10;
498   if (!mm58274c->intf->mode24)
499   {
500      /* 12-hour mode */
501      if (systime.local_time.hour > 12)
502      {
503         systime.local_time.hour -= 12;
504         mm58274c->clk_set |= clk_set_pm;
505      }
506      if (systime.local_time.hour == 0)
507         systime.local_time.hour = 12;
508   }
509   mm58274c->hours1 = systime.local_time.hour / 10;
510   mm58274c->hours2 = systime.local_time.hour % 10;
511   mm58274c->minutes1 = systime.local_time.minute / 10;
512   mm58274c->minutes2 = systime.local_time.minute % 10;
513   mm58274c->seconds1 = systime.local_time.second / 10;
514   mm58274c->seconds2 = systime.local_time.second % 10;
515   mm58274c->tenths = 0;
516}
517
518const device_type MM58274C = &device_creator<mm58274c_device>;
519
520mm58274c_device::mm58274c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
521   : device_t(mconfig, MM58274C, "National Semiconductor MM58274C", tag, owner, clock)
522{
523   m_token = global_alloc_clear(mm58274c_t);
524}
525
526//-------------------------------------------------
527//  device_config_complete - perform any
528//  operations now that the configuration is
529//  complete
530//-------------------------------------------------
531
532void mm58274c_device::device_config_complete()
533{
534}
535
536//-------------------------------------------------
537//  device_start - device-specific startup
538//-------------------------------------------------
539
540void mm58274c_device::device_start()
541{
542   DEVICE_START_NAME( mm58274c )(this);
543}
544
545//-------------------------------------------------
546//  device_reset - device-specific reset
547//-------------------------------------------------
548
549void mm58274c_device::device_reset()
550{
551   DEVICE_RESET_NAME( mm58274c )(this);
552}
trunk/src/mess/machine/mm58274c.h
r21684r21685
1#ifndef MM58274C_H
2#define MM58274C_H
3
4/***************************************************************************
5    MACROS
6***************************************************************************/
7
8class mm58274c_device : public device_t
9{
10public:
11   mm58274c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
12   ~mm58274c_device() { global_free(m_token); }
13
14   // access to legacy token
15   void *token() const { assert(m_token != NULL); return m_token; }
16protected:
17   // device-level overrides
18   virtual void device_config_complete();
19   virtual void device_start();
20   virtual void device_reset();
21private:
22   // internal state
23   void *m_token;
24};
25
26extern const device_type MM58274C;
27
28
29/***************************************************************************
30    FUNCTION PROTOTYPES
31***************************************************************************/
32/* interface */
33/*
34    Initializes the clock chip.
35    day1 must be set to a value from 0 (sunday), 1 (monday) ...
36    to 6 (saturday) and is needed to correctly retrieve the day-of-week
37    from the host system clock.
38*/
39struct mm58274c_interface
40{
41   int mode24;     /* 24/12 mode */
42   int day1;       /* first day of week */
43};
44
45DECLARE_READ8_DEVICE_HANDLER ( mm58274c_r );
46DECLARE_WRITE8_DEVICE_HANDLER( mm58274c_w );
47
48/***************************************************************************
49    DEVICE CONFIGURATION MACROS
50***************************************************************************/
51
52#define MCFG_MM58274C_ADD(_tag, _intrf) \
53   MCFG_DEVICE_ADD(_tag, MM58274C, 0) \
54   MCFG_DEVICE_CONFIG(_intrf)
55
56#endif /* MM58274C_H */
trunk/src/mess/machine/upd7002.c
r21684r21685
1/******************************************************************************
2    uPD7002 Analogue to Digital Converter
3
4    MESS Driver By:
5
6    Gordon Jefferyes
7    mess_bbc@gjeffery.dircon.co.uk
8
9******************************************************************************/
10
11#include "emu.h"
12#include "upd7002.h"
13
14
15struct uPD7002_t
16{
17   /* Pointer to our interface */
18   const uPD7002_interface *intf;
19
20   /* Status Register
21       D0 and D1 define the currently selected input channel
22       D2 flag output
23       D3 0 = 8 bit mode   1 = 12 bit mode
24       D4 2nd MSB of conversion
25       D5     MSB of conversion
26       D6 0 = busy, 1 = not busy    (~busy)
27       D7 0 = conversion completed, 1 = conversion not completed  (~EOC)
28   */
29   int status;
30
31   /* High data byte
32       This byte contains the 8 most significant bits of the analogue to digital conversion. */
33   int data1;
34
35   /* Low data byte
36       In 12 bit mode: Bits 7 to 4 define the four low order bits of the conversion.
37       In  8 bit mode. All bits 7 to 4 are inaccurate.
38       Bits 3 to 0 are always set to low. */
39   int data0;
40
41
42   /* temporary store of the next A to D conversion */
43   int digitalvalue;
44
45   /* this counter is used to check a full end of conversion has been reached
46   if the uPD7002 is half way through one conversion and a new conversion is requested
47   the counter at the end of the first conversion will not match and not be processed
48   only then at the end of the second conversion will the conversion complete function run */
49   int conversion_counter;
50};
51
52
53/*****************************************************************************
54 Implementation
55*****************************************************************************/
56
57INLINE uPD7002_t *get_safe_token(device_t *device)
58{
59   assert(device != NULL);
60   assert(device->type() == UPD7002);
61
62   return (uPD7002_t *)downcast<uPD7002_device *>(device)->token();
63}
64
65READ8_DEVICE_HANDLER ( uPD7002_EOC_r )
66{
67   uPD7002_t *uPD7002 = get_safe_token(device);
68   return (uPD7002->status>>7)&0x01;
69}
70
71
72static TIMER_CALLBACK(uPD7002_conversioncomplete)
73{
74   device_t *device = (device_t *)ptr;
75   uPD7002_t *uPD7002 = get_safe_token(device);
76
77   int counter_value = param;
78   if (counter_value==uPD7002->conversion_counter)
79   {
80      // this really always does a 12 bit conversion
81      uPD7002->data1 = uPD7002->digitalvalue>>8;
82      uPD7002->data0 = uPD7002->digitalvalue&0xf0;
83
84      // set the status register with top 2 MSB, not busy and conversion complete
85      uPD7002->status = (uPD7002->status & 0x0f)|((uPD7002->data1 & 0xc0)>>2)|0x40;
86
87      // call the EOC function with EOC from status
88      // uPD7002_EOC_r(0) this has just been set to 0
89      if (uPD7002->intf->EOC_func) (uPD7002->intf->EOC_func)(device,0);
90      uPD7002->conversion_counter=0;
91   }
92}
93
94
95READ8_DEVICE_HANDLER ( uPD7002_r )
96{
97   uPD7002_t *uPD7002 = get_safe_token(device);
98
99   switch(offset&0x03)
100   {
101      case 0:
102         return uPD7002->status;
103
104      case 1:
105         return uPD7002->data1;
106
107      case 2: case 3:
108         return uPD7002->data0;
109   }
110   return 0;
111}
112
113
114
115WRITE8_DEVICE_HANDLER ( uPD7002_w )
116{
117   uPD7002_t *uPD7002 = get_safe_token(device);
118   /* logerror("write to uPD7002 $%02X = $%02X\n",offset,data); */
119
120   switch(offset&0x03)
121   {
122      case 0:
123      /*
124      Data Latch/AD start
125          D0 and D1 together define which one of the four input channels is selected
126          D2 flag input, normally set to 0????
127          D3 defines whether an 8 (0) or 12 (1) bit resolution conversion should occur
128          D4 to D7 not used.
129
130          an 8  bit conversion typically takes 4ms
131          an 12 bit conversion typically takes 10ms
132
133          writing to this register will initiate a conversion.
134      */
135
136      /* set D6=0 busy ,D7=1 conversion not complete */
137      uPD7002->status=(data & 0x0f) | 0x80;
138
139      // call the EOC function with EOC from status
140      // uPD7002_EOC_r(0) this has just been set to 1
141      if (uPD7002->intf->EOC_func) uPD7002->intf->EOC_func(device, 1);
142
143      /* the uPD7002 works by sampling the analogue value at the start of the conversion
144         so it is read hear and stored until the end of the A to D conversion */
145
146      // this function should return a 16 bit value.
147      uPD7002->digitalvalue = uPD7002->intf->get_analogue_func(device, uPD7002->status & 0x03);
148
149      uPD7002->conversion_counter++;
150
151      // call a timer to start the conversion
152      if (uPD7002->status & 0x08)
153      {
154         // 12 bit conversion takes 10ms
155         space.machine().scheduler().timer_set(attotime::from_msec(10), FUNC(uPD7002_conversioncomplete), uPD7002->conversion_counter, (void *)device);
156      } else {
157         // 8 bit conversion takes 4ms
158         space.machine().scheduler().timer_set(attotime::from_msec(4), FUNC(uPD7002_conversioncomplete), uPD7002->conversion_counter, (void *)device);
159      }
160      break;
161
162      case 1: case 2:
163      /* Nothing */
164      break;
165
166      case 3:
167      /* Test Mode: Used for inspecting the device, The data input-output terminals assume an input
168            state and are connected to the A/D counter. Therefore, the A/D conversion data
169            read out after this is meaningless.
170      */
171      break;
172   }
173}
174
175/* Device Interface */
176
177static DEVICE_START( uPD7002 )
178{
179   uPD7002_t *uPD7002 = get_safe_token(device);
180   // validate arguments
181
182   assert(device != NULL);
183   assert(device->tag() != NULL);
184   assert(device->static_config() != NULL);
185
186   uPD7002->intf = (const uPD7002_interface*)device->static_config();
187   uPD7002->status = 0;
188   uPD7002->data1 = 0;
189   uPD7002->data0 = 0;
190   uPD7002->digitalvalue = 0;
191   uPD7002->conversion_counter = 0;
192
193   // register for state saving
194   state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->status);
195   state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->data1);
196   state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->data0);
197   state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->digitalvalue);
198   state_save_register_item(device->machine(), "uPD7002", device->tag(), 0, uPD7002->conversion_counter);
199}
200
201static DEVICE_RESET( uPD7002 )
202{
203   uPD7002_t *uPD7002 = get_safe_token(device);
204   uPD7002->status = 0;
205   uPD7002->data1 = 0;
206   uPD7002->data0 = 0;
207   uPD7002->digitalvalue = 0;
208   uPD7002->conversion_counter = 0;
209}
210
211const device_type UPD7002 = &device_creator<uPD7002_device>;
212
213uPD7002_device::uPD7002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
214   : device_t(mconfig, UPD7002, "uPD7002", tag, owner, clock)
215{
216   m_token = global_alloc_clear(uPD7002_t);
217}
218
219//-------------------------------------------------
220//  device_config_complete - perform any
221//  operations now that the configuration is
222//  complete
223//-------------------------------------------------
224
225void uPD7002_device::device_config_complete()
226{
227}
228
229//-------------------------------------------------
230//  device_start - device-specific startup
231//-------------------------------------------------
232
233void uPD7002_device::device_start()
234{
235   DEVICE_START_NAME( uPD7002 )(this);
236}
237
238//-------------------------------------------------
239//  device_reset - device-specific reset
240//-------------------------------------------------
241
242void uPD7002_device::device_reset()
243{
244   DEVICE_RESET_NAME( uPD7002 )(this);
245}
trunk/src/mess/machine/upd7002.h
r21684r21685
1/*****************************************************************************
2 *
3 * machine/upd7002.h
4 *
5 * uPD7002 Analogue to Digital Converter
6 *
7 * Driver by Gordon Jefferyes <mess_bbc@gjeffery.dircon.co.uk>
8 *
9 ****************************************************************************/
10
11#ifndef UPD7002_H_
12#define UPD7002_H_
13
14/***************************************************************************
15    MACROS
16***************************************************************************/
17
18class uPD7002_device : public device_t
19{
20public:
21   uPD7002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
22   ~uPD7002_device() { global_free(m_token); }
23
24   // access to legacy token
25   void *token() const { assert(m_token != NULL); return m_token; }
26protected:
27   // device-level overrides
28   virtual void device_config_complete();
29   virtual void device_start();
30   virtual void device_reset();
31private:
32   // internal state
33   void *m_token;
34};
35
36extern const device_type UPD7002;
37
38
39/***************************************************************************
40    TYPE DEFINITIONS
41***************************************************************************/
42
43typedef int (*uPD7002_get_analogue_func)(device_t *device, int channel_number);
44#define UPD7002_GET_ANALOGUE(name)  int name(device_t *device, int channel_number )
45
46typedef void (*uPD7002_eoc_func)(device_t *device, int data);
47#define UPD7002_EOC(name)   void name(device_t *device, int data )
48
49
50struct uPD7002_interface
51{
52   uPD7002_get_analogue_func get_analogue_func;
53   uPD7002_eoc_func          EOC_func;
54};
55
56/***************************************************************************
57    FUNCTION PROTOTYPES
58***************************************************************************/
59
60/* Standard handlers */
61
62DECLARE_READ8_DEVICE_HANDLER ( uPD7002_EOC_r );
63DECLARE_READ8_DEVICE_HANDLER ( uPD7002_r );
64DECLARE_WRITE8_DEVICE_HANDLER ( uPD7002_w );
65
66
67/***************************************************************************
68    DEVICE CONFIGURATION MACROS
69***************************************************************************/
70
71#define MCFG_UPD7002_ADD(_tag, _intrf) \
72   MCFG_DEVICE_ADD(_tag, UPD7002, 0) \
73   MCFG_DEVICE_CONFIG(_intrf)
74
75
76#endif /* UPD7002_H_ */
trunk/src/mess/machine/ay31015.c
r21684r21685
1/****************************************************************************
2
3    ay31015.c by Robbbert, May 2008. Bugs fixed by Judge.
4
5    Code for the AY-3-1014A, AY-3-1015(D), AY-5-1013(A), and AY-6-1013 UARTs
6    The HD6402 UART is compatible with the AY-3-1015 UART.
7
8    This is cycle-accurate according to the specifications.
9
10    It supports independent receive and transmit clocks,
11    and transmission and reception can occur simultaneously if desired.
12
13*****************************************************************************
14
15Differences between the chip types:
16- All units have pull-up resistors on the inputs, except for the AY-3-1014A which is CMOS-compatible.
17- AY-3-1014A and AY-3-1015 - 1.5 stop bits mode available.
18- Max baud rate of 30k, except AY-5-1013 which has 20k.
19- AY-5-1013 has extended temperature ratings.
20- AY-5-1013 and AY-6-1013 require a -12 volt supply on pin 2. Pin is not used otherwise.
21- AY-5-1013 and AY-6-1013 do not reset the received data register when XR pin is used.
22
23******************************************************************************
24
25It is not clear in the documentation as to which settings will reset the device.
26    To be safe, we will always reset whenever the control register changes.
27
28    Also, it not clear exactly what happens under various error conditions.
29
30********************************************************************************
31
32Device Data:
33
34* Common Controls:
35-- Pin 1 - Vcc - 5 volts
36-- Pin 2 - not used (on AY-5-1013 and AY-6-1013 this is Voo = -12 volts)
37-- Pin 3 - Gnd - 0 volts
38-- Pin 21 - XR - External Reset - resets all registers to initial state except for the control register
39-- Pin 35 - NP - No Parity - "1" will kill any parity processing
40-- Pin 36 - TSB - Number of Stop Bits - "0" = 1 stop bit; "1" = 2 stop bits. If "1", and 5 bits per character, then we have 1.5 stop bits
41-- pin 37 - NB1
42-- pin 38 - NB2 - Number of bits per character = NB1 + (NB2 * 2) + 5
43-- pin 39 - EPS - Odd or Even Parity Select - "0" = Odd parity; "1" = Even parity. Has no effect if NP is high.
44-- Pin 34 - CS - Control Strobe - Read NP, TSB, EPS, NB1, NB2 into the control register.
45
46Format of data stream:
47Start bit (low), Bit 0, Bit 1... highest bit, Parity bit (if enabled), 1-2 stop bits (high)
48
49
50* Receiver Controls:
51-- Pin 17 - RCP - Clock which is 16x the desired baud rate
52-- Pin 20 - SI - Serial input stream - "1" = Mark (waiting for input), "0" = Space (Start bit) initiates the transfer of a byte
53-- Pin 4 - RDE - "0" causes the received data to appear on RD1 to RD8.
54-- Pins 5 to 12 - RD8 to RD1 - These are the data lines (bits 7 to 0). Data is right-justified.
55-- Pin 16 - SWE - Status word enable - causes the status bits (PE, FE, OR, DAV, TBMT) to appear at the pins.
56-- Pin 19 - DAV - "1" indicates that a byte has been received by the UART, and should now be accepted by the computer
57-- Pin 18 - RDAV - "0" will force DAV low.
58-- Pin 13 - PE - Parity error - "1" indicates that a parity error occurred
59-- Pin 14 - FE - Framing error - "1" Indicates that the stop bit was missing
60-- Pin 15 - OR - overrun - "1" indicates that a new character has become available before the computer had accepted the previous character
61
62* Transmitter controls:
63-- Pin 40 - TCP - Clock which is 16x the desired baud rate
64-- Pin 25 - SO - Serial output stream - it will stay at "1" while no data is being transmitted
65-- Pins 26 to 33 - DB1 to DB8 - These are the data lines containing the byte to be sent
66-- Pin 23 - DS - Data Strobe - "0" will copy DB1 to DB8 into the transmit buffer
67-- Pin 22 - TBMT - Transmit buffer Empty - "1" indicates to the computer that another byte may be sent to the UART
68-- Pin 24 - EOC - End of Character - "0" means that a character is being sent.
69
70******************************************* COMMON CONTROLS ********************************************************/
71
72#include "emu.h"
73#include "ay31015.h"
74
75enum state_t
76{
77   IDLE,
78   START_BIT,
79   PROCESSING,
80   PARITY_BIT,
81   FIRST_STOP_BIT,
82   SECOND_STOP_BIT,
83   PREP_TIME
84};
85
86
87struct ay31015_t
88{
89   const ay31015_config    *config;
90
91   int pins[41];
92
93   UINT8 control_reg;
94   UINT8 status_reg;
95   UINT16 second_stop_bit; // 0, 8, 16
96   UINT16 total_pulses;    // bits * 16
97   UINT8 internal_sample;
98
99   state_t rx_state;
100   UINT8 rx_data;      // byte being received
101   UINT8 rx_buffer;    // received byte waiting to be accepted by computer
102   UINT8 rx_bit_count;
103   UINT8 rx_parity;
104   UINT16 rx_pulses;   // total pulses left
105   double rx_clock;
106   emu_timer *rx_timer;
107
108   state_t tx_state;
109   UINT8 tx_data;      // byte being sent
110   UINT8 tx_buffer;    // next byte to send
111   UINT8 tx_parity;
112   UINT16 tx_pulses;   // total pulses left
113   double tx_clock;
114   emu_timer *tx_timer;
115
116   devcb_resolved_read8    read_si;                /* SI - pin 20 - This will be called whenever the SI pin is sampled. Optional */
117   devcb_resolved_write8   write_so;               /* SO - pin 25 - This will be called whenever data is put on the SO pin. Optional */
118   devcb_resolved_write8   status_changed;         /* This will be called whenever one of the status pins may have changed. Optional */
119};
120
121
122/* control reg */
123#define CONTROL_NB1     0x01
124#define CONTROL_NB2     0x02
125#define CONTROL_TSB     0x04
126#define CONTROL_EPS     0x08
127#define CONTROL_NP      0x10
128
129
130/* status reg */
131#define STATUS_TBMT     0x01
132#define STATUS_DAV      0x02
133#define STATUS_OR       0x04
134#define STATUS_FE       0x08
135#define STATUS_PE       0x10
136#define STATUS_EOC      0x20
137
138
139/*-------------------------------------------------
140    get_safe_token - safely gets the data
141-------------------------------------------------*/
142
143INLINE ay31015_t *get_safe_token(device_t *device)
144{
145   assert(device != NULL);
146   assert(device->type() == AY31015);
147   return (ay31015_t *) downcast<ay31015_device *>(device)->token();
148}
149
150
151INLINE UINT8 ay31015_get_si( device_t *device )
152{
153   ay31015_t   *ay31015 = get_safe_token( device );
154
155   if ( !ay31015->read_si.isnull() )
156      ay31015->pins[AY31015_SI] = ay31015->read_si( 0 ) ? 1 : 0;
157
158   return ay31015->pins[AY31015_SI];
159}
160
161
162INLINE void ay31015_set_so( device_t *device, int data )
163{
164   ay31015_t   *ay31015 = get_safe_token( device );
165
166   ay31015->pins[AY31015_SO] = data ? 1 : 0;
167
168   if ( !ay31015->write_so.isnull() )
169      ay31015->write_so( 0, ay31015->pins[AY31015_SO] );
170}
171
172
173INLINE int ay31015_update_status_pin( ay31015_t *ay31015, UINT8 reg_bit, ay31015_output_pin_t pin )
174{
175   int new_value = ( ay31015->status_reg & reg_bit ) ? 1 : 0;
176
177   if ( new_value == ay31015->pins[pin] )
178      return 0;
179
180   ay31015->pins[pin] = new_value;
181   return 1;
182}
183
184
185/*-------------------------------------------------
186    ay31015_update_status_pins - Update the status pins
187-------------------------------------------------*/
188static void ay31015_update_status_pins( device_t *device )
189{
190   ay31015_t   *ay31015 = get_safe_token( device );
191   int status_pins_changed = 0;
192
193   /* Should status pins be updated? */
194   if ( ! ay31015->pins[AY31015_SWE] )
195   {
196      status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_PE, AY31015_PE );
197      status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_FE, AY31015_FE );
198      status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_OR, AY31015_OR );
199      status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_DAV, AY31015_DAV );
200      status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_TBMT, AY31015_TBMT );
201   }
202   status_pins_changed += ay31015_update_status_pin( ay31015, STATUS_EOC, AY31015_EOC );
203
204   if ( status_pins_changed && !ay31015->status_changed.isnull() )
205   {
206      ay31015->status_changed( 0, status_pins_changed );
207   }
208}
209
210
211/*************************************************** RECEIVE CONTROLS *************************************************/
212
213
214/*-------------------------------------------------
215    ay31015_rx_process - convert serial to parallel
216-------------------------------------------------*/
217static TIMER_CALLBACK( ay31015_rx_process )
218{
219   device_t *device = (device_t *)ptr;
220   ay31015_t           *ay31015 = get_safe_token( device );
221
222   switch (ay31015->rx_state)
223   {
224      case PREP_TIME:                         // assist sync by ensuring high bit occurs
225         ay31015->rx_pulses--;
226         if (ay31015_get_si( device ))
227            ay31015->rx_state = IDLE;
228         return;
229
230      case IDLE:
231         ay31015->rx_pulses--;
232         if (!ay31015_get_si( device ))
233         {
234            ay31015->rx_state = START_BIT;
235            ay31015->rx_pulses = 16;
236         }
237         return;
238
239      case START_BIT:
240         ay31015->rx_pulses--;
241         if (ay31015->rx_pulses == 8)            // start bit must be low at sample time
242         {
243            if ( ay31015_get_si( device ) )
244               ay31015->rx_state = IDLE;
245         }
246         else
247         if (!ay31015->rx_pulses)                    // end of start bit
248         {
249            ay31015->rx_state = PROCESSING;
250            ay31015->rx_pulses = ay31015->total_pulses;
251            ay31015->rx_bit_count = 0;
252            ay31015->rx_parity = 0;
253            ay31015->rx_data = 0;
254         }
255         return;
256
257      case PROCESSING:
258         ay31015->rx_pulses--;
259         if (!ay31015->rx_pulses)                    // end of a byte
260         {
261            ay31015->rx_pulses = 16;
262            if (ay31015->control_reg & CONTROL_NP)      // see if we need to get a parity bit
263               ay31015->rx_state = FIRST_STOP_BIT;
264            else
265               ay31015->rx_state = PARITY_BIT;
266         }
267         else
268         if (!(ay31015->rx_pulses & 15))             // end of a bit
269            ay31015->rx_bit_count++;
270         else
271         if ((ay31015->rx_pulses & 15) == 8)             // sample input stream
272         {
273            ay31015->internal_sample = ay31015_get_si( device );
274            ay31015->rx_parity ^= ay31015->internal_sample;     // calculate cumulative parity
275            ay31015->rx_data |= ay31015->internal_sample << ay31015->rx_bit_count;
276         }
277         return;
278
279      case PARITY_BIT:
280         ay31015->rx_pulses--;
281
282         if (ay31015->rx_pulses == 8)                    // sample input stream
283         {
284            ay31015->rx_parity ^= ay31015_get_si( device );             // calculate cumulative parity
285         }
286         else
287         if (!ay31015->rx_pulses)                    // end of a byte
288         {
289            ay31015->rx_pulses = 16;
290            ay31015->rx_state = FIRST_STOP_BIT;
291
292            if ((!(ay31015->control_reg & CONTROL_EPS)) && (ay31015->rx_parity))
293               ay31015->rx_parity = 0;         // odd parity, ok
294            else
295            if ((ay31015->control_reg & CONTROL_EPS) && (!ay31015->rx_parity))
296               ay31015->rx_parity = 0;         // even parity, ok
297            else
298               ay31015->rx_parity = 1;         // parity error
299         }
300         return;
301
302      case FIRST_STOP_BIT:
303         ay31015->rx_pulses--;
304         if (ay31015->rx_pulses == 8)                // sample input stream
305            ay31015->internal_sample = ay31015_get_si( device );
306         else
307         if (ay31015->rx_pulses == 7)                // set error flags
308         {
309            if (!ay31015->internal_sample)
310            {
311               ay31015->status_reg |= STATUS_FE;       // framing error - the stop bit not high
312               ay31015->rx_state = PREP_TIME;      // lost sync - start over
313         //      return;
314            }
315            else
316               ay31015->status_reg &= ~STATUS_FE;
317
318            if ((ay31015->rx_parity) && (!(ay31015->control_reg & CONTROL_NP)))
319               ay31015->status_reg |= STATUS_PE;       // parity error
320            else
321               ay31015->status_reg &= ~STATUS_PE;
322
323            if (ay31015->status_reg & STATUS_DAV)
324               ay31015->status_reg |= STATUS_OR;       // overrun error - previous byte still in buffer
325            else
326               ay31015->status_reg &= ~STATUS_OR;
327
328            ay31015->rx_buffer = ay31015->rx_data;      // bring received byte out for computer to read
329
330            ay31015_update_status_pins( device );
331         }
332         else
333         if (ay31015->rx_pulses == 6)
334         {
335            ay31015->status_reg |= STATUS_DAV;      // tell computer that new byte is ready
336            ay31015_update_status_pins( device );
337         }
338         else
339         if (ay31015->rx_pulses == 4)
340         {
341            if (ay31015->second_stop_bit)
342            {
343               /* We should wait for the full first stop bit and
344                  the beginning of the second stop bit */
345               ay31015->rx_state = SECOND_STOP_BIT;
346               ay31015->rx_pulses += ay31015->second_stop_bit - 7;
347            }
348            else
349            {
350               /* We have seen a STOP bit, go back to PREP_TIME */
351               ay31015->rx_state = PREP_TIME;
352            }
353         }
354         return;
355
356      case SECOND_STOP_BIT:
357         ay31015->rx_pulses--;
358         if (!ay31015->rx_pulses)
359            ay31015->rx_state = PREP_TIME;
360         return;
361
362   }
363}
364
365
366/*************************************************** TRANSMIT CONTROLS *************************************************/
367
368
369/*-------------------------------------------------
370    ay31015_tx_process - convert parallel to serial
371-------------------------------------------------*/
372static TIMER_CALLBACK( ay31015_tx_process )
373{
374   device_t *device = (device_t *)ptr;
375   ay31015_t           *ay31015 = get_safe_token( device );
376
377   UINT8 t1;
378   switch (ay31015->tx_state)
379   {
380      case IDLE:
381         if (!(ay31015->status_reg & STATUS_TBMT))
382         {
383            ay31015->tx_state = PREP_TIME;      // When idle, see if a byte has been sent to us
384            ay31015->tx_pulses = 1;
385         }
386         return;
387
388      case PREP_TIME:                     // This phase lets the transmitter regain sync after an idle period
389         ay31015->tx_pulses--;
390         if (!ay31015->tx_pulses)
391         {
392            ay31015->tx_state = START_BIT;
393            ay31015->tx_pulses = 16;
394         }
395         return;
396
397      case START_BIT:
398         if (ay31015->tx_pulses == 16)               // beginning of start bit
399         {
400            ay31015->tx_data = ay31015->tx_buffer;          // load the shift register
401            ay31015->status_reg |= STATUS_TBMT;         // tell computer that another byte can be sent to uart
402            ay31015_set_so( device, 0 );                /* start bit begins now (we are "spacing") */
403            ay31015->status_reg &= ~STATUS_EOC;         // we are no longer idle
404            ay31015->tx_parity = 0;
405            ay31015_update_status_pins( device );
406         }
407
408         ay31015->tx_pulses--;
409         if (!ay31015->tx_pulses)                    // end of start bit
410         {
411            ay31015->tx_state = PROCESSING;
412            ay31015->tx_pulses = ay31015->total_pulses;
413         }
414         return;
415
416      case PROCESSING:
417         if (!(ay31015->tx_pulses & 15))             // beginning of a data bit
418         {
419            if (ay31015->tx_data & 1)
420            {
421               ay31015_set_so( device, 1 );
422               ay31015->tx_parity++;               // calculate cumulative parity
423            }
424            else
425               ay31015_set_so( device, 0 );
426
427            ay31015->tx_data >>= 1;             // adjust the shift register
428         }
429
430         ay31015->tx_pulses--;
431         if (!ay31015->tx_pulses)                    // all data bits sent
432         {
433            ay31015->tx_pulses = 16;
434            if (ay31015->control_reg & CONTROL_NP)      // see if we need to make a parity bit
435               ay31015->tx_state = FIRST_STOP_BIT;
436            else
437               ay31015->tx_state = PARITY_BIT;
438         }
439
440         return;
441
442      case PARITY_BIT:
443         if (ay31015->tx_pulses == 16)
444         {
445            t1 = (ay31015->control_reg & CONTROL_EPS) ? 0 : 1;
446            t1 ^= (ay31015->tx_parity & 1);
447            if (t1)
448               ay31015_set_so( device, 1 );            /* extra bit to set the correct parity */
449            else
450               ay31015_set_so( device, 0 );            /* it was already correct */
451         }
452
453         ay31015->tx_pulses--;
454         if (!ay31015->tx_pulses)
455         {
456            ay31015->tx_state = FIRST_STOP_BIT;
457            ay31015->tx_pulses = 16;
458         }
459         return;
460
461      case FIRST_STOP_BIT:
462         if (ay31015->tx_pulses == 16)
463            ay31015_set_so( device, 1 );                /* create a stop bit (marking and soon idle) */
464         ay31015->tx_pulses--;
465         if (!ay31015->tx_pulses)
466         {
467            ay31015->status_reg |= STATUS_EOC;          // character is completely sent
468            if (ay31015->second_stop_bit)
469            {
470               ay31015->tx_state = SECOND_STOP_BIT;
471               ay31015->tx_pulses = ay31015->second_stop_bit;
472            }
473            else
474            if (ay31015->status_reg & STATUS_TBMT)
475               ay31015->tx_state = IDLE;           // if nothing to send, go idle
476            else
477            {
478               ay31015->tx_pulses = 16;
479               ay31015->tx_state = START_BIT;      // otherwise immediately start next byte
480            }
481            ay31015_update_status_pins( device );
482         }
483         return;
484
485      case SECOND_STOP_BIT:
486         ay31015->tx_pulses--;
487         if (!ay31015->tx_pulses)
488         {
489            if (ay31015->status_reg & STATUS_TBMT)
490               ay31015->tx_state = IDLE;           // if nothing to send, go idle
491            else
492            {
493               ay31015->tx_pulses = 16;
494               ay31015->tx_state = START_BIT;      // otherwise immediately start next byte
495            }
496         }
497         return;
498
499   }
500}
501
502
503/*-------------------------------------------------
504    ay31015_reset - reset internal state
505-------------------------------------------------*/
506static void ay31015_reset( device_t *device )
507{
508   ay31015_t   *ay31015 = get_safe_token( device );
509
510   /* total pulses = 16 * data-bits */
511   UINT8 t1;
512
513   if ( ay31015->control_reg & CONTROL_NB2 )
514      t1 = ( ay31015->control_reg & CONTROL_NB1 ) ? 8 : 7;
515   else
516      t1 = ( ay31015->control_reg & CONTROL_NB1 ) ? 6 : 5;
517
518   ay31015->total_pulses = t1 << 4;                    /* total clock pulses to load a byte */
519   ay31015->second_stop_bit = ((ay31015->control_reg & CONTROL_TSB) ? 16 : 0);     /* 2nd stop bit */
520   if ((t1 == 5) && (ay31015->second_stop_bit == 16))
521      ay31015->second_stop_bit = 8;               /* 5 data bits and 2 stop bits = 1.5 stop bits */
522   ay31015->status_reg = STATUS_EOC | STATUS_TBMT;
523   ay31015->tx_data = 0;
524   ay31015->rx_state = PREP_TIME;
525   ay31015->tx_state = IDLE;
526   ay31015->pins[AY31015_SI] = 1;
527   ay31015_set_so( device, 1 );
528
529   if ( ay31015->config->type == AY_3_1015 )
530      ay31015->rx_data = 0;
531
532}
533
534
535/*-------------------------------------------------
536    ay31015_transfer_control_pins - transfers contents of controls pins to the control register
537-------------------------------------------------*/
538static void ay31015_transfer_control_pins( device_t *device )
539{
540   ay31015_t   *ay31015 = get_safe_token( device );
541   UINT8 control = 0;
542
543   control |= ay31015->pins[AY31015_NP ] ? CONTROL_NP  : 0;
544   control |= ay31015->pins[AY31015_TSB] ? CONTROL_TSB : 0;
545   control |= ay31015->pins[AY31015_NB1] ? CONTROL_NB1 : 0;
546   control |= ay31015->pins[AY31015_NB2] ? CONTROL_NB2 : 0;
547   control |= ay31015->pins[AY31015_EPS] ? CONTROL_EPS : 0;
548
549   if ( ay31015->control_reg != control )
550   {
551      ay31015->control_reg = control;
552      ay31015_reset( device );
553   }
554}
555
556
557/*-------------------------------------------------
558    ay31015_set_input_pin - set an input pin
559-------------------------------------------------*/
560void ay31015_set_input_pin( device_t *device, ay31015_input_pin_t pin, int data )
561{
562   ay31015_t   *ay31015 = get_safe_token(device);
563
564   data = data ? 1 : 0;
565
566   switch ( pin )
567   {
568   case AY31015_SWE:
569      ay31015->pins[pin] = data;
570      ay31015_update_status_pins( device );
571      break;
572   case AY31015_RDAV:
573      ay31015->pins[pin] = data;
574      if ( ! data )
575      {
576         ay31015->status_reg &= ~STATUS_DAV;
577         ay31015->pins[AY31015_DAV] = 0;
578      }
579      break;
580   case AY31015_SI:
581      ay31015->pins[pin] = data;
582      break;
583   case AY31015_XR:
584      ay31015->pins[pin] = data;
585      if ( data )
586         ay31015_reset( device );
587      break;
588   case AY31015_CS:
589   case AY31015_NP:
590   case AY31015_TSB:
591   case AY31015_NB1:
592   case AY31015_NB2:
593   case AY31015_EPS:
594      ay31015->pins[pin] = data;
595      if ( ay31015->pins[AY31015_CS] )
596         ay31015_transfer_control_pins( device );
597      break;
598   }
599}
600
601
602/*-------------------------------------------------
603    ay31015_get_output_pin - get the status of an output pin
604-------------------------------------------------*/
605int ay31015_get_output_pin( device_t *device, ay31015_output_pin_t pin )
606{
607   ay31015_t   *ay31015 = get_safe_token(device);
608
609   return ay31015->pins[pin];
610}
611
612
613INLINE void ay31015_update_rx_timer( device_t *device )
614{
615   ay31015_t   *ay31015 = get_safe_token( device );
616
617   if ( ay31015->rx_clock > 0.0 )
618   {
619      ay31015->rx_timer->adjust( attotime::from_hz( ay31015->rx_clock ), 0, attotime::from_hz( ay31015->rx_clock ) );
620   }
621   else
622   {
623      ay31015->rx_timer->enable( 0 );
624   }
625}
626
627
628INLINE void ay31015_update_tx_timer( device_t *device )
629{
630   ay31015_t   *ay31015 = get_safe_token( device );
631
632   if ( ay31015->tx_clock > 0.0 )
633   {
634      ay31015->tx_timer->adjust( attotime::from_hz( ay31015->tx_clock ), 0, attotime::from_hz( ay31015->tx_clock ) );
635   }
636   else
637   {
638      ay31015->tx_timer->enable( 0 );
639   }
640}
641
642
643/*-------------------------------------------------
644    ay31015_set_receiver_clock - set receive clock
645-------------------------------------------------*/
646void ay31015_set_receiver_clock( device_t *device, double new_clock )
647{
648   ay31015_t   *ay31015 = get_safe_token(device);
649
650   ay31015->rx_clock = new_clock;
651   ay31015_update_rx_timer( device );
652}
653
654
655/*-------------------------------------------------
656    ay31015_set_transmitter_clock - set transmit clock
657-------------------------------------------------*/
658void ay31015_set_transmitter_clock( device_t *device, double new_clock )
659{
660   ay31015_t   *ay31015 = get_safe_token(device);
661
662   ay31015->tx_clock = new_clock;
663   ay31015_update_tx_timer( device );
664}
665
666
667/*-------------------------------------------------
668    ay31015_get_received_data - return a byte to the computer
669-------------------------------------------------*/
670UINT8 ay31015_get_received_data( device_t *device )
671{
672   ay31015_t   *ay31015 = get_safe_token(device);
673
674   return ay31015->rx_buffer;
675}
676
677
678/*-------------------------------------------------
679    ay31015_set_transmit_data - accept a byte to transmit, if able
680-------------------------------------------------*/
681void ay31015_set_transmit_data( device_t *device, UINT8 data )
682{
683   ay31015_t   *ay31015 = get_safe_token(device);
684
685   if (ay31015->status_reg & STATUS_TBMT)
686   {
687      ay31015->tx_buffer = data;
688      ay31015->status_reg &= ~STATUS_TBMT;
689      ay31015_update_status_pins( device );
690   }
691}
692
693
694static DEVICE_START(ay31015)
695{
696   ay31015_t   *ay31015 = get_safe_token(device);
697
698   ay31015->config = (const ay31015_config*)device->static_config();
699
700   ay31015->read_si.resolve(ay31015->config->read_si_cb, *device);
701   ay31015->write_so.resolve(ay31015->config->write_so_cb, *device);
702   ay31015->status_changed.resolve(ay31015->config->status_changed_cb, *device);
703
704   ay31015->tx_clock = ay31015->config->transmitter_clock;
705   ay31015->rx_clock = ay31015->config->receiver_clock;
706
707   ay31015->rx_timer = device->machine().scheduler().timer_alloc(FUNC(ay31015_rx_process), (void *)device );
708   ay31015->tx_timer = device->machine().scheduler().timer_alloc(FUNC(ay31015_tx_process), (void *)device );
709
710   ay31015_update_rx_timer( device );
711   ay31015_update_tx_timer( device );
712}
713
714
715static DEVICE_RESET( ay31015 )
716{
717   ay31015_t   *ay31015 = get_safe_token(device);
718
719   ay31015->control_reg = 0;
720   ay31015->rx_data = 0;
721
722   ay31015_reset( device );
723}
724
725
726const device_type AY31015 = &device_creator<ay31015_device>;
727
728ay31015_device::ay31015_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
729   : device_t(mconfig, AY31015, "AY-3-1015", tag, owner, clock)
730{
731   m_token = global_alloc_clear(ay31015_t);
732}
733
734//-------------------------------------------------
735//  device_config_complete - perform any
736//  operations now that the configuration is
737//  complete
738//-------------------------------------------------
739
740void ay31015_device::device_config_complete()
741{
742}
743
744//-------------------------------------------------
745//  device_start - device-specific startup
746//-------------------------------------------------
747
748void ay31015_device::device_start()
749{
750   DEVICE_START_NAME( ay31015 )(this);
751}
752
753//-------------------------------------------------
754//  device_reset - device-specific reset
755//-------------------------------------------------
756
757void ay31015_device::device_reset()
758{
759   DEVICE_RESET_NAME( ay31015 )(this);
760}
trunk/src/mess/machine/ay31015.h
r21684r21685
1/* ay31015.h
2
3    Written for MESS by Robbbert on May 29th, 2008.
4
5*/
6
7#ifndef __AY31015_H_
8#define __AY31015_H_
9
10/***************************************************************************
11    TYPE DEFINITIONS
12***************************************************************************/
13
14
15enum ay31015_type_t
16{
17   /* For AY-3-1014A, AY-3-1015(D) and HD6402 variants */
18   AY_3_1015,
19
20   /* For AY-3-1014, AY-5-1013 and AY-6-1013 variants */
21   AY_5_1013
22};
23
24
25enum ay31015_input_pin_t
26{
27   AY31015_SWE=16,         /* -SWE  - Pin 16 - Status word enable */
28   AY31015_RDAV=18,        /* -RDAV - Pin 18 - Reset data available */
29   AY31015_SI=20,          /*  SI   - Pin 20 - Serial input */
30   AY31015_XR=21,          /*  XR   - Pin 21 - External reset */
31   AY31015_CS=34,          /*  CS   - Pin 34 - Control strobe */
32   AY31015_NP=35,          /*  NP   - Pin 35 - No parity */
33   AY31015_TSB=36,         /*  TSB  - Pin 36 - Number of stop bits */
34   AY31015_NB1=37,         /*  NB1  - Pin 37 - Number of bits #1 */
35   AY31015_NB2=38,         /*  NB2  - Pin 38 - Number of bits #2 */
36   AY31015_EPS=39          /*  EPS  - Pin 39 - Odd/Even parity select */
37};
38
39
40enum ay31015_output_pin_t
41{
42   AY31015_PE=13,          /* PE   - Pin 13 - Parity error */
43   AY31015_FE=14,          /* FE   - Pin 14 - Framing error */
44   AY31015_OR=15,          /* OR   - Pin 15 - Over-run */
45   AY31015_DAV=19,         /* DAV  - Pin 19 - Data available */
46   AY31015_TBMT=22,        /* TBMT - Pin 22 - Transmit buffer empty */
47   AY31015_EOC=24,         /* EOC  - Pin 24 - End of character */
48   AY31015_SO=25           /* SO   - Pin 25 - Serial output */
49};
50
51
52struct  ay31015_config
53{
54   ay31015_type_t      type;                   /* Type of chip */
55   double              transmitter_clock;      /* TCP - pin 40 */
56   double              receiver_clock;         /* RCP - pin 17 */
57   devcb_read8         read_si_cb;             /* SI - pin 20 - This will be called whenever the SI pin is sampled. Optional */
58   devcb_write8        write_so_cb;                /* SO - pin 25 - This will be called whenever data is put on the SO pin. Optional */
59   devcb_write8        status_changed_cb;          /* This will be called whenever one of the status pins may have changed. Optional */
60};
61
62
63/***************************************************************************
64    DEVICE CONFIGURATION MACROS
65***************************************************************************/
66
67#define MCFG_AY31015_ADD(_tag, _config) \
68   MCFG_DEVICE_ADD(_tag, AY31015, 0)       \
69   MCFG_DEVICE_CONFIG(_config)
70
71
72/***************************************************************************
73    FUNCTION PROTOTYPES
74***************************************************************************/
75
76/* Set an input pin */
77void ay31015_set_input_pin( device_t *device, ay31015_input_pin_t pin, int data );
78
79
80/* Get an output pin */
81int ay31015_get_output_pin( device_t *device, ay31015_output_pin_t pin );
82
83
84/* Set a new transmitter clock (new_clock is in Hz) */
85void ay31015_set_transmitter_clock( device_t *device, double new_clock );
86
87
88/* Set a new receiver clock (new_clock is in Hz) */
89void ay31015_set_receiver_clock( device_t *device, double new_clock );
90
91
92/* Reead the received data */
93/* The received data is available on RD8-RD1 (pins 5-12) */
94UINT8 ay31015_get_received_data( device_t *device );
95
96
97/* Set the transmitter buffer */
98/* The data to transmit is set on DB1-DB8 (pins 26-33) */
99void ay31015_set_transmit_data( device_t *device, UINT8 data );
100
101
102/***************************************************************************
103    DEVICE INTERFACE
104***************************************************************************/
105
106class ay31015_device : public device_t
107{
108public:
109   ay31015_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
110   ~ay31015_device() { global_free(m_token); }
111
112   // access to legacy token
113   void *token() const { assert(m_token != NULL); return m_token; }
114protected:
115   // device-level overrides
116   virtual void device_config_complete();
117   virtual void device_start();
118   virtual void device_reset();
119private:
120   // internal state
121   void *m_token;
122};
123
124extern const device_type AY31015;
125
126#endif
trunk/src/mess/machine/mc6843.c
r21684r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2007
4
5  Motorola 6843 Floppy Disk Controller emulation.
6
7**********************************************************************/
8
9/*
10  Main MC 6843 features are:
11   - single density floppies
12   - IBM 3740 compatible
13   - DMA-able
14   - high-level commands (including multi-sector read/write)
15
16   CLONES: HD 46503S seems to be a clone of MC 6843
17
18   BUGS
19   The driver was designed with Thomson computer emulation in mind
20   (CD 90-015 5"1/4 floppy controller) and works in this context.
21   It might work in other contexts but has currently shortcomings:
22   - DMA is not emulated
23   - Free-Format Read is not emulated
24   - Free-Format Write only supports track formatting, in a specific
25   format (FWF=1, Thomson-like sector formats)
26   - very rough timing: basically, there is a fixed delay between
27   a command request (CMR write) and its response (first byte
28   available, seek complete, etc.); there is no delay between
29   read / write
30 */
31
32
33#include "emu.h"
34#include "mc6843.h"
35#include "imagedev/flopdrv.h"
36
37
38/******************* parameters ******************/
39
40#define VERBOSE 0
41
42
43/******************* internal chip data structure ******************/
44
45struct mc6843_t
46{
47   /* interface */
48   const mc6843_interface* iface;
49
50   /* registers */
51   UINT8 CTAR;       /* current track */
52   UINT8 CMR;        /* command */
53   UINT8 ISR;        /* interrupt status */
54   UINT8 SUR;        /* set-up */
55   UINT8 STRA;       /* status */
56   UINT8 STRB;       /* status */
57   UINT8 SAR;        /* sector address */
58   UINT8 GCR;        /* general count */
59   UINT8 CCR;        /* CRC control */
60   UINT8 LTAR;       /* logical address track (=track destination) */
61
62   /* internal state */
63   UINT8  drive;
64   UINT8  side;
65   UINT8  data[128];   /* sector buffer */
66   UINT32 data_size;   /* size of data */
67   UINT32 data_idx;    /* current read/write position in data */
68   UINT32 data_id;     /* chrd_id for sector write */
69   UINT8  index_pulse;
70
71   /* trigger delayed actions (bottom halves) */
72   emu_timer* timer_cont;
73
74};
75
76
77
78/* macro-command numbers */
79#define CMD_STZ 0x2 /* seek track zero */
80#define CMD_SEK 0x3 /* seek */
81#define CMD_SSR 0x4 /* single sector read */
82#define CMD_SSW 0x5 /* single sector write */
83#define CMD_RCR 0x6 /* read CRC */
84#define CMD_SWD 0x7 /* single sector write with delete data mark */
85#define CMD_MSW 0xd /* multiple sector write */
86#define CMD_MSR 0xc /* multiple sector read */
87#define CMD_FFW 0xb /* free format write */
88#define CMD_FFR 0xa /* free format read */
89
90/* coarse delays */
91#define DELAY_SEEK   attotime::from_usec( 100 )  /* track seek time */
92#define DELAY_ADDR   attotime::from_usec( 100 )  /* search-address time */
93
94
95
96static const char *const mc6843_cmd[16] =
97{
98   "---", "---", "STZ", "SEK", "SSR", "SSW", "RCR", "SWD",
99   "---", "---", "FFR", "FFW", "MSR", "MSW", "---", "---",
100};
101
102
103/******************* utility function and macros ********************/
104
105#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
106
107
108
109INLINE mc6843_t* get_safe_token( device_t *device )
110{
111   assert( device != NULL );
112   assert( device->type() == MC6843 );
113   return (mc6843_t*) downcast<mc6843_device *>(device)->token();
114}
115
116
117/************************** floppy interface ****************************/
118
119
120
121static device_t* mc6843_floppy_image ( device_t *device )
122{
123   mc6843_t* mc6843 = get_safe_token( device );
124   return floppy_get_device( device->machine(), mc6843->drive );
125}
126
127
128
129void mc6843_set_drive( device_t *device, int drive )
130{
131   mc6843_t* mc6843 = get_safe_token( device );
132   mc6843->drive = drive;
133}
134
135
136
137void mc6843_set_side( device_t *device, int side )
138{
139   mc6843_t* mc6843 = get_safe_token( device );
140   mc6843->side = side;
141}
142
143
144
145/* called after ISR or STRB has changed */
146static void mc6843_status_update( device_t *device )
147{
148   mc6843_t* mc6843 = get_safe_token( device );
149   int irq = 0;
150
151   /* ISR3 */
152   if ( (mc6843->CMR & 0x40) || ! mc6843->STRB )
153      mc6843->ISR &= ~8;
154   else
155      mc6843->ISR |=  8;
156
157   /* interrupts */
158   if ( mc6843->ISR & 4 )
159      irq = 1; /* unmaskable */
160   if ( ! (mc6843->CMR & 0x80) )
161   {
162      /* maskable */
163      if ( mc6843->ISR & ~4 )
164         irq = 1;
165   }
166
167   if ( mc6843->iface->irq_func )
168   {
169      mc6843->iface->irq_func( device, irq );
170      LOG(( "mc6843_status_update: irq=%i (CMR=%02X, ISR=%02X)\n", irq, mc6843->CMR, mc6843->ISR ));
171   }
172}
173
174
175void mc6843_set_index_pulse  ( device_t *device, int index_pulse )
176{
177   mc6843_t* mc6843 = get_safe_token( device );
178   mc6843->index_pulse = index_pulse;
179}
180
181
182/* called at end of command */
183static void mc6843_cmd_end( device_t *device )
184{
185   mc6843_t* mc6843 = get_safe_token( device );
186   int cmd = mc6843->CMR & 0x0f;
187   if ( ( cmd == CMD_STZ ) || ( cmd == CMD_SEK ) )
188   {
189      mc6843->ISR |= 0x02; /* set Settling Time Complete */
190   }
191   else
192   {
193      mc6843->ISR |= 0x01;  /* set Macro Command Complete */
194   }
195   mc6843->STRA &= ~0x80; /* clear Busy */
196   mc6843->CMR  &=  0xf0; /* clear command */
197   mc6843_status_update( device );
198}
199
200
201
202/* Seek Track Zero bottom half */
203static void mc6843_finish_STZ( device_t *device )
204{
205   mc6843_t* mc6843 = get_safe_token( device );
206   device_t* img = mc6843_floppy_image( device );
207   int i;
208
209   /* seek to track zero */
210   for ( i=0; i<83; i++ )
211   {
212      if (floppy_tk00_r(img) == CLEAR_LINE)
213         break;
214      floppy_drive_seek( img, -1 );
215   }
216
217   LOG(( "%f mc6843_finish_STZ: actual=%i\n", device->machine().time().as_double(), floppy_drive_get_current_track( img ) ));
218
219   /* update state */
220   mc6843->CTAR = 0;
221   mc6843->GCR = 0;
222   mc6843->SAR = 0;
223   mc6843->STRB |= floppy_tk00_r(img) << 4;
224
225   mc6843_cmd_end( device );
226}
227
228
229
230/* Seek bottom half */
231static void mc6843_finish_SEK( device_t *device )
232{
233   mc6843_t* mc6843 = get_safe_token( device );
234   device_t* img = mc6843_floppy_image( device );
235
236   /* seek to track */
237   floppy_drive_seek( img, mc6843->GCR - mc6843->CTAR );
238
239   LOG(( "%f mc6843_finish_SEK: from %i to %i (actual=%i)\n", device->machine().time().as_double(), mc6843->CTAR, mc6843->GCR, floppy_drive_get_current_track( img ) ));
240
241   /* update state */
242   mc6843->CTAR = mc6843->GCR;
243   mc6843->SAR = 0;
244   mc6843_cmd_end( device );
245}
246
247
248
249/* preamble to all sector read / write commands, returns 1 if found */
250static int mc6843_address_search( device_t *device, chrn_id* id )
251{
252   mc6843_t* mc6843 = get_safe_token( device );
253   device_t* img = mc6843_floppy_image( device );
254   int r = 0;
255
256   while ( 1 )
257   {
258      if ( ( ! floppy_drive_get_next_id( img, mc6843->side, id ) ) || ( id->flags & ID_FLAG_CRC_ERROR_IN_ID_FIELD ) || ( id->N != 0 ) )
259      {
260         /* read address error */
261         LOG(( "%f mc6843_address_search: get_next_id failed\n", device->machine().time().as_double() ));
262         mc6843->STRB |= 0x0a; /* set CRC error & Sector Address Undetected */
263         mc6843_cmd_end( device );
264         return 0;
265      }
266
267      if ( id->C != mc6843->LTAR )
268      {
269         /* track mismatch */
270         LOG(( "%f mc6843_address_search: track mismatch: logical=%i real=%i\n", device->machine().time().as_double(), mc6843->LTAR, id->C ));
271         mc6843->data[0] = id->C; /* make the track number available to the CPU */
272         mc6843->STRA |= 0x20;    /* set Track Not Equal */
273         mc6843_cmd_end( device );
274         return 0;
275      }
276
277      if ( id->R == mc6843->SAR )
278      {
279         /* found! */
280         LOG(( "%f mc6843_address_search: sector %i found on track %i\n", device->machine().time().as_double(), id->R, id->C ));
281         if ( ! (mc6843->CMR & 0x20) )
282         {
283            mc6843->ISR |= 0x04; /* if no DMA, set Status Sense */
284         }
285         return 1;
286      }
287
288      if ( floppy_drive_get_flag_state( img, FLOPPY_DRIVE_INDEX ) )
289      {
290         r++;
291         if ( r >= 4 )
292         {
293            /* time-out after 3 full revolutions */
294            LOG(( "%f mc6843_address_search: no sector %i found after 3 revolutions\n", device->machine().time().as_double(), mc6843->SAR ));
295            mc6843->STRB |= 0x08; /* set Sector Address Undetected */
296            mc6843_cmd_end( device );
297            return 0;
298         }
299      }
300   }
301
302   return 0; /* unreachable */
303}
304
305
306
307/* preamble specific to read commands (adds extra checks) */
308static int mc6843_address_search_read( device_t *device, chrn_id* id )
309{
310   mc6843_t* mc6843 = get_safe_token( device );
311   if ( ! mc6843_address_search( device, id ) )
312      return 0;
313
314   if ( id->flags & ID_FLAG_CRC_ERROR_IN_DATA_FIELD )
315   {
316      LOG(( "%f mc6843_address_search_read: data CRC error\n", device->machine().time().as_double() ));
317      mc6843->STRB |= 0x06; /* set CRC error & Data Mark Undetected */
318      mc6843_cmd_end( device );
319      return 0;
320   }
321
322   if ( id->flags & ID_FLAG_DELETED_DATA )
323   {
324      LOG(( "%f mc6843_address_search_read: deleted data\n", device->machine().time().as_double() ));
325      mc6843->STRA |= 0x02; /* set Delete Data Mark Detected */
326   }
327
328   return 1;
329}
330
331
332
333
334/* Read CRC bottom half */
335static void mc6843_finish_RCR( device_t *device )
336{
337   chrn_id id;
338   if ( ! mc6843_address_search_read( device, &id ) )
339      return;
340   mc6843_cmd_end( device );
341}
342
343
344
345/* Single / Multiple Sector Read bottom half */
346static void mc6843_cont_SR( device_t *device )
347{
348   mc6843_t* mc6843 = get_safe_token( device );
349   chrn_id id;
350   device_t* img = mc6843_floppy_image( device );
351
352   /* sector seek */
353   if ( ! mc6843_address_search_read( device, &id ) )
354      return;
355
356   /* sector read */
357   floppy_drive_read_sector_data( img, mc6843->side, id.data_id, mc6843->data, 128 );
358   mc6843->data_idx = 0;
359   mc6843->data_size = 128;
360   mc6843->STRA |= 0x01;     /* set Data Transfer Request */
361   mc6843_status_update( device );
362}
363
364
365
366/* Single / Multiple Sector Write bottom half */
367static void mc6843_cont_SW( device_t *device )
368{
369   mc6843_t* mc6843 = get_safe_token( device );
370   chrn_id id;
371
372   /* sector seek */
373   if ( ! mc6843_address_search( device, &id ) )
374      return;
375
376   /* setup sector write buffer */
377   mc6843->data_idx = 0;
378   mc6843->data_size = 128;
379   mc6843->STRA |= 0x01;         /* set Data Transfer Request */
380   mc6843->data_id = id.data_id; /* for subsequent write sector command */
381   mc6843_status_update( device );
382}
383
384
385
386/* bottom halves, called to continue / finish a command after some delay */
387static TIMER_CALLBACK( mc6843_cont )
388{
389   device_t* device = (device_t*) ptr;
390   mc6843_t* mc6843 = get_safe_token( device );
391   int cmd = mc6843->CMR & 0x0f;
392
393   LOG(( "%f mc6843_cont: timer called for cmd=%s(%i)\n", device->machine().time().as_double(), mc6843_cmd[cmd], cmd ));
394
395   mc6843->timer_cont->adjust( attotime::never );
396
397   switch ( cmd )
398   {
399   case CMD_STZ: mc6843_finish_STZ( device ); break;
400   case CMD_SEK: mc6843_finish_SEK( device ); break;
401   case CMD_SSR: mc6843_cont_SR( device );    break;
402   case CMD_SSW: mc6843_cont_SW( device );    break;
403   case CMD_RCR: mc6843_finish_RCR( device ); break;
404   case CMD_SWD: mc6843_cont_SW( device );    break;
405   case CMD_MSW: mc6843_cont_SW( device );    break;
406   case CMD_MSR: mc6843_cont_SR( device );    break;
407   }
408}
409
410
411
412/************************** CPU interface ****************************/
413
414
415
416READ8_DEVICE_HANDLER ( mc6843_r )
417{
418   mc6843_t* mc6843 = get_safe_token( device );
419   UINT8 data = 0;
420
421   switch ( offset ) {
422   case 0: /* Data Input Register (DIR) */
423   {
424      int cmd = mc6843->CMR & 0x0f;
425
426      LOG(( "%f $%04x mc6843_r: data input cmd=%s(%i), pos=%i/%i, GCR=%i, ",
427            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ),
428            mc6843_cmd[cmd], cmd, mc6843->data_idx,
429            mc6843->data_size, mc6843->GCR ));
430
431      if ( cmd == CMD_SSR || cmd == CMD_MSR )
432      {
433         /* sector read */
434         assert( mc6843->data_size > 0 );
435         assert( mc6843->data_idx < mc6843->data_size );
436         assert( mc6843->data_idx < sizeof(mc6843->data) );
437         data = mc6843->data[ mc6843->data_idx ];
438         mc6843->data_idx++;
439
440         if ( mc6843->data_idx >= mc6843->data_size )
441         {
442            /* end of sector read */
443
444            mc6843->STRA &= ~0x01; /* clear Data Transfer Request */
445
446            if ( cmd == CMD_MSR )
447            {
448               /* schedule next sector in multiple sector read */
449               mc6843->GCR--;
450               mc6843->SAR++;
451               if ( mc6843->GCR == 0xff )
452               {
453                  mc6843_cmd_end( device );
454               }
455               else if ( mc6843->SAR > 26 )
456
457               {
458                  mc6843->STRB |= 0x08; /* set Sector Address Undetected */
459                  mc6843_cmd_end( device );
460               }
461               else
462               {
463                  mc6843->timer_cont->adjust( DELAY_ADDR );
464               }
465            }
466            else
467            {
468               mc6843_cmd_end( device );
469            }
470         }
471      }
472      else if ( cmd == 0 )
473      {
474         data = mc6843->data[0];
475      }
476      else
477      {
478         /* XXX TODO: other read modes */
479         data = mc6843->data[0];
480         logerror( "$%04x mc6843 read in unsupported command mode %i\n", space.machine().firstcpu->pcbase( ), cmd );
481      }
482
483      LOG(( "data=%02X\n", data ));
484
485      break;
486   }
487
488   case 1: /* Current-Track Address Register (CTAR) */
489      data = mc6843->CTAR;
490      LOG(( "%f $%04x mc6843_r: read CTAR %i (actual=%i)\n",
491            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
492            floppy_drive_get_current_track( mc6843_floppy_image( device ) ) ));
493      break;
494
495   case 2: /* Interrupt Status Register (ISR) */
496      data = mc6843->ISR;
497      LOG(( "%f $%04x mc6843_r: read ISR %02X: cmd=%scomplete settle=%scomplete sense-rq=%i STRB=%i\n",
498            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
499            (data & 1) ? "" : "not-" , (data & 2) ? "" : "not-",
500            (data >> 2) & 1, (data >> 3) & 1 ));
501
502      /* reset */
503      mc6843->ISR &= 8; /* keep STRB */
504      mc6843_status_update( device );
505      break;
506
507   case 3: /* Status Register A (STRA) */
508   {
509      /* update */
510      device_t* img = mc6843_floppy_image( device );
511      int flag = floppy_drive_get_flag_state( img, FLOPPY_DRIVE_READY);
512      mc6843->STRA &= 0xa3;
513      if ( flag & FLOPPY_DRIVE_READY )
514         mc6843->STRA |= 0x04;
515
516      mc6843->STRA |= !floppy_tk00_r(img) << 3;
517      mc6843->STRA |= !floppy_wpt_r(img) << 4;
518
519      if ( mc6843->index_pulse )
520         mc6843->STRA |= 0x40;
521
522      data = mc6843->STRA;
523      LOG(( "%f $%04x mc6843_r: read STRA %02X: data-rq=%i del-dta=%i ready=%i t0=%i wp=%i trk-dif=%i idx=%i busy=%i\n",
524            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
525            data & 1, (data >> 1) & 1, (data >> 2) & 1, (data >> 3) & 1,
526            (data >> 4) & 1, (data >> 5) & 1, (data >> 6) & 1, (data >> 7) & 1 ));
527      break;
528   }
529
530   case 4: /* Status Register B (STRB) */
531      data = mc6843->STRB;
532      LOG(( "%f $%04x mc6843_r: read STRB %02X: data-err=%i CRC-err=%i dta--mrk-err=%i sect-mrk-err=%i seek-err=%i fi=%i wr-err=%i hard-err=%i\n",
533            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
534            data & 1, (data >> 1) & 1, (data >> 2) & 1, (data >> 3) & 1,
535            (data >> 4) & 1, (data >> 5) & 1, (data >> 6) & 1, (data >> 7) & 1 ));
536
537      /* (partial) reset */
538      mc6843->STRB &= ~0xfb;
539      mc6843_status_update( device );
540      break;
541
542   case 7: /* Logical-Track Address Register (LTAR) */
543      data = mc6843->LTAR;
544      LOG(( "%f $%04x mc6843_r: read LTAR %i (actual=%i)\n",
545            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
546            floppy_drive_get_current_track( mc6843_floppy_image( device ) ) ));
547      break;
548
549   default:
550      logerror( "$%04x mc6843 invalid read offset %i\n", space.machine().firstcpu->pcbase( ), offset );
551   }
552
553   return data;
554}
555
556WRITE8_DEVICE_HANDLER ( mc6843_w )
557{
558   mc6843_t* mc6843 = get_safe_token( device );
559   switch ( offset ) {
560   case 0: /* Data Output Register (DOR) */
561   {
562      int cmd = mc6843->CMR & 0x0f;
563      int FWF = (mc6843->CMR >> 4) & 1;
564
565      LOG(( "%f $%04x mc6843_w: data output cmd=%s(%i), pos=%i/%i, GCR=%i, data=%02X\n",
566            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ),
567            mc6843_cmd[cmd], cmd, mc6843->data_idx,
568            mc6843->data_size, mc6843->GCR, data ));
569
570      if ( cmd == CMD_SSW || cmd == CMD_MSW || cmd == CMD_SWD )
571      {
572         /* sector write */
573         assert( mc6843->data_size > 0 );
574         assert( mc6843->data_idx < mc6843->data_size );
575         assert( mc6843->data_idx < sizeof(mc6843->data) );
576         mc6843->data[ mc6843->data_idx ] = data;
577         mc6843->data_idx++;
578         if ( mc6843->data_idx >= mc6843->data_size )
579         {
580            /* end of sector write */
581            device_t* img = mc6843_floppy_image( device );
582
583            LOG(( "%f $%04x mc6843_w: write sector %i\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6843->data_id ));
584
585            floppy_drive_write_sector_data(
586               img, mc6843->side, mc6843->data_id,
587               mc6843->data, mc6843->data_size,
588               (cmd == CMD_SWD) ? ID_FLAG_DELETED_DATA : 0 );
589
590            mc6843->STRA &= ~0x01; /* clear Data Transfer Request */
591
592            if ( cmd == CMD_MSW )
593            {
594               mc6843->GCR--;
595               mc6843->SAR++;
596               if ( mc6843->GCR == 0xff )
597               {
598                  mc6843_cmd_end( device );
599               }
600               else if ( mc6843->SAR > 26 )
601
602               {
603                  mc6843->STRB |= 0x08; /* set Sector Address Undetected */
604                  mc6843_cmd_end( device );
605               }
606               else
607               {
608                  mc6843->timer_cont->adjust( DELAY_ADDR );
609               }
610            }
611            else
612            {
613               mc6843_cmd_end( device );
614            }
615         }
616      }
617      else if ( (cmd == CMD_FFW) && FWF )
618      {
619         /* assume we are formatting */
620         UINT8 nibble;
621         nibble =
622            (data & 0x01) |
623            ((data & 0x04) >> 1 )|
624            ((data & 0x10) >> 2 )|
625            ((data & 0x40) >> 3 );
626
627         assert( mc6843->data_idx < sizeof(mc6843->data) );
628
629         mc6843->data[mc6843->data_idx / 2] =
630            (mc6843->data[mc6843->data_idx / 2] << 4) | nibble;
631
632         if ( (mc6843->data_idx == 0) && (mc6843->data[0] == 0xfe ) )
633         {
634            /* address mark detected */
635            mc6843->data_idx = 2;
636         }
637         else if ( mc6843->data_idx == 9 )
638         {
639            /* address id field complete */
640            if ( (mc6843->data[2] == 0) && (mc6843->data[4] == 0) )
641            {
642               /* valid address id field */
643               device_t* img = mc6843_floppy_image( device );
644               UINT8 track  = mc6843->data[1];
645               UINT8 sector = mc6843->data[3];
646               UINT8 filler = 0xe5; /* standard Thomson filler */
647               LOG(( "%f $%04x mc6843_w: address id detected track=%i sector=%i\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), track, sector));
648               floppy_drive_format_sector( img, mc6843->side, sector, track, 0, sector, 0, filler );
649            }
650            else
651            {
652               /* abort */
653               mc6843->data_idx = 0;
654            }
655         }
656         else if ( mc6843->data_idx > 0 )
657         {
658            /* accumulate address id field */
659            mc6843->data_idx++;
660         }
661      }
662      else if ( cmd == 0 )
663      {
664         /* nothing */
665      }
666      else
667      {
668         /* XXX TODO: other write modes */
669         logerror( "$%04x mc6843 write %02X in unsupported command mode %i (FWF=%i)\n", space.machine().firstcpu->pcbase( ), data, cmd, FWF );
670      }
671      break;
672   }
673
674   case 1: /* Current-Track Address Register (CTAR) */
675      mc6843->CTAR = data & 0x7f;
676      LOG(( "%f $%04x mc6843_w: set CTAR to %i %02X (actual=%i) \n",
677            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6843->CTAR, data,
678            floppy_drive_get_current_track( mc6843_floppy_image( device ) ) ));
679      break;
680
681   case 2: /* Command Register (CMR) */
682   {
683      int cmd = data & 15;
684
685      LOG(( "%f $%04x mc6843_w: set CMR to $%02X: cmd=%s(%i) FWF=%i DMA=%i ISR3-intr=%i fun-intr=%i\n",
686            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ),
687            data, mc6843_cmd[cmd], cmd, (data >> 4) & 1, (data >> 5) & 1,
688            (data >> 6) & 1, (data >> 7) & 1 ));
689
690      /* sanitize state */
691      mc6843->STRA &= ~0x81; /* clear Busy & Data Transfer Request */
692      mc6843->data_idx = 0;
693      mc6843->data_size = 0;
694
695      /* commands are initiated by updating some flags and scheduling
696         a bottom-half (mc6843_cont) after some delay */
697
698      switch (cmd)
699      {
700      case CMD_SSW:
701      case CMD_SSR:
702      case CMD_SWD:
703      case CMD_RCR:
704      case CMD_MSR:
705      case CMD_MSW:
706         mc6843->STRA |=  0x80; /* set Busy */
707         mc6843->STRA &= ~0x22; /* clear Track Not Equal & Delete Data Mark Detected */
708         mc6843->STRB &= ~0x04; /* clear Data Mark Undetected */
709         mc6843->timer_cont->adjust( DELAY_ADDR );
710         break;
711      case CMD_STZ:
712      case CMD_SEK:
713         mc6843->STRA |= 0x80; /* set Busy */
714         mc6843->timer_cont->adjust( DELAY_SEEK );
715         break;
716      case CMD_FFW:
717      case CMD_FFR:
718         mc6843->data_idx = 0;
719         mc6843->STRA |= 0x01; /* set Data Transfer Request */
720         break;
721      }
722
723      mc6843->CMR = data;
724      mc6843_status_update( device );
725      break;
726   }
727
728   case 3: /* Set-Up Register (SUR) */
729      mc6843->SUR = data;
730
731      /* assume CLK freq = 1MHz (IBM 3740 compatibility) */
732      LOG(( "%f $%04x mc6843_w: set SUR to $%02X: head settling time=%fms, track-to-track seek time=%f\n",
733            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ),
734            data, 4.096 * (data & 15), 1.024 * ((data >> 4) & 15) ));
735      break;
736
737   case 4: /* Sector Address Register (SAR) */
738      mc6843->SAR = data & 0x1f;
739      LOG(( "%f $%04x mc6843_w: set SAR to %i (%02X)\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6843->SAR, data ));
740      break;
741
742   case 5: /* General Count Register (GCR) */
743      mc6843->GCR = data & 0x7f;
744      LOG(( "%f $%04x mc6843_w: set GCR to %i (%02X)\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6843->GCR, data ));
745      break;
746
747   case 6: /* CRC Control Register (CCR) */
748      mc6843->CCR = data & 3;
749      LOG(( "%f $%04x mc6843_w: set CCR to %02X: CRC=%s shift=%i\n",
750            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data,
751            (data & 1) ? "enabled" : "disabled", (data >> 1) & 1 ));
752      break;
753
754   case 7: /* Logical-Track Address Register (LTAR) */
755      mc6843->LTAR = data & 0x7f;
756      LOG(( "%f $%04x mc6843_w: set LTAR to %i %02X (actual=%i)\n",
757            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6843->LTAR, data,
758            floppy_drive_get_current_track( mc6843_floppy_image( device ) ) ));
759      break;
760
761   default:
762      logerror( "$%04x mc6843 invalid write offset %i (data=$%02X)\n", space.machine().firstcpu->pcbase( ), offset, data );
763   }
764}
765
766
767
768/************************ reset *****************************/
769
770static DEVICE_RESET( mc6843 )
771{
772   mc6843_t* mc6843 = get_safe_token( device );
773   int i;
774   LOG (( "mc6843 reset\n" ));
775
776   /* setup/reset floppy drive */
777   for ( i = 0; i < 4; i++ )
778   {
779      device_t * img = floppy_get_device( device->machine(), i );
780      floppy_mon_w(img, CLEAR_LINE);
781      floppy_drive_set_ready_state( img, FLOPPY_DRIVE_READY, 0 );
782      floppy_drive_set_rpm( img, 300. );
783   }
784
785   /* reset registers */
786   mc6843->CMR &= 0xf0; /* zero only command */
787   mc6843->ISR = 0;
788   mc6843->STRA &= 0x5c;
789   mc6843->SAR = 0;
790   mc6843->STRB &= 0x20;
791   mc6843_status_update( device );
792
793   mc6843->data_size = 0;
794   mc6843->data_idx = 0;
795   mc6843->timer_cont->adjust( attotime::never );
796}
797
798
799
800/************************ start *****************************/
801
802static DEVICE_START( mc6843 )
803{
804   mc6843_t* mc6843 = get_safe_token( device );
805
806   mc6843->iface = (const mc6843_interface*)device->static_config();
807
808   mc6843->timer_cont = device->machine().scheduler().timer_alloc(FUNC(mc6843_cont), (void*) device) ;
809
810   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->CTAR );
811   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->CMR );
812   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->ISR );
813   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->SUR );
814   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->STRA );
815   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->STRB );
816   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->SAR );
817   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->GCR );
818   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->CCR );
819   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->LTAR );
820   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->drive );
821   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->side );
822   state_save_register_item_array( device->machine(),"mc6843", device->tag(), 0, mc6843->data );
823   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->data_size );
824   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->data_idx );
825   state_save_register_item( device->machine(),"mc6843", device->tag(), 0, mc6843->data_id );
826}
827
828
829const device_type MC6843 = &device_creator<mc6843_device>;
830
831mc6843_device::mc6843_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
832   : device_t(mconfig, MC6843, "Motorola MC6843 floppy controller", tag, owner, clock)
833{
834   m_token = global_alloc_clear(mc6843_t);
835}
836
837//-------------------------------------------------
838//  device_config_complete - perform any
839//  operations now that the configuration is
840//  complete
841//-------------------------------------------------
842
843void mc6843_device::device_config_complete()
844{
845}
846
847//-------------------------------------------------
848//  device_start - device-specific startup
849//-------------------------------------------------
850
851void mc6843_device::device_start()
852{
853   DEVICE_START_NAME( mc6843 )(this);
854}
855
856//-------------------------------------------------
857//  device_reset - device-specific reset
858//-------------------------------------------------
859
860void mc6843_device::device_reset()
861{
862   DEVICE_RESET_NAME( mc6843 )(this);
863}
trunk/src/mess/machine/mc6843.h
r21684r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2007
4
5  Motorola 6843 Floppy Disk Controller emulation.
6
7**********************************************************************/
8
9#ifndef MC6843_H
10#define MC6843_H
11
12class mc6843_device : public device_t
13{
14public:
15   mc6843_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
16   ~mc6843_device() { global_free(m_token); }
17
18   // access to legacy token
19   void *token() const { assert(m_token != NULL); return m_token; }
20protected:
21   // device-level overrides
22   virtual void device_config_complete();
23   virtual void device_start();
24   virtual void device_reset();
25private:
26   // internal state
27   void *m_token;
28};
29
30extern const device_type MC6843;
31
32
33
34/* ---------- configuration ------------ */
35
36struct mc6843_interface
37{
38   void ( * irq_func ) ( device_t *device, int state );
39};
40
41
42#define MCFG_MC6843_ADD(_tag, _intrf) \
43   MCFG_DEVICE_ADD(_tag, MC6843, 0)          \
44   MCFG_DEVICE_CONFIG(_intrf)
45
46#define MCFG_MC6843_REMOVE(_tag)        \
47   MCFG_DEVICE_REMOVE(_tag)
48
49
50/* ---------- functions ------------ */
51
52extern DECLARE_READ8_DEVICE_HANDLER  ( mc6843_r );
53extern DECLARE_WRITE8_DEVICE_HANDLER ( mc6843_w );
54
55extern void mc6843_set_drive ( device_t *device, int drive );
56extern void mc6843_set_side  ( device_t *device, int side );
57extern void mc6843_set_index_pulse ( device_t *device, int index_pulse );
58
59#endif
trunk/src/mess/machine/mos6530.c
r21684r21685
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 "mos6530.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
41struct mos6530_port
42{
43   devcb_resolved_read8        in_port_func;
44   devcb_resolved_write8       out_port_func;
45
46   UINT8               in;
47   UINT8               out;
48   UINT8               ddr;
49};
50
51
52struct mos6530_state
53{
54   devcb_resolved_write_line   out_irq_func;
55
56   mos6530_port    port[2];
57
58   UINT8           irqstate;
59   UINT8           irqenable;
60
61   UINT8           timershift;
62   UINT8           timerstate;
63   emu_timer *     timer;
64
65   UINT32          clock;
66};
67
68
69
70/***************************************************************************
71    INLINE FUNCTIONS
72***************************************************************************/
73
74/*-------------------------------------------------
75    get_safe_token - convert a device's token
76    into a mos6530_state
77-------------------------------------------------*/
78
79INLINE mos6530_state *get_safe_token(device_t *device)
80{
81   assert(device != NULL);
82   assert(device->type() == MOS6530);
83   return (mos6530_state *)downcast<mos6530_device *>(device)->token();
84}
85
86
87/*-------------------------------------------------
88    update_irqstate - update the IRQ state
89    based on interrupt enables
90-------------------------------------------------*/
91
92INLINE void update_irqstate(device_t *device)
93{
94   mos6530_state *miot = get_safe_token(device);
95   UINT8 out = miot->port[1].out;
96
97   if ( miot->irqenable )
98      out = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( out & 0x7F );
99
100   if (!miot->port[1].out_port_func.isnull())
101      miot->port[1].out_port_func(0, out);
102   else
103      logerror("6530MIOT chip %s: Port B is being written to but has no handler.\n", device->tag());
104}
105
106
107/*-------------------------------------------------
108    get_timer - return the current timer value
109-------------------------------------------------*/
110
111INLINE UINT8 get_timer(mos6530_state *miot)
112{
113   /* if idle, return 0 */
114   if (miot->timerstate == TIMER_IDLE)
115      return 0;
116
117   /* if counting, return the number of ticks remaining */
118   else if (miot->timerstate == TIMER_COUNTING)
119      return miot->timer->remaining().as_ticks(miot->clock) >> miot->timershift;
120
121   /* if finishing, return the number of ticks without the shift */
122   else
123      return miot->timer->remaining().as_ticks(miot->clock);
124}
125
126
127/***************************************************************************
128    INTERNAL FUNCTIONS
129***************************************************************************/
130
131/*-------------------------------------------------
132    timer_end_callback - callback to process the
133    timer
134-------------------------------------------------*/
135
136static TIMER_CALLBACK( timer_end_callback )
137{
138   device_t *device = (device_t *)ptr;
139   mos6530_state *miot = get_safe_token(device);
140
141   assert(miot->timerstate != TIMER_IDLE);
142
143   /* if we finished counting, switch to the finishing state */
144   if (miot->timerstate == TIMER_COUNTING)
145   {
146      miot->timerstate = TIMER_FINISHING;
147      miot->timer->adjust(attotime::from_ticks(256, miot->clock));
148
149      /* signal timer IRQ as well */
150      miot->irqstate |= TIMER_FLAG;
151      update_irqstate(device);
152   }
153
154   /* if we finished finishing, switch to the idle state */
155   else if (miot->timerstate == TIMER_FINISHING)
156   {
157      miot->timerstate = TIMER_IDLE;
158      miot->timer->adjust(attotime::never);
159   }
160}
161
162
163
164/***************************************************************************
165    I/O ACCESS
166***************************************************************************/
167
168/*-------------------------------------------------
169    mos6530_w - master I/O write access
170-------------------------------------------------*/
171
172WRITE8_DEVICE_HANDLER( mos6530_w )
173{
174   mos6530_state *miot = get_safe_token(device);
175
176   /* if A2 == 1, we are writing to the timer */
177   if (offset & 0x04)
178   {
179      static const UINT8 timershift[4] = { 0, 3, 6, 10 };
180      attotime curtime = space.machine().time();
181      INT64 target;
182
183      /* A0-A1 contain the timer divisor */
184      miot->timershift = timershift[offset & 3];
185
186      /* A3 contains the timer IRQ enable */
187      if (offset & 8)
188         miot->irqenable |= TIMER_FLAG;
189      else
190         miot->irqenable &= ~TIMER_FLAG;
191
192      /* writes here clear the timer flag */
193      if (miot->timerstate != TIMER_FINISHING || get_timer(miot) != 0xff)
194         miot->irqstate &= ~TIMER_FLAG;
195      update_irqstate(device);
196
197      /* update the timer */
198      miot->timerstate = TIMER_COUNTING;
199      target = curtime.as_ticks(miot->clock) + 1 + (data << miot->timershift);
200      miot->timer->adjust(attotime::from_ticks(target, miot->clock) - curtime);
201   }
202
203   /* if A2 == 0, we are writing to the I/O section */
204   else
205   {
206      /* A1 selects the port */
207      mos6530_port *port = &miot->port[(offset >> 1) & 1];
208
209      /* if A0 == 1, we are writing to the port's DDR */
210      if (offset & 1)
211         port->ddr = data;
212
213      /* if A0 == 0, we are writing to the port's output */
214      else
215      {
216         UINT8 olddata = port->out;
217         port->out = data;
218
219         if ( ( offset & 2 ) && miot->irqenable )
220         {
221            olddata = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( olddata & 0x7F );
222            data = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( data & 0x7F );
223         }
224
225         if (!port->out_port_func.isnull())
226            port->out_port_func(0, data);
227         else
228            logerror("6530MIOT chip %s: Port %c is being written to but has no handler.  PC: %08X - %02X\n", device->tag(), 'A' + (offset & 1), space.machine().firstcpu->pc(), data);
229      }
230   }
231}
232
233
234/*-------------------------------------------------
235    mos6530_r - master I/O read access
236-------------------------------------------------*/
237
238READ8_DEVICE_HANDLER( mos6530_r )
239{
240   mos6530_state *miot = get_safe_token(device);
241   UINT8 val = 0;
242
243   /* if A2 == 1 and A0 == 1, we are reading interrupt flags */
244   if ((offset & 0x05) == 0x05)
245   {
246      val = miot->irqstate;
247   }
248
249   /* if A2 == 1 and A0 == 0, we are reading the timer */
250   else if ((offset & 0x05) == 0x04)
251   {
252      val = get_timer(miot);
253
254      /* A3 contains the timer IRQ enable */
255      if (offset & 8)
256         miot->irqenable |= TIMER_FLAG;
257      else
258         miot->irqenable &= ~TIMER_FLAG;
259
260      /* implicitly clears the timer flag */
261      if (miot->timerstate != TIMER_FINISHING || val != 0xff)
262         miot->irqstate &= ~TIMER_FLAG;
263      update_irqstate(device);
264   }
265
266   /* if A2 == 0 and A0 == anything, we are reading from ports */
267   else
268   {
269      /* A1 selects the port */
270      mos6530_port *port = &miot->port[(offset >> 1) & 1];
271
272      /* if A0 == 1, we are reading the port's DDR */
273      if (offset & 1)
274         val = port->ddr;
275
276      /* if A0 == 0, we are reading the port as an input */
277      else
278      {
279         UINT8   out = port->out;
280
281         if ( ( offset & 2 ) && miot->irqenable )
282            out = ( ( miot->irqstate & TIMER_FLAG ) ? 0x00 : 0x80 ) | ( out & 0x7F );
283
284         /* call the input callback if it exists */
285         if (!port->in_port_func.isnull())
286         {
287            port->in = port->in_port_func(0);
288         }
289         else
290            logerror("6530MIOT chip %s: Port %c is being read but has no handler.  PC: %08X\n", device->tag(), 'A' + (offset & 1), space.machine().firstcpu->pc());
291
292         /* apply the DDR to the result */
293         val = (out & port->ddr) | (port->in & ~port->ddr);
294      }
295   }
296   return val;
297}
298
299
300/*-------------------------------------------------
301    mos6530_porta_in_set - set port A input
302    value
303-------------------------------------------------*/
304
305void mos6530_porta_in_set(device_t *device, UINT8 data, UINT8 mask)
306{
307   mos6530_state *miot = get_safe_token(device);
308   miot->port[0].in = (miot->port[0].in & ~mask) | (data & mask);
309}
310
311
312/*-------------------------------------------------
313    mos6530_portb_in_set - set port B input
314    value
315-------------------------------------------------*/
316
317void mos6530_portb_in_set(device_t *device, UINT8 data, UINT8 mask)
318{
319   mos6530_state *miot = get_safe_token(device);
320   miot->port[1].in = (miot->port[1].in & ~mask) | (data & mask);
321}
322
323
324/*-------------------------------------------------
325    mos6530_porta_in_get - return port A input
326    value
327-------------------------------------------------*/
328
329UINT8 mos6530_porta_in_get(device_t *device)
330{
331   mos6530_state *miot = get_safe_token(device);
332   return miot->port[0].in;
333}
334
335
336/*-------------------------------------------------
337    mos6530_portb_in_get - return port B input
338    value
339-------------------------------------------------*/
340
341UINT8 mos6530_portb_in_get(device_t *device)
342{
343   mos6530_state *miot = get_safe_token(device);
344   return miot->port[1].in;
345}
346
347
348/*-------------------------------------------------
349    mos6530_porta_in_get - return port A output
350    value
351-------------------------------------------------*/
352
353UINT8 mos6530_porta_out_get(device_t *device)
354{
355   mos6530_state *miot = get_safe_token(device);
356   return miot->port[0].out;
357}
358
359
360/*-------------------------------------------------
361    mos6530_portb_in_get - return port B output
362    value
363-------------------------------------------------*/
364
365UINT8 mos6530_portb_out_get(device_t *device)
366{
367   mos6530_state *miot = get_safe_token(device);
368   return miot->port[1].out;
369}
370
371
372/***************************************************************************
373    DEVICE INTERFACE
374***************************************************************************/
375
376static DEVICE_START( mos6530 )
377{
378   mos6530_state *miot = get_safe_token(device);
379   const mos6530_interface *intf = (const mos6530_interface*)device->static_config();
380
381   /* validate arguments */
382   assert(device != NULL);
383   assert(device->tag() != NULL);
384
385   /* set static values */
386   miot->clock = device->clock();
387
388   /* resolve callbacks */
389   miot->port[0].in_port_func.resolve(intf->in_pa_func, *device);
390   miot->port[1].in_port_func.resolve(intf->in_pb_func, *device);
391   miot->port[0].out_port_func.resolve(intf->out_pa_func, *device);
392   miot->port[1].out_port_func.resolve(intf->out_pb_func, *device);
393
394   /* allocate timers */
395   miot->timer = device->machine().scheduler().timer_alloc(FUNC(timer_end_callback), (void *)device);
396
397   /* register for save states */
398   device->save_item(NAME(miot->port[0].in));
399   device->save_item(NAME(miot->port[0].out));
400   device->save_item(NAME(miot->port[0].ddr));
401   device->save_item(NAME(miot->port[1].in));
402   device->save_item(NAME(miot->port[1].out));
403   device->save_item(NAME(miot->port[1].ddr));
404
405   device->save_item(NAME(miot->irqstate));
406   device->save_item(NAME(miot->irqenable));
407
408   device->save_item(NAME(miot->timershift));
409   device->save_item(NAME(miot->timerstate));
410}
411
412
413static DEVICE_RESET( mos6530 )
414{
415   mos6530_state *miot = get_safe_token(device);
416
417   /* reset I/O states */
418   miot->port[0].out = 0;
419   miot->port[0].ddr = 0;
420   miot->port[1].out = 0;
421   miot->port[1].ddr = 0;
422
423   /* reset IRQ states */
424   miot->irqenable = 0;
425   miot->irqstate = TIMER_FLAG;
426   update_irqstate(device);
427
428   /* reset timer states */
429   miot->timershift = 0;
430   miot->timerstate = TIMER_IDLE;
431   miot->timer->adjust(attotime::never);
432}
433
434
435const device_type MOS6530 = &device_creator<mos6530_device>;
436
437mos6530_device::mos6530_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
438   : device_t(mconfig, MOS6530, "MOS6530", tag, owner, clock)
439{
440   m_token = global_alloc_clear(mos6530_state);
441}
442
443//-------------------------------------------------
444//  device_config_complete - perform any
445//  operations now that the configuration is
446//  complete
447//-------------------------------------------------
448
449void mos6530_device::device_config_complete()
450{
451}
452
453//-------------------------------------------------
454//  device_start - device-specific startup
455//-------------------------------------------------
456
457void mos6530_device::device_start()
458{
459   DEVICE_START_NAME( mos6530 )(this);
460}
461
462//-------------------------------------------------
463//  device_reset - device-specific reset
464//-------------------------------------------------
465
466void mos6530_device::device_reset()
467{
468   DEVICE_RESET_NAME( mos6530 )(this);
469}
trunk/src/mess/machine/mos6530.h
r21684r21685
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    MACROS / CONSTANTS
38***************************************************************************/
39
40class mos6530_device : public device_t
41{
42public:
43   mos6530_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
44   ~mos6530_device() { global_free(m_token); }
45
46   // access to legacy token
47   void *token() const { assert(m_token != NULL); return m_token; }
48protected:
49   // device-level overrides
50   virtual void device_config_complete();
51   virtual void device_start();
52   virtual void device_reset();
53private:
54   // internal state
55   void *m_token;
56};
57
58extern const device_type MOS6530;
59
60
61#define MCFG_MOS6530_ADD(_tag, _clock, _config) \
62   MCFG_DEVICE_ADD((_tag), MOS6530, _clock)    \
63   MCFG_DEVICE_CONFIG(_config)
64
65#define MOS6530_INTERFACE(name) \
66   const mos6530_interface (name) =
67
68/***************************************************************************
69    TYPE DEFINITIONS
70***************************************************************************/
71
72struct mos6530_interface
73{
74   devcb_read8             in_pa_func;
75   devcb_write8            out_pa_func;
76
77   devcb_read8             in_pb_func;
78   devcb_write8            out_pb_func;
79};
80
81/***************************************************************************
82    PROTOTYPES
83***************************************************************************/
84
85DECLARE_READ8_DEVICE_HANDLER( mos6530_r );
86DECLARE_WRITE8_DEVICE_HANDLER( mos6530_w );
87
88void mos6530_porta_in_set(device_t *device, UINT8 data, UINT8 mask);
89void mos6530_portb_in_set(device_t *device, UINT8 data, UINT8 mask);
90
91UINT8 mos6530_porta_in_get(device_t *device);
92UINT8 mos6530_portb_in_get(device_t *device);
93
94UINT8 mos6530_porta_out_get(device_t *device);
95UINT8 mos6530_portb_out_get(device_t *device);
96
97#endif
trunk/src/mess/machine/c64_legacy.c
r21684r21685
1/***************************************************************************
2    commodore c64 home computer
3
4    peter.trauner@jk.uni-linz.ac.at
5    documentation
6     www.funet.fi
7***************************************************************************/
8
9/*
10    2008-09-06: Tape status for C64 & C128 [FP & RZ]
11    - tape loading works
12    - tap files are supported
13    - tape writing works
14*/
15
16#include "emu.h"
17
18#include "cpu/m6502/m6510.h"
19#include "cpu/z80/z80.h"
20#include "sound/mos6581.h"
21#include "machine/6526cia.h"
22#include "machine/cbmiec.h"
23
24#include "includes/cbm.h"
25#include "includes/c64_legacy.h"
26
27#include "imagedev/cassette.h"
28#include "imagedev/cartslot.h"
29
30#define VERBOSE_LEVEL 0
31#define DBG_LOG( MACHINE, N, M, A ) \
32   do { \
33      if(VERBOSE_LEVEL >= N) \
34      { \
35         if( M ) \
36            logerror("%11.6f: %-24s", MACHINE.time().as_double(), (char*) M ); \
37         logerror A; \
38      } \
39   } while (0)
40
41#define log_cart 0
42
43/* Info from http://unusedino.de/ec64/technical/misc/c64/64doc.html */
44/*
45
46  The leftmost column of the table contains addresses in hexadecimal
47notation. The columns aside it introduce all possible memory
48configurations. The default mode is on the left, and the absolutely
49most rarely used Ultimax game console configuration is on the right.
50(Has anybody ever seen any Ultimax games?) Each memory configuration
51column has one or more four-digit binary numbers as a title. The bits,
52from left to right, represent the state of the -LORAM, -HIRAM, -GAME
53and -EXROM lines, respectively. The bits whose state does not matter
54are marked with "x". For instance, when the Ultimax video game
55configuration is active (the -GAME line is shorted to ground), the
56-LORAM and -HIRAM lines have no effect.
57
58      default                      001x                       Ultimax
59       1111   101x   1000   011x   00x0   1110   0100   1100   xx01
6010000
61----------------------------------------------------------------------
62 F000
63       Kernal RAM    RAM    Kernal RAM    Kernal Kernal Kernal ROMH(*
64 E000
65----------------------------------------------------------------------
66 D000  IO/C   IO/C   IO/RAM IO/C   RAM    IO/C   IO/C   IO/C   I/O
67----------------------------------------------------------------------
68 C000  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
69----------------------------------------------------------------------
70 B000
71       BASIC  RAM    RAM    RAM    RAM    BASIC  ROMH   ROMH    -
72 A000
73----------------------------------------------------------------------
74 9000
75       RAM    RAM    RAM    RAM    RAM    ROML   RAM    ROML   ROML(*
76 8000
77----------------------------------------------------------------------
78 7000
79
80 6000
81       RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
82 5000
83
84 4000
85----------------------------------------------------------------------
86 3000
87
88 2000  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM     -
89
90 1000
91----------------------------------------------------------------------
92 0000  RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM    RAM
93----------------------------------------------------------------------
94
95   *) Internal memory does not respond to write accesses to these
96       areas.
97
98
99    Legend: Kernal      E000-FFFF       Kernal ROM.
100
101            IO/C        D000-DFFF       I/O address space or Character
102                                        generator ROM, selected by
103                                        -CHAREN. If the CHAREN bit is
104                                        clear, the character generator
105                                        ROM will be selected. If it is
106                                        set, the I/O chips are
107                                        accessible.
108
109            IO/RAM      D000-DFFF       I/O address space or RAM,
110                                        selected by -CHAREN. If the
111                                        CHAREN bit is clear, the
112                                        character generator ROM will
113                                        be selected. If it is set, the
114                                        internal RAM is accessible.
115
116            I/O         D000-DFFF       I/O address space.
117                                        The -CHAREN line has no effect.
118
119            BASIC       A000-BFFF       BASIC ROM.
120
121            ROMH        A000-BFFF or    External ROM with the -ROMH line
122                        E000-FFFF       connected to its -CS line.
123
124            ROML        8000-9FFF       External ROM with the -ROML line
125                                        connected to its -CS line.
126
127            RAM         various ranges  Commodore 64's internal RAM.
128
129            -           1000-7FFF and   Open address space.
130                        A000-CFFF       The Commodore 64's memory chips
131                                        do not detect any memory accesses
132                                        to this area except the VIC-II's
133                                        DMA and memory refreshes.
134
135    NOTE:   Whenever the processor tries to write to any ROM area
136            (Kernal, BASIC, CHAROM, ROML, ROMH), the data will get
137            "through the ROM" to the C64's internal RAM.
138
139            For this reason, you can easily copy data from ROM to RAM,
140            without any bank switching. But implementing external
141            memory expansions without DMA is very hard, as you have to
142            use a 256 byte window on the I/O1 or I/O2 area, like
143            GEORAM, or the Ultimax memory configuration, if you do not
144            want the data to be written both to internal and external
145            RAM.
146
147            However, this is not true for the Ultimax video game
148            configuration. In that mode, the internal RAM ignores all
149            memory accesses outside the area $0000-$0FFF, unless they
150            are performed by the VIC, and you can write to external
151            memory at $1000-$CFFF and $E000-$FFFF, if any, without
152            changing the contents of the internal RAM.
153
154*/
155
156static void c64_bankswitch( running_machine &machine, int reset )
157{
158   legacy_c64_state *state = machine.driver_data<legacy_c64_state>();
159   int loram, hiram, charen;
160   int ultimax_mode = 0;
161   int data = machine.device<m6510_device>("maincpu")->get_port() & 0x07;
162
163   /* Are we in Ultimax mode? */
164   if (!state->m_game && state->m_exrom)
165      ultimax_mode = 1;
166
167   DBG_LOG(machine, 1, "bankswitch", ("%d\n", data & 7));
168   loram  = (data & 1) ? 1 : 0;
169   hiram  = (data & 2) ? 1 : 0;
170   charen = (data & 4) ? 1 : 0;
171   //logerror("Bankswitch mode || charen, state->m_ultimax\n");
172   //logerror("%d, %d, %d, %d  ||   %d,      %d  \n", loram, hiram, state->m_game, state->m_exrom, charen, ultimax_mode);
173
174   if (ultimax_mode)
175   {
176         state->m_io_enabled = 1;        // charen has no effect in ultimax_mode
177
178         state->membank("bank1")->set_base(state->m_roml);
179         state->membank("bank3")->set_base(state->m_memory + 0xa000);
180         state->membank("bank4")->set_base(state->m_romh);
181         machine.device("maincpu")->memory().space(AS_PROGRAM).nop_write(0xe000, 0xffff);
182   }
183   else
184   {
185      /* 0x8000-0x9000 */
186      if (loram && hiram && !state->m_exrom)
187      {
188         state->membank("bank1")->set_base(state->m_roml);
189      }
190      else
191      {
192         state->membank("bank1")->set_base(state->m_memory + 0x8000);
193      }
194
195      /* 0xa000 */
196      if (hiram && !state->m_game && !state->m_exrom)
197         state->membank("bank3")->set_base(state->m_romh);
198
199      else if (loram && hiram && state->m_game)
200         state->membank("bank3")->set_base(state->m_basic);
201
202      else
203         state->membank("bank3")->set_base(state->m_memory + 0xa000);
204
205      /* 0xd000 */
206      // RAM
207      if (!loram && !hiram && (state->m_game || !state->m_exrom))
208      {
209         state->m_io_enabled = 0;
210         state->m_io_ram_r_ptr = state->m_memory + 0xd000;
211         state->m_io_ram_w_ptr = state->m_memory + 0xd000;
212      }
213      // IO/RAM
214      else if (loram && !hiram && !state->m_game) // remember we cannot be in ultimax_mode, no need of !state->m_exrom
215      {
216         state->m_io_enabled = 1;
217         state->m_io_ram_r_ptr = (!charen) ? state->m_chargen : state->m_memory + 0xd000;
218         state->m_io_ram_w_ptr = state->m_memory + 0xd000;
219      }
220      // IO/C
221      else
222      {
223         state->m_io_enabled = charen ? 1 : 0;
224
225         if (!charen)
226         {
227         state->m_io_ram_r_ptr = state->m_chargen;
228         state->m_io_ram_w_ptr = state->m_memory + 0xd000;
229         }
230      }
231
232      /* 0xe000-0xf000 */
233      state->membank("bank4")->set_base(hiram ? state->m_kernal : state->m_memory + 0xe000);
234      state->membank("bank5")->set_base(state->m_memory + 0xe000);
235   }
236
237   /* make sure the opbase function gets called each time */
238   /* NPW 15-May-2008 - Another hack in the C64 drivers broken! */
239   /* opbase->mem_max = 0xcfff; */
240
241   state->m_old_game = state->m_game;
242   state->m_old_exrom = state->m_exrom;
243   state->m_old_data = data;
244}
245
246int c64_paddle_read( device_t *device, address_space &space, int which )
247{
248   running_machine &machine = device->machine();
249   int pot1 = 0xff, pot2 = 0xff, pot3 = 0xff, pot4 = 0xff, temp;
250   UINT8 cia0porta = mos6526_pa_r(machine.device("cia_0"), space, 0);
251   int controller1 = machine.root_device().ioport("CTRLSEL")->read() & 0x07;
252   int controller2 = machine.root_device().ioport("CTRLSEL")->read() & 0x70;
253   /* Notice that only a single input is defined for Mouse & Lightpen in both ports */
254   switch (controller1)
255   {
256      case 0x01:
257         if (which)
258            pot2 = machine.root_device().ioport("PADDLE2")->read();
259         else
260            pot1 = machine.root_device().ioport("PADDLE1")->read();
261         break;
262
263      case 0x02:
264         if (which)
265            pot2 = machine.root_device().ioport("TRACKY")->read();
266         else
267            pot1 = machine.root_device().ioport("TRACKX")->read();
268         break;
269
270      case 0x03:
271         if (which && (machine.root_device().ioport("JOY1_2B")->read() & 0x20))  /* Joy1 Button 2 */
272            pot1 = 0x00;
273         break;
274
275      case 0x04:
276         if (which)
277            pot2 = machine.root_device().ioport("LIGHTY")->read();
278         else
279            pot1 = machine.root_device().ioport("LIGHTX")->read();
280         break;
281
282      case 0x06:
283         if (which && (machine.root_device().ioport("OTHER")->read() & 0x04))    /* Lightpen Signal */
284            pot2 = 0x00;
285         break;
286
287      case 0x00:
288      case 0x07:
289         break;
290
291      default:
292         logerror("Invalid Controller Setting %d\n", controller1);
293         break;
294   }
295
296   switch (controller2)
297   {
298      case 0x10:
299         if (which)
300            pot4 = machine.root_device().ioport("PADDLE4")->read();
301         else
302            pot3 = machine.root_device().ioport("PADDLE3")->read();
303         break;
304
305      case 0x20:
306         if (which)
307            pot4 = machine.root_device().ioport("TRACKY")->read();
308         else
309            pot3 = machine.root_device().ioport("TRACKX")->read();
310         break;
311
312      case 0x30:
313         if (which && (machine.root_device().ioport("JOY2_2B")->read() & 0x20))  /* Joy2 Button 2 */
314            pot4 = 0x00;
315         break;
316
317      case 0x40:
318         if (which)
319            pot4 = machine.root_device().ioport("LIGHTY")->read();
320         else
321            pot3 = machine.root_device().ioport("LIGHTX")->read();
322         break;
323
324      case 0x60:
325         if (which && (machine.root_device().ioport("OTHER")->read() & 0x04))    /* Lightpen Signal */
326            pot4 = 0x00;
327         break;
328
329      case 0x00:
330      case 0x70:
331         break;
332
333      default:
334         logerror("Invalid Controller Setting %d\n", controller1);
335         break;
336   }
337
338   if (machine.root_device().ioport("CTRLSEL")->read() & 0x80)     /* Swap */
339   {
340      temp = pot1; pot1 = pot3; pot3 = temp;
341      temp = pot2; pot2 = pot4; pot4 = temp;
342   }
343
344   switch (cia0porta & 0xc0)
345   {
346      case 0x40:
347         return which ? pot2 : pot1;
348
349      case 0x80:
350         return which ? pot4 : pot3;
351
352      case 0xc0:
353         return which ? pot2 : pot1;
354
355      default:
356         return 0;
357   }
358}
359
360READ8_HANDLER( c64_colorram_read )
361{
362   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
363   return state->m_colorram[offset & 0x3ff];
364}
365
366WRITE8_HANDLER( c64_colorram_write )
367{
368   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
369   state->m_colorram[offset & 0x3ff] = data | 0xf0;
370}
371
372/***********************************************
373
374    C64 Cartridges
375
376***********************************************/
377
378/* Info based on http://ist.uwaterloo.ca/~schepers/formats/CRT.TXT      */
379/* Please refer to the webpage for the latest version and for a very
380   complete listing of various cart types and their bankswitch tricks   */
381/*
382  Cartridge files were introduced in the CCS64  emulator,  written  by  Per
383Hakan Sundell, and use the ".CRT" file extension. This format  was  created
384to handle the various ROM cartridges that exist, such as Action Replay, the
385Power cartridge, and the Final Cartridge.
386
387  Normal game cartridges can load  into  several  different  memory  ranges
388($8000-9FFF,  $A000-BFFF  or  $E000-FFFF).  Newer   utility   and   freezer
389cartridges were less intrusive, hiding themselves until  called  upon,  and
390still others used bank-switching techniques to allow much larger ROM's than
391normal. Because of these "stealthing" and bank-switching methods, a special
392cartridge format  was  necessary,  to  let  the  emulator  know  where  the
393cartridge should reside, the control line  states  to  enable  it  and  any
394special hardware features it uses.
395
396(...)
397
398[ A .CRT file consists of
399
400    $0000-0040 :    Header of the whole .crt files
401    $0040-EOF :     Blocks of data
402
403  Each block of data, called 'CHIP', can be of variable size. The first
4040x10 bytes of each CHIP block is the block header, and it contains various
405informations on the block itself, as its size (both with and without the
406header), the loading address and an index to identify which memory bank
407the data must be loaded to.  FP ]
408
409.CRT header description
410-----------------------
411
412 Bytes: $0000-000F - 16-byte cartridge signature  "C64  CARTRIDGE"  (padded
413                     with space characters)
414         0010-0013 - File header length  ($00000040,  in  high/low  format,
415                     calculated from offset $0000). The default  (also  the
416                     minimum) value is $40.  Some  cartridges  exist  which
417                     show a value of $00000020 which is wrong.
418         0014-0015 - Cartridge version (high/low, presently 01.00)
419         0016-0017 - Cartridge hardware type ($0000, high/low)
420              0018 - Cartridge port EXROM line status
421                      0 - inactive
422                      1 - active
423              0019 - Cartridge port GAME line status
424                      0 - inactive
425                      1 - active
426         001A-001F - Reserved for future use
427         0020-003F - 32-byte cartridge  name  "CCSMON"  (uppercase,  padded
428                     with null characters)
429         0040-xxxx - Cartridge contents (called CHIP PACKETS, as there  can
430                     be more than one  per  CRT  file).  See  below  for  a
431                     breakdown of the CHIP format.
432
433CHIP content description
434------------------------
435
436[ Addresses shifted back to $0000.  FP ]
437
438 Bytes: $0000-0003 - Contained ROM signature "CHIP" (note there can be more
439                     than one image in a .CRT file)
440         0004-0007 - Total packet length (ROM  image  size  and
441                     header combined) (high/low format)
442         0008-0009 - Chip type
443                      0 - ROM
444                      1 - RAM, no ROM data
445                      2 - Flash ROM
446         000A-000B - Bank number
447         000C-000D - Starting load address (high/low format)
448         000E-000F - ROM image size in bytes  (high/low  format,  typically
449                     $2000 or $4000)
450         0010-xxxx - ROM data
451
452
453*/
454
455
456/* Hardware Types for C64 carts */
457enum {
458   GENERIC_CRT = 0,        /* 00 - Normal cartridge                    */
459   ACTION_REPLAY,      /* 01 - Action Replay                       */
460   KCS_PC,         /* 02 - KCS Power Cartridge                 */
461   FINAL_CART_III,     /* 03 - Final Cartridge III                 */
462   SIMONS_BASIC,       /* 04 - Simons Basic                        */
463   OCEAN_1,            /* 05 - Ocean type 1 (1)                    */
464   EXPERT,         /* 06 - Expert Cartridge                    */
465   FUN_PLAY,           /* 07 - Fun Play, Power Play                */
466   SUPER_GAMES,        /* 08 - Super Games                         */
467   ATOMIC_POWER,       /* 09 - Atomic Power                        */
468   EPYX_FASTLOAD,      /* 10 - Epyx Fastload                       */
469   WESTERMANN,         /* 11 - Westermann Learning                 */
470   REX,                /* 12 - Rex Utility                         */
471   FINAL_CART_I,       /* 13 - Final Cartridge I                   */
472   MAGIC_FORMEL,       /* 14 - Magic Formel                        */
473   C64GS,          /* 15 - C64 Game System, System 3           */
474   WARPSPEED,          /* 16 - WarpSpeed                           */
475   DINAMIC,            /* 17 - Dinamic (2)                         */
476   ZAXXON,         /* 18 - Zaxxon, Super Zaxxon (SEGA)         */
477   DOMARK,         /* 19 - Magic Desk, Domark, HES Australia   */
478   SUPER_SNAP_5,       /* 20 - Super Snapshot 5                    */
479   COMAL_80,           /* 21 - Comal-80                            */
480   STRUCT_BASIC,       /* 22 - Structured Basic                    */
481   ROSS,               /* 23 - Ross                                */
482   DELA_EP64,          /* 24 - Dela EP64                           */
483   DELA_EP7X8,         /* 25 - Dela EP7x8                          */
484   DELA_EP256,         /* 26 - Dela EP256                          */
485   REX_EP256,          /* 27 - Rex EP256                           */
486   MIKRO_ASSMBLR,      /* 28 - Mikro Assembler                     */
487   REAL_FC_I,          /* 29 - (3)                                 */
488   ACTION_REPLAY_4,        /* 30 - Action Replay 4                     */
489   STARDOS,            /* 31 - StarDOS                             */
490   /*
491   (1) Ocean type 1 includes Navy Seals, Robocop 2 & 3,  Shadow  of
492   the Beast, Toki, Terminator 2 and more. Both 256 and 128 Kb images.
493   (2) Dinamic includes Narco Police and more.
494   (3) Type 29 is reserved for the real Final Cartridge I, the one
495   above (Type 13) will become Final Cartridge II.                 */
496   /****************************************
497   Vice also defines the following types:
498   #define CARTRIDGE_ACTION_REPLAY3    -29
499   #define CARTRIDGE_IEEE488           -11
500   #define CARTRIDGE_IDE64             -7
501   #define CARTRIDGE_RETRO_REPLAY      -5
502   #define CARTRIDGE_SUPER_SNAPSHOT    -4
503
504   Can we support these as well?
505   *****************************************/
506};
507
508DEVICE_IMAGE_UNLOAD_MEMBER( legacy_c64_state, c64_cart )
509{
510   int i;
511
512   for (i = 0; i < C64_MAX_ROMBANK; i++)
513   {
514      m_cart.bank[i].size = 0;
515      m_cart.bank[i].addr = 0;
516      m_cart.bank[i].index = 0;
517      m_cart.bank[i].start = 0;
518   }
519}
520
521
522void legacy_c64_state::c64_legacy_driver_init()
523{
524   /* In the first slot we can load a .crt file. In this case we want
525       to use game & exrom values from the header, not the default ones. */
526   m_cart.game = -1;
527   m_cart.exrom = -1;
528   m_cart.mapper = GENERIC_CRT;
529   m_cart.n_banks = 0;
530}
531
532static int c64_crt_load( device_image_interface &image )
533{
534   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
535   int size = image.length(), test, i = 0, ii;
536   int _80_loaded = 0, _90_loaded = 0, a0_loaded = 0, b0_loaded = 0, e0_loaded = 0, f0_loaded = 0;
537   const char *filetype = image.filetype();
538   int address = 0, new_start = 0;
539   // int lbank_end_addr = 0, hbank_end_addr = 0;
540   UINT8 *cart_cpy = state->memregion("user1")->base();
541
542   /* We support .crt files */
543   if (!mame_stricmp(filetype, "crt"))
544   {
545      int j;
546      unsigned short c64_cart_type;
547
548      if (i >= C64_MAX_ROMBANK)
549         return IMAGE_INIT_FAIL;
550
551      /* Start to parse the .crt header */
552      /* 0x16-0x17 is Hardware type */
553      image.fseek(0x16, SEEK_SET);
554      image.fread(&c64_cart_type, 2);
555      state->m_cart.mapper = BIG_ENDIANIZE_INT16(c64_cart_type);
556
557      /* If it is unsupported cart type, warn the user */
558      switch (state->m_cart.mapper)
559      {
560         case SIMONS_BASIC:  /* Type #  4 */
561         case OCEAN_1:       /* Type #  5 */
562         case FUN_PLAY:      /* Type #  7 */
563         case SUPER_GAMES:       /* Type #  8 */
564         case EPYX_FASTLOAD: /* Type # 10 */
565         case REX:           /* Type # 12 */
566         case C64GS:         /* Type # 15 */
567         case DINAMIC:       /* Type # 17 */
568         case ZAXXON:        /* Type # 18 */
569         case DOMARK:        /* Type # 19 */
570         case COMAL_80:      /* Type # 21 */
571         case GENERIC_CRT:       /* Type #  0 */
572            printf("Currently supported cart type (Type %d)\n", state->m_cart.mapper);
573            break;
574
575         default:
576         case ACTION_REPLAY: /* Type #  1 */
577         case KCS_PC:        /* Type #  2 */
578         case FINAL_CART_III:    /* Type #  3 */
579         case EXPERT:        /* Type #  6 */
580         case ATOMIC_POWER:  /* Type #  9 */
581         case WESTERMANN:        /* Type # 11 */
582         case FINAL_CART_I:  /* Type # 13 */
583         case MAGIC_FORMEL:  /* Type # 14 */
584         case SUPER_SNAP_5:  /* Type # 20 */
585            printf("Currently unsupported cart type (Type %d)\n", state->m_cart.mapper);
586            break;
587      }
588
589      /* 0x18 is EXROM */
590      image.fseek(0x18, SEEK_SET);
591      image.fread(&state->m_cart.exrom, 1);
592
593      /* 0x19 is GAME */
594      image.fread(&state->m_cart.game, 1);
595
596      /* We can pass to the data: it starts from 0x40 */
597      image.fseek(0x40, SEEK_SET);
598      j = 0x40;
599
600      logerror("Loading cart %s size:%.4x\n", image.filename(), size);
601      logerror("Header info: EXROM %d, GAME %d, Cart Type %d \n", state->m_cart.exrom, state->m_cart.game, c64_cart_type);
602
603
604      /* Data in a .crt image are organized in blocks called 'CHIP':
605         each 'CHIP' consists of a 0x10 header, which contains the
606         actual size of the block, the loading address and info on
607         the bankswitch, followed by the actual data                  */
608      while (j < size)
609      {
610         unsigned short chip_size, chip_bank_index, chip_data_size;
611         unsigned char buffer[10];
612
613         /* Start to parse the CHIP header */
614         /* First 4 bytes are the string 'CHIP' */
615         image.fread(buffer, 6);
616
617         /* 0x06-0x07 is the size of the CHIP block (header + data) */
618         image.fread(&chip_size, 2);
619         chip_size = BIG_ENDIANIZE_INT16(chip_size);
620
621         /* 0x08-0x09 chip type (ROM, RAM + no ROM, Flash ROM) */
622         image.fread(buffer + 6, 2);
623
624         /* 0x0a-0x0b is the bank number of the CHIP block */
625         image.fread(&chip_bank_index, 2);
626         chip_bank_index = BIG_ENDIANIZE_INT16(chip_bank_index);
627
628         /* 0x0c-0x0d is the loading address of the CHIP block */
629         image.fread(&address, 2);
630         address = BIG_ENDIANIZE_INT16(address);
631
632         /* 0x0e-0x0f is the data size of the CHIP block (without header) */
633         image.fread(&chip_data_size, 2);
634         chip_data_size = BIG_ENDIANIZE_INT16(chip_data_size);
635
636         /* Print out the CHIP header! */
637         logerror("%.4s %.2x %.2x %.4x %.2x %.2x %.4x %.4x:%.4x\n",
638            buffer, buffer[4], buffer[5], chip_size,
639            buffer[6], buffer[7], chip_bank_index,
640            address, chip_data_size);
641         logerror("Loading CHIP data at %.4x size:%.4x\n", address, chip_data_size);
642
643         /* Store data, address & size of the CHIP block */
644         state->m_cart.bank[i].addr = address;
645         state->m_cart.bank[i].index = chip_bank_index;
646         state->m_cart.bank[i].size = chip_data_size;
647         state->m_cart.bank[i].start = new_start;
648
649         test = image.fread(cart_cpy + new_start, state->m_cart.bank[i].size);
650         new_start += state->m_cart.bank[i].size;
651
652         /* Does CHIP contain any data? */
653         if (test != state->m_cart.bank[i].size)
654            return IMAGE_INIT_FAIL;
655
656         /* Advance to the next CHIP block */
657         i++;
658         j += chip_size;
659      }
660   }
661   else /* We also support .80 files for c64 & .e0/.f0 for max */
662   {
663      /* Assign loading address according to extension */
664      if (!mame_stricmp(filetype, "80"))
665         address = 0x8000;
666
667      if (!mame_stricmp(filetype, "e0"))
668         address = 0xe000;
669
670      if (!mame_stricmp(filetype, "f0"))
671         address = 0xf000;
672
673      logerror("loading %s rom at %.4x size:%.4x\n", image.filename(), address, size);
674
675      /* Store data, address & size */
676      state->m_cart.bank[0].addr = address;
677      state->m_cart.bank[0].size = size;
678      state->m_cart.bank[0].start = new_start;
679
680      test = image.fread(cart_cpy + new_start, state->m_cart.bank[0].size);
681      new_start += state->m_cart.bank[0].size;
682
683      /* Does cart contain any data? */
684      if (test != state->m_cart.bank[0].size)
685         return IMAGE_INIT_FAIL;
686   }
687
688   state->m_cart.n_banks = i; // this is also needed so that we only set mappers if a cart is present!
689
690   /* If we load a .crt file, use EXROM & GAME from the header! */
691   if ((state->m_cart.exrom != -1) && (state->m_cart.game != -1))
692   {
693      state->m_exrom = state->m_cart.exrom;
694      state->m_game  = state->m_cart.game;
695   }
696
697   /* Finally load the cart */
698   state->m_roml = state->m_c64_roml;
699   state->m_romh = state->m_c64_romh;
700
701   memset(state->m_roml, 0, 0x2000);
702   memset(state->m_romh, 0, 0x2000);
703
704   switch (state->m_cart.mapper)
705   {
706   default:
707      if (!state->m_game && state->m_exrom && (state->m_cart.n_banks == 1))
708      {
709         memcpy(state->m_romh, cart_cpy, 0x2000);
710      }
711      else
712      {
713         // we first attempt to load the first 'CHIPs' with address 0x8000-0xb000 and 0xe000-0xf000, otherwise we load the first (or first two) 'CHIPs' of the image
714         for (ii = 0; ii < state->m_cart.n_banks; ii++)
715         {
716            if (state->m_cart.bank[ii].addr == 0x8000 && !_80_loaded)
717            {
718               memcpy(state->m_roml, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
719               _80_loaded = 1;
720               if (state->m_cart.bank[ii].size > 0x1000)
721                  _90_loaded = 1;
722               if (state->m_cart.bank[ii].size > 0x2000)
723                  a0_loaded = 1;
724               if (state->m_cart.bank[ii].size > 0x3000)
725                  b0_loaded = 1;
726//                  printf("addr 0x8000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
727            }
728
729            if (state->m_cart.bank[ii].addr == 0x9000 && !_90_loaded)
730            {
731               memcpy(state->m_roml + 0x1000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
732               _90_loaded = 1;
733               if (state->m_cart.bank[ii].size > 0x1000)
734                  a0_loaded = 1;
735               if (state->m_cart.bank[ii].size > 0x2000)
736                  b0_loaded = 1;
737//                  printf("addr 0x9000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
738            }
739
740            if (state->m_cart.bank[ii].addr == 0xa000 && !a0_loaded)
741            {
742               memcpy(state->m_roml + 0x2000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
743               a0_loaded = 1;
744               if (state->m_cart.bank[ii].size > 0x1000)
745                  b0_loaded = 1;
746//                  printf("addr 0xa000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
747            }
748
749            if (state->m_cart.bank[ii].addr == 0xb000 && !b0_loaded)
750            {
751               memcpy(state->m_roml + 0x3000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
752               b0_loaded = 1;
753//                  printf("addr 0xb000: 80 %d, 90 %d, a0 %d, b0 %d\n", _80_loaded, _90_loaded, a0_loaded, b0_loaded);
754            }
755
756            if (state->m_cart.bank[ii].addr == 0xe000 && !e0_loaded)
757            {
758               memcpy(state->m_romh, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
759               e0_loaded = 1;
760               if (state->m_cart.bank[ii].size > 0x1000)
761                  f0_loaded = 1;
762//                  printf("addr 0xe000: e0 %d, f0 %d\n", e0_loaded, f0_loaded);
763            }
764
765            if (state->m_cart.bank[ii].addr == 0xf000 && !f0_loaded)
766            {
767               memcpy(state->m_romh + 0x1000, cart_cpy + state->m_cart.bank[ii].start, state->m_cart.bank[ii].size);
768               f0_loaded = 1;
769//                  printf("addr 0xe000: e0 %d, f0 %d\n", e0_loaded, f0_loaded);
770            }
771         }
772      }
773   }
774
775   return IMAGE_INIT_PASS;
776}
777
778/***************************************************************************
779    SOFTWARE LIST CARTRIDGE HANDLING
780***************************************************************************/
781
782#define install_write_handler(_start, _end, _handler) \
783   image.device().machine().firstcpu->space(AS_PROGRAM).install_legacy_write_handler(_start, _end, FUNC(_handler));
784
785#define install_io1_handler(_handler) \
786   image.device().machine().firstcpu->space(AS_PROGRAM).install_legacy_write_handler(0xde00, 0xde00, 0, 0xff, FUNC(_handler));
787
788#define install_io2_handler(_handler) \
789   image.device().machine().firstcpu->space(AS_PROGRAM).install_legacy_write_handler(0xdf00, 0xdf00, 0, 0xff, FUNC(_handler));
790
791#define allocate_cartridge_timer(_period, _func) \
792   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>(); \
793   state->m_cartridge_timer = image.device().machine().scheduler().timer_alloc(FUNC(_func)); \
794   state->m_cartridge_timer->adjust(_period, 0);
795
796#define set_game_line(_machine, _state) \
797   _machine.driver_data<legacy_c64_state>()->m_game = _state; \
798   c64_bankswitch(_machine, 0);
799
800INLINE void load_cartridge_region(device_image_interface &image, const char *name, offs_t offset, size_t size)
801{
802   UINT8 *cart = image.device().machine().root_device().memregion("user1")->base();
803   UINT8 *rom = image.get_software_region(name);
804   memcpy(cart + offset, rom, size);
805}
806
807INLINE void map_cartridge_roml(running_machine &machine, offs_t offset)
808{
809   legacy_c64_state *state = machine.driver_data<legacy_c64_state>();
810   UINT8 *cart = state->memregion("user1")->base();
811   memcpy(state->m_roml, cart + offset, 0x2000);
812}
813
814INLINE void map_cartridge_romh(running_machine &machine, offs_t offset)
815{
816   legacy_c64_state *state = machine.driver_data<legacy_c64_state>();
817   UINT8 *cart = state->memregion("user1")->base();
818   memcpy(state->m_romh, cart + offset, 0x2000);
819}
820
821static void load_standard_c64_cartridge(device_image_interface &image)
822{
823   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
824   UINT32 size;
825
826   // is there anything to load at 0x8000?
827   size = image.get_software_region_length("roml");
828
829   if (size)
830   {
831      memcpy(state->m_roml, image.get_software_region("roml"), MIN(0x2000, size));
832
833      if (size == 0x4000)
834      {
835         // continue loading to ROMH region
836         memcpy(state->m_romh, image.get_software_region("roml") + 0x2000, 0x2000);
837      }
838   }
839
840   // is there anything to load at 0xa000?
841   size = image.get_software_region_length("romh");
842   if (size)
843      memcpy(state->m_romh, image.get_software_region("romh"), size);
844}
845
846static TIMER_CALLBACK( vizawrite_timer )
847{
848   map_cartridge_roml(machine, 0x2000);
849   set_game_line(machine, 1);
850}
851
852static void load_vizawrite_cartridge(device_image_interface &image)
853{
854   #define VW64_DECRYPT_ADDRESS(_offset) \
855      BITSWAP16(_offset,15,14,13,12,7,8,6,9,5,11,4,3,2,10,1,0)
856
857   #define VW64_DECRYPT_DATA(_data) \
858      BITSWAP8(_data,7,6,0,5,1,4,2,3)
859
860   UINT8 *roml = image.get_software_region("roml");
861   UINT8 *romh = image.get_software_region("romh");
862   UINT8 *decrypted = image.device().machine().root_device().memregion("user1")->base();
863
864   // decrypt ROMs
865   for (offs_t offset = 0; offset < 0x2000; offset++)
866   {
867      offs_t address = VW64_DECRYPT_ADDRESS(offset);
868      decrypted[address] = VW64_DECRYPT_DATA(roml[offset]);
869      decrypted[address + 0x2000] = VW64_DECRYPT_DATA(roml[offset + 0x2000]);
870      decrypted[address + 0x4000] = VW64_DECRYPT_DATA(romh[offset]);
871   }
872
873   // map cartridge ROMs
874   map_cartridge_roml(image.device().machine(), 0x0000);
875   map_cartridge_romh(image.device().machine(), 0x4000);
876
877   // allocate GAME changing timer
878   allocate_cartridge_timer(attotime::from_msec(1184), vizawrite_timer);
879}
880
881static WRITE8_HANDLER( hugo_bank_w )
882{
883   /*
884
885       bit     description
886
887       0
888       1
889       2
890       3
891       4       A14
892       5       A15
893       6       A16
894       7       A13
895
896   */
897
898   int bank = ((data >> 3) & 0x0e) | BIT(data, 7);
899
900   map_cartridge_roml(space.machine(), bank * 0x2000);
901}
902
903static void load_hugo_cartridge(device_image_interface &image)
904{
905   #define HUGO_DECRYPT_ADDRESS(_offset) \
906      BITSWAP16(_offset,15,14,13,12,7,6,5,4,3,2,1,0,8,9,11,10)
907
908   #define HUGO_DECRYPT_DATA(_data) \
909      BITSWAP8(_data,7,6,5,4,0,1,2,3)
910
911   UINT8 *roml = image.get_software_region("roml");
912   UINT8 *decrypted = image.device().machine().root_device().memregion("user1")->base();
913
914   // decrypt ROMs
915   for (offs_t offset = 0; offset < 0x20000; offset++)
916   {
917      offs_t address = (offset & 0x10000) | HUGO_DECRYPT_ADDRESS(offset);
918      decrypted[address] = HUGO_DECRYPT_DATA(roml[offset]);
919   }
920
921   // map cartridge ROMs
922   map_cartridge_roml(image.device().machine(), 0x0000);
923
924   // install bankswitch handler
925   install_io1_handler(hugo_bank_w);
926}
927
928static WRITE8_HANDLER( easy_calc_result_bank_w )
929{
930   map_cartridge_romh(space.machine(), 0x2000 + (!offset * 0x2000));
931}
932
933static void load_easy_calc_result_cartridge(device_image_interface &image)
934{
935   load_cartridge_region(image, "roml", 0x0000, 0x2000);
936   load_cartridge_region(image, "romh", 0x2000, 0x4000);
937
938   map_cartridge_roml(image.device().machine(), 0x0000);
939   map_cartridge_romh(image.device().machine(), 0x2000);
940
941   install_write_handler(0xde00, 0xde01, easy_calc_result_bank_w);
942}
943
944static WRITE8_HANDLER( pagefox_bank_w )
945{
946   /*
947
948       Die 96KB des Moduls belegen in 6 16K-Banken den Modulbereich von $8000- $c000.
949       Die Umschaltung erfolgt mit einem Register in $DE80 (-$DEFF, nicht voll decodiert),
950       welches nur beschrieben und nicht gelesen werden kann. Durch Schreiben der Werte
951       $08 oder $0A selektiert man eine der beiden RAM-Banke, $FF deselektiert das Modul.
952
953       Zusatzlich muss Adresse 1 entsprechend belegt werden :$37 fur Lesezugriffe auf das
954       Modul, $35 oder $34 fur Lesezugriffe auf das Ram des C64. Schreibzugriffe lenkt
955       der C64 grundsatzlich ins eigene RAM, weshalb zum Beschreiben des Modulrams ein
956       Trick notwendig ist: Man schaltet das Ram-Modul parallel zum C64-Ram, rettet vor
957       dem Schreiben den C64-Ram-Inhalt und stellt ihn nachher wieder her...
958
959       Ldy#0
960       Lda#$35
961       Sta 1
962       Loop Lda (Ptr),y
963       Pha
964       Lda#$08
965       Sta $DE80
966       Lda (Quell),y
967       Sta (Ptr),y
968       Lda#$FF
969       Sta $DE80
970       Pla
971       Sta (Ptr),y
972       Iny
973       Bne Loop
974
975   */
976
977   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
978   UINT8 *cart = state->memregion("user1")->base();
979
980   if (data == 0xff)
981   {
982      // hide cartridge
983      state->m_game = 1;
984      state->m_exrom = 1;
985   }
986   else
987   {
988      if (state->m_game)
989      {
990         // enable cartridge
991         state->m_game = 0;
992         state->m_exrom = 0;
993      }
994
995      int bank = (data >> 1) & 0x07;
996      int ram = BIT(data, 3);
997      offs_t address = bank * 0x4000;
998
999      state->m_roml_writable = ram;
1000
1001      if (ram)
1002      {
1003         state->m_roml = cart + address;
1004      }
1005      else
1006      {
1007         state->m_roml = state->m_c64_roml;
1008
1009         map_cartridge_roml(space.machine(), address);
1010         map_cartridge_romh(space.machine(), address + 0x2000);
1011      }
1012   }
1013
1014   c64_bankswitch(space.machine(), 0);
1015}
1016
1017static void load_pagefox_cartridge(device_image_interface &image)
1018{
1019   load_cartridge_region(image, "rom", 0x0000, 0x10000);
1020
1021   map_cartridge_roml(image.device().machine(), 0x0000);
1022   map_cartridge_romh(image.device().machine(), 0x2000);
1023
1024   install_write_handler(0xde80, 0xdeff, pagefox_bank_w);
1025}
1026
1027static WRITE8_HANDLER( multiscreen_bank_w )
1028{
1029   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
1030   UINT8 *cart = state->memregion("user1")->base();
1031   int bank = data & 0x0f;
1032   offs_t address = bank * 0x4000;
1033
1034   if (bank == 0x0d)
1035   {
1036      // RAM
1037      state->m_roml = cart + address;
1038      state->m_roml_writable = 1;
1039
1040      map_cartridge_romh(space.machine(), 0x2000);
1041   }
1042   else
1043   {
1044      // ROM
1045      state->m_roml = state->m_c64_roml;
1046      state->m_roml_writable = 0;
1047
1048      map_cartridge_roml(space.machine(), address);
1049      map_cartridge_romh(space.machine(), address + 0x2000);
1050   }
1051
1052   c64_bankswitch(space.machine(), 0);
1053}
1054
1055static void load_multiscreen_cartridge(device_image_interface &image)
1056{
1057   load_cartridge_region(image, "roml", 0x0000, 0x4000);
1058   load_cartridge_region(image, "rom", 0x4000, 0x30000);
1059
1060   map_cartridge_roml(image.device().machine(), 0x0000);
1061   map_cartridge_romh(image.device().machine(), 0x2000);
1062
1063   install_write_handler(0xdfff, 0xdfff, multiscreen_bank_w);
1064}
1065
1066static WRITE8_HANDLER( simons_basic_bank_w )
1067{
1068   set_game_line(space.machine(), !BIT(data, 0));
1069}
1070
1071static void load_simons_basic_cartridge(device_image_interface &image)
1072{
1073   load_cartridge_region(image, "roml", 0x0000, 0x2000);
1074   load_cartridge_region(image, "romh", 0x2000, 0x2000);
1075
1076   map_cartridge_roml(image.device().machine(), 0x0000);
1077   map_cartridge_romh(image.device().machine(), 0x2000);
1078
1079   install_io1_handler(simons_basic_bank_w);
1080}
1081
1082static READ8_HANDLER( super_explode_r )
1083{
1084   legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>();
1085
1086   return state->m_roml[0x1f00 | offset];
1087}
1088
1089static WRITE8_HANDLER( super_explode_bank_w )
1090{
1091   map_cartridge_roml(space.machine(), BIT(data, 7) * 0x2000);
1092}
1093
1094static void load_super_explode_cartridge(device_image_interface &image)
1095{
1096   load_cartridge_region(image, "roml", 0x0000, 0x4000);
1097
1098   map_cartridge_roml(image.device().machine(), 0x0000);
1099
1100   address_space &space = image.device().machine().firstcpu->space(AS_PROGRAM);
1101   space.install_legacy_read_handler(0xdf00, 0xdfff, FUNC(super_explode_r));
1102
1103   install_io2_handler(super_explode_bank_w);
1104}
1105
1106static void c64_software_list_cartridge_load(device_image_interface &image)
1107{
1108   legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>();
1109
1110   // initialize ROML and ROMH pointers
1111   state->m_roml = state->m_c64_roml;
1112   state->m_romh = state->m_c64_romh;
1113
1114   // clear ROML and ROMH areas
1115   memset(state->m_roml, 0, 0x2000);
1116   memset(state->m_romh, 0, 0x2000);
1117
1118   // set GAME and EXROM
1119   state->m_game = atol(image.get_feature("game"));
1120   state->m_exrom = atol(image.get_feature("exrom"));
1121
1122   // determine cartridge type
1123   const char *cart_type = image.get_feature("cart_type");
1124
1125   if (cart_type == NULL)
1126   {
1127      load_standard_c64_cartridge(image);
1128   }
1129   else
1130   {
1131      if (!strcmp(cart_type, "vizawrite"))
1132         load_vizawrite_cartridge(image);
1133
1134      else if (!strcmp(cart_type, "hugo"))
1135         load_hugo_cartridge(image);
1136
1137      else if (!strcmp(cart_type, "easy_calc_result"))
1138         load_easy_calc_result_cartridge(image);
1139
1140      else if (!strcmp(cart_type, "pagefox"))
1141         load_pagefox_cartridge(image);
1142
1143      else if (!strcmp(cart_type, "multiscreen"))
1144         /*
1145
1146             TODO: crashes on protection check after cartridge RAM test
1147
1148             805A: lda  $01
1149             805C: and  #$FE
1150             805E: sta  $01
1151             8060: m6502_brk#$00 <-- BOOM!
1152
1153         */
1154         load_multiscreen_cartridge(image);
1155
1156      else if (!strcmp(cart_type, "simons_basic"))
1157         load_simons_basic_cartridge(image);
1158
1159      else if (!strcmp(cart_type, "super_explode"))
1160         load_super_explode_cartridge(image);
1161
1162      else
1163         load_standard_c64_cartridge(image);
1164   }
1165}
1166
1167DEVICE_IMAGE_LOAD_MEMBER( legacy_c64_state, c64_cart )
1168{
1169   int result = IMAGE_INIT_PASS;
1170
1171   if (image.software_entry() != NULL)
1172   {
1173      c64_software_list_cartridge_load(image);
1174   }
1175   else
1176      result = c64_crt_load(image);
1177
1178   return result;
1179}
1180MACHINE_CONFIG_FRAGMENT( c64_cartslot )
1181   MCFG_CARTSLOT_ADD("cart1")
1182   MCFG_CARTSLOT_EXTENSION_LIST("crt,80")
1183   MCFG_CARTSLOT_NOT_MANDATORY
1184   MCFG_CARTSLOT_INTERFACE("c64_cart")
1185   MCFG_CARTSLOT_LOAD(legacy_c64_state,c64_cart)
1186   MCFG_CARTSLOT_UNLOAD(legacy_c64_state,c64_cart)
1187
1188   MCFG_CARTSLOT_ADD("cart2")
1189   MCFG_CARTSLOT_EXTENSION_LIST("crt,80")
1190   MCFG_CARTSLOT_NOT_MANDATORY
1191   MCFG_CARTSLOT_LOAD(legacy_c64_state,c64_cart)
1192   MCFG_CARTSLOT_UNLOAD(legacy_c64_state,c64_cart)
1193
1194   MCFG_SOFTWARE_LIST_ADD("cart_list_c64", "c64_cart")
1195MACHINE_CONFIG_END
trunk/src/mess/machine/mc6854.c
r21684r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2006
4
5  Motorola 6854 emulation.
6
7  The MC6854 chip is an Advanced Data-Link Controller (ADLC).
8  It provides a high-level network interface that can transimit frames with
9  arbitrary data and address length, and is compatible with the following
10  standards:
11  - ADCCP (Advanced Data Communication Control Procedure)
12  - HDLC  (High-Level Data-Link Control)
13  - SDLC  (Synchronous Data-Link Control)
14  It is designed to be interfaced with a M6800-family CPU.
15
16  It is used in the "Nano-network" extension of the Thomson computers to
17  link up to 32 computers at 500 Kbps.
18  Many networks involving one PC server and several MO5 or TO7/70 computers
19  were build in French schools in the 1980's to teach computer science.
20
21  TODO:
22  - CRC
23  - DMA mode
24  - loop mode
25  - status prioritization
26  - NRZI vs. NRZ coding
27  - FD output
28
29**********************************************************************/
30
31
32#include "emu.h"
33#include "mc6854.h"
34
35
36
37/******************* parameters ******************/
38
39
40
41#define VERBOSE 0
42
43
44#define MAX_FRAME_LENGTH 65536
45/* arbitrary value, you may need to enlarge it if you get truncated frames */
46
47#define FIFO_SIZE 3
48/* hardcoded size of the 6854 FIFO (this is a hardware limit) */
49
50#define FLAG 0x7e
51/* flag value, as defined by HDLC protocol: 01111110 */
52
53#define BIT_LENGTH attotime::from_hz( 500000 )
54
55
56
57/******************* internal chip data structure ******************/
58
59
60struct mc6854_t
61{
62   devcb_resolved_write_line   out_irq_func;
63   devcb_resolved_read_line    in_rxd_func;
64   devcb_resolved_write_line   out_txd_func;
65   devcb_resolved_write_line   out_rts_func;
66   devcb_resolved_write_line   out_dtr_func;
67
68   /* interface */
69   const mc6854_interface* iface;
70
71   /* registers */
72   UINT8 cr1, cr2, cr3, cr4; /* control registers */
73   UINT8 sr1, sr2;           /* status registers */
74
75   UINT8 cts, dcd;
76
77   /* transmit state */
78   UINT8  tstate;
79   UINT16 tfifo[FIFO_SIZE];  /* X x 8-bit FIFO + full & last marker bits */
80   UINT8  tones;             /* counter for zero-insertion */
81   emu_timer *ttimer;       /* when to ask for more data */
82
83   /* receive state */
84   UINT8  rstate;
85   UINT32 rreg;              /* shift register */
86   UINT8  rones;             /* count '1 bits */
87   UINT8  rsize;             /* bits in the shift register */
88   UINT16 rfifo[FIFO_SIZE];  /* X x 8-bit FIFO + full & addr marker bits */
89
90   /* frame-based interface*/
91   UINT8  frame[MAX_FRAME_LENGTH];
92   UINT32 flen, fpos;
93
94};
95
96/* meaning of tstate / rtate:
97   0 = idle / waiting for frame flag
98   1 = flag sync
99   2 = 8-bit address field(s)
100   3-4 = 8-bit control field(s)
101   5 = 8-bit logical control field(s)
102   6 = variable-length data field(s)
103*/
104
105
106
107/******************* utility function and macros ********************/
108
109
110
111#define LOG(x)  do { if (VERBOSE) logerror x; } while (0)
112
113
114
115/* control register 1 */
116
117#define AC ( mc6854->cr1 & 1 )
118#define FCTDRA ( mc6854->cr2 & 8 )
119/* extra register select bits */
120
121#define RRESET ( mc6854->cr1 & 0x40 )
122#define TRESET ( mc6854->cr1 & 0x80 )
123/* transmit / reset condition */
124
125#define RIE ( mc6854->cr1 & 2 )
126#define TIE ( mc6854->cr1 & 4 )
127/* interrupt enable */
128
129#define DISCONTINUE ( mc6854->cr1 & 0x20 )
130/* discontinue received frame */
131
132
133
134/* control register 2 */
135
136#define PSE ( mc6854->cr2 & 1 )
137/* prioritize status bits (TODO) */
138
139#define TWOBYTES ( mc6854->cr2 & 2 )
140/* two-bytes mode */
141
142#define FMIDLE ( mc6854->cr2 & 4 )
143/* flag time fill (vs. mark idle) */
144
145#define TLAST ( mc6854->cr2 & 0x10 )
146/* transmit last byte of frame */
147
148#define RTS ( mc6854->cr2 & 0x80 )
149/* request-to-send */
150
151
152
153/* control register 3 */
154
155#define LCF ( mc6854->cr3 & 1 )
156/* logical control field select */
157
158#define CEX ( mc6854->cr3 & 2 )
159/* control field is 16 bits instead of 8 */
160
161#define AEX ( mc6854->cr3 & 4 )
162/* extended address mode (vs normal 8-bit address mode) */
163
164#define IDL0 ( mc6854->cr3 & 8 )
165/* idle condition begins with a '0' instead of a '1" */
166
167#define FDSE ( mc6854->cr3 & 0x10 )
168/* enable the flag detect status in SR1 */
169
170#define LOOP ( mc6854->cr3 & 0x20 )
171/* loop mode */
172
173#define TST ( mc6854->cr3 & 0x40 )
174/* test mode (or go active on poll) */
175
176#define DTR ( mc6854->cr3 & 0x80 )
177/* data-transmit-ready (or loop on-line control) */
178
179
180
181/* control register 4 */
182
183#define TWOINTER ( mc6854->cr4 & 1 )
184/* both an openning and a closing inter-frame are sent */
185
186static const int word_length[4] = { 5, 6, 7, 8 };
187#define TWL word_length[ ( mc6854->cr4 >> 1 ) & 3 ]
188#define RWL word_length[ ( mc6854->cr4 >> 3 ) & 3 ]
189/* transmit / receive word length */
190
191#define ABT ( mc6854->cr4 & 0x20 )
192/* aborts */
193
194#define ABTEX ( mc6854->cr4 & 0x40 )
195/* abort generates 16 '1' bits instead of 8 */
196
197#define NRZ ( mc6854->cr4 & 0x80 )
198/* zero complement / non-zero complement data format */
199
200
201
202/* status register 1 */
203#define RDA  0x01  /* receiver data available */
204#define S2RQ 0x02  /* status register #2 read request */
205#define FD   0x04  /* flag detect */
206#define CTS  0x10  /* clear-to-send */
207#define TU   0x20  /* transmitter underrun */
208#define TDRA 0x40  /* transmitter data register available */
209#define IRQ  0x80  /* interrupt request */
210
211
212/* status register 2 */
213#define AP    0x01  /* address present */
214#define FV    0x02  /* frame valid */
215#define RIDLE 0x04  /* receiver idle */
216#define RABT  0x08  /* receiver abort */
217#define ERR   0x10  /* invalid frame error */
218#define DCD   0x20  /* data carrier detect (ignored) */
219#define OVRN  0x40  /* receiver overrun */
220#define RDA2  0x80  /* copy of RDA */
221
222
223
224INLINE mc6854_t* get_safe_token( device_t *device )
225{
226   assert( device != NULL );
227   assert( device->type() == MC6854 );
228   return (mc6854_t*) downcast<mc6854_device *>(device)->token();
229}
230
231
232/*********************** transmit ***********************/
233
234
235
236/* MC6854 fills bit queue */
237static void mc6854_send_bits( device_t *device, UINT32 data, int len, int zi )
238{
239   mc6854_t* mc6854 = get_safe_token( device );
240   attotime expire;
241   int i;
242   if ( zi )
243   {
244      /* zero-insertion mode */
245      UINT32 d = 0;
246      int l = 0;
247      for ( i = 0; i < len; i++, data >>= 1, l++ )
248      {
249         if ( data & 1 )
250         {
251            d |= 1 << l;
252            mc6854->tones++;
253            if ( mc6854->tones == 5 )
254            {
255               /* insert a '0' after 5 consecutive '1" */
256               mc6854->tones = 0;
257               l++;
258            }
259         }
260         else
261            mc6854->tones = 0;
262      }
263      data = d;
264      len = l;
265   }
266   else
267      mc6854->tones = 0;
268
269   /* send bits */
270   if ( !mc6854->out_txd_func.isnull() )
271   {
272      for ( i = 0; i < len; i++, data >>= 1 )
273         mc6854->out_txd_func( data & 1 );
274   }
275
276   /* schedule when to ask the MC6854 for more bits */
277   expire = mc6854->ttimer ->remaining( );
278   if ( expire== attotime::never )
279      expire = attotime::zero;
280   mc6854->ttimer->reset( expire + (BIT_LENGTH * len));
281}
282
283
284
285/* CPU push -> tfifo[0] -> ... -> tfifo[FIFO_SIZE-1] -> pop */
286static void mc6854_tfifo_push( device_t *device, UINT8 data )
287{
288   mc6854_t* mc6854 = get_safe_token( device );
289   int i;
290
291   if ( TRESET )
292      return;
293
294   /* push towards the rightmost free entry */
295   for ( i = FIFO_SIZE - 1; i >= 0; i-- )
296   {
297      if ( ! ( mc6854->tfifo[ i ] & 0x100 ) )
298         break;
299   }
300
301   if ( i >= 0 )
302      mc6854->tfifo[ i ] = data | 0x100;
303   else
304      logerror( "%f mc6854_tfifo_push: FIFO overrun\n", device->machine().time().as_double() );
305
306   /* start frame, if needed */
307   if ( ! mc6854->tstate )
308   {
309      LOG(( "%f mc6854_tfifo_push: start frame\n", device->machine().time().as_double() ));
310      mc6854->tstate = 2;
311      mc6854_send_bits( device, FLAG, 8, 0 );
312   }
313}
314
315
316
317/* CPU asks for normal frame termination */
318static void mc6854_tfifo_terminate( device_t *device )
319{
320   mc6854_t* mc6854 = get_safe_token( device );
321
322   /* mark most recently pushed byte as the last one of the frame */
323   int i;
324   for ( i = 0; i < FIFO_SIZE; i++ )
325   {
326      if ( mc6854->tfifo[ i ] & 0x100 )
327      {
328         mc6854->tfifo[ i ] |= 0x200;
329         break;
330      }
331   }
332}
333
334
335
336/* call-back to refill the bit-stream from the FIFO */
337static TIMER_CALLBACK(mc6854_tfifo_cb)
338{
339   device_t* device = (device_t*) ptr;
340   mc6854_t* mc6854 = get_safe_token( device );
341   int i, data = mc6854->tfifo[ FIFO_SIZE - 1 ];
342
343   if ( ! mc6854->tstate )
344      return;
345
346   /* shift FIFO to the right */
347   for ( i = FIFO_SIZE - 1; i > 0; i-- )
348      mc6854->tfifo[ i ] = mc6854->tfifo[ i - 1 ];
349   mc6854->tfifo[ 0 ] = 0;
350
351   if ( data & 0x100 )
352   {
353      /* got data */
354
355      int blen = 8;
356
357      switch ( mc6854->tstate )
358      {
359      case 2: /* 8-bit address field */
360         if ( ( data & 1 ) || ( ! AEX ) )
361            mc6854->tstate = 3;
362         LOG(( "%f mc6854_tfifo_cb: address field $%02X\n", machine.time().as_double(), data & 0xff ));
363         break;
364
365      case 3: /* 8-bit control field */
366         if ( CEX )
367            mc6854->tstate = 4;
368         else if ( LCF )
369            mc6854->tstate = 5;
370         else
371            mc6854->tstate = 6;
372         LOG(( "%f mc6854_tfifo_cb: control field $%02X\n", machine.time().as_double(), data & 0xff ));
373         break;
374
375      case 4: /* 8-bit extended control field (optional) */
376         if ( LCF )
377            mc6854->tstate = 5;
378         else
379            mc6854->tstate = 6;
380         LOG(( "%f mc6854_tfifo_cb: control field $%02X\n", machine.time().as_double(), data & 0xff ));
381         break;
382
383      case 5: /* 8-bit logical control (optional) */
384         if ( ! ( data & 0x80 ) )
385            mc6854->tstate = 6;
386         LOG(( "%f mc6854_tfifo_cb: logical control field $%02X\n", machine.time().as_double(), data & 0xff ));
387         break;
388
389      case 6: /* variable-length data */
390         blen = TWL;
391         LOG(( "%f mc6854_tfifo_cb: data field $%02X, %i bits\n", machine.time().as_double(), data & 0xff, blen ));
392         break;
393
394      default:
395         LOG(( "%f mc6854_tfifo_cb: state=%i\n", machine.time().as_double(), mc6854->tstate));
396      }
397
398      if ( mc6854->flen < MAX_FRAME_LENGTH )
399         mc6854->frame[ mc6854->flen++ ] = data;
400      else
401         logerror( "mc6854_tfifo_cb: truncated frame, max=%i\n", MAX_FRAME_LENGTH );
402
403      mc6854_send_bits( device, data, blen, 1 );
404   }
405   else
406   {
407      /* data underrun => abort */
408      logerror( "%f mc6854_tfifo_cb: FIFO underrun\n", machine.time().as_double() );
409      mc6854->sr1 |= TU;
410      mc6854->tstate = 0;
411      mc6854_send_bits( device, 0xffff, ABTEX ? 16 : 8, 0 );
412      mc6854->flen = 0;
413   }
414
415   /* close frame, if needed */
416   if ( data & 0x200 )
417   {
418      int len = mc6854->flen;
419
420      LOG(( "%f mc6854_tfifo_cb: end frame\n", machine.time().as_double() ));
421      mc6854_send_bits( device, 0xdeadbeef, 16, 1 );  /* send check-sum: TODO */
422      mc6854_send_bits( device, FLAG, 8, 0 );         /* send closing flag */
423
424      if ( mc6854->tfifo[ FIFO_SIZE - 1 ] & 0x100 )
425      {
426         /* re-open frame asap */
427         LOG(( "%f mc6854_tfifo_cb: start frame\n", machine.time().as_double() ));
428         if ( TWOINTER )
429            mc6854_send_bits( device, FLAG, 8, 0 );
430      }
431      else
432         mc6854->tstate = 0;
433
434      mc6854->flen = 0;
435      if ( mc6854->iface->out_frame )
436         mc6854->iface->out_frame( device, mc6854->frame, len );
437   }
438}
439
440
441
442static void mc6854_tfifo_clear( device_t *device )
443{
444   mc6854_t* mc6854 = get_safe_token( device );
445   memset( mc6854->tfifo, 0, sizeof( mc6854->tfifo ) );
446   mc6854->tstate = 0;
447   mc6854->flen = 0;
448   mc6854->ttimer->reset(  );
449}
450
451
452
453/*********************** receive ***********************/
454
455
456
457/* MC6854 pushes a field in the FIFO */
458static void mc6854_rfifo_push( device_t *device, UINT8 d )
459{
460   mc6854_t* mc6854 = get_safe_token( device );
461   int i, blen = 8;
462   unsigned data = d;
463
464   switch ( mc6854->rstate )
465   {
466   case 0:
467   case 1:
468   case 2: /* 8-bit address field */
469      if ( ( data & 1 ) || ( ! AEX ) )
470         mc6854->rstate = 3;
471      else
472         mc6854->rstate = 2;
473      LOG(( "%f mc6854_rfifo_push: address field $%02X\n", device->machine().time().as_double(), data ));
474      data |= 0x400; /* address marker */
475      break;
476
477   case 3: /* 8-bit control field */
478      if ( CEX )
479         mc6854->rstate = 4;
480      else if ( LCF )
481         mc6854->rstate = 5;
482      else
483         mc6854->rstate = 6;
484      LOG(( "%f mc6854_rfifo_push: control field $%02X\n", device->machine().time().as_double(), data ));
485      break;
486
487   case 4: /* 8-bit extended control field (optional) */
488      if ( LCF )
489         mc6854->rstate = 5;
490      else
491         mc6854->rstate = 6;
492      LOG(( "%f mc6854_rfifo_push: control field $%02X\n", device->machine().time().as_double(), data ));
493      break;
494
495   case 5: /* 8-bit logical control (optional) */
496      if ( ! ( data & 0x80 ) )
497         mc6854->rstate = 6;
498      LOG(( "%f mc6854_rfifo_push: logical control field $%02X\n", device->machine().time().as_double(), data ));
499      break;
500
501   case 6: /* variable-length data */
502      blen = RWL;
503      data >>= 8 - blen;
504      LOG(( "%f mc6854_rfifo_push: data field $%02X, %i bits\n", device->machine().time().as_double(), data, blen ));
505      break;
506   }
507
508   /* no further FIFO fill until FV is cleared! */
509   if ( mc6854->sr2 & FV )
510   {
511      LOG(( "%f mc6854_rfifo_push: field not pushed\n", device->machine().time().as_double() ));
512      return;
513   }
514
515   data |= 0x100; /* entry full marker */
516
517   /* push towards the rightmost free entry */
518   for ( i = FIFO_SIZE - 1; i >= 0; i-- )
519   {
520      if ( ! ( mc6854->rfifo[ i ] & 0x100 ) )
521         break;
522   }
523
524   if ( i >= 0 )
525      mc6854->rfifo[ i ] = data | 0x100;
526   else
527   {
528      /* FIFO full */
529      mc6854->sr2 |= OVRN;
530      mc6854->rfifo[ 0 ] = data;
531      logerror( "%f mc6854_rfifo_push: FIFO overrun\n", device->machine().time().as_double() );
532   }
533
534   mc6854->rsize -= blen;
535}
536
537
538
539static void mc6854_rfifo_terminate( device_t *device )
540{
541   mc6854_t* mc6854 = get_safe_token( device );
542   /* mark most recently pushed byte as the last one of the frame */
543   int i;
544   for ( i = 0; i < FIFO_SIZE; i++ )
545   {
546      if ( mc6854->rfifo[ i ] & 0x100 )
547      {
548         mc6854->tfifo[ i ] |= 0x200;
549         break;
550      }
551
552   }
553
554   mc6854->flen = 0;
555   mc6854->rstate = 1;
556}
557
558
559
560/* CPU pops the FIFO */
561static UINT8 mc6854_rfifo_pop( device_t *device )
562{
563   mc6854_t* mc6854 = get_safe_token( device );
564   int i, data = mc6854->rfifo[ FIFO_SIZE - 1 ];
565
566   /* shift FIFO to the right */
567   for ( i = FIFO_SIZE - 1; i > 0; i -- )
568      mc6854->rfifo[ i ] = mc6854->rfifo[ i - 1 ];
569   mc6854->rfifo[ 0 ] = 0;
570
571   if ( mc6854->rfifo[ FIFO_SIZE - 1 ] & 0x200 )
572   {
573      /* last byte in frame */
574      mc6854->sr2 |= FV; /* TODO: check CRC & set ERR instead of FV if error*/
575   }
576
577   /* auto-refill in frame mode */
578   if ( mc6854->flen > 0 )
579   {
580      mc6854_rfifo_push( device, mc6854->frame[ mc6854->fpos++ ] );
581      if ( mc6854->fpos == mc6854->flen )
582         mc6854_rfifo_terminate( device );
583   }
584
585   return data;
586}
587
588
589/* MC6854 makes fields from bits */
590WRITE_LINE_DEVICE_HANDLER( mc6854_set_rx )
591{
592   mc6854_t* mc6854 = get_safe_token( device );
593   int fieldlen = ( mc6854->rstate < 6 ) ? 8 : RWL;
594
595   if ( RRESET || (mc6854->sr2 & DCD) )
596      return;
597
598   if ( state )
599   {
600      mc6854->rones++;
601      mc6854->rreg = (mc6854->rreg >> 1) | 0x80000000;
602      if ( mc6854->rones >= 8 )
603      {
604         /* abort */
605         mc6854->rstate = 0;
606         mc6854->rsize = 0;
607         if ( mc6854->rstate > 1 )
608         {
609            /* only in-frame abort */
610            mc6854->sr2 |= RABT;
611            LOG(( "%f mc6854_receive_bit: abort\n", device->machine().time().as_double() ));
612         }
613      }
614      else
615      {
616         mc6854->rsize++;
617         if ( mc6854->rstate && mc6854->rsize >= fieldlen + 24 )
618            mc6854_rfifo_push( device, mc6854->rreg );
619      }
620   }
621   else if ( mc6854->rones == 5 )
622   {
623      /* discards '0' inserted after 5 '1' */
624      mc6854->rones = 0;
625      return;
626   }
627   else if ( mc6854->rones == 6 )
628   {
629      /* flag */
630      if ( FDSE )
631         mc6854->sr1 |= FD;
632
633      if ( mc6854->rstate > 1 )
634      {
635         /* end of frame */
636         mc6854->rreg >>= 1;
637         mc6854->rsize++;
638         if ( mc6854->rsize >= fieldlen + 24 ) /* last field */
639            mc6854_rfifo_push( device, mc6854->rreg );
640         mc6854_rfifo_terminate( device );
641         LOG(( "%f mc6854_receive_bit: end of frame\n", device->machine().time().as_double() ));
642      }
643      mc6854->rones = 0;
644      mc6854->rstate = 1;
645      mc6854->rsize = 0;
646   } else
647   {
648      mc6854->rones = 0;
649      mc6854->rreg >>= 1;
650      mc6854->rsize++;
651      if ( mc6854->rstate && mc6854->rsize >= fieldlen + 24 )
652         mc6854_rfifo_push( device, mc6854->rreg );
653   }
654}
655
656
657
658static void mc6854_rfifo_clear( device_t *device )
659{
660   mc6854_t* mc6854 = get_safe_token( device );
661   memset( mc6854->rfifo, 0, sizeof( mc6854->rfifo ) );
662   mc6854->rstate = 0;
663   mc6854->rreg = 0;
664   mc6854->rsize = 0;
665   mc6854->rones = 0;
666   mc6854->flen = 0;
667}
668
669
670
671int mc6854_send_frame( device_t *device, UINT8* data, int len )
672{
673   mc6854_t* mc6854 = get_safe_token( device );
674   if ( mc6854->rstate > 1 || mc6854->tstate > 1 || RTS )
675      return -1; /* busy */
676
677   if ( len > MAX_FRAME_LENGTH )
678   {
679      logerror( "mc6854_send_frame: truncated frame, size=%i, max=%i\n", len, MAX_FRAME_LENGTH );
680      len = MAX_FRAME_LENGTH;
681   }
682   else if ( len < 2 )
683   {
684      logerror( "mc6854_send_frame: frame too short, size=%i, min=2\n", len );
685      len = 2;
686   }
687   memcpy( mc6854->frame, data, len );
688   if ( FDSE )
689      mc6854->sr1 |= FD;
690   mc6854->flen = len;
691   mc6854->fpos = 0;
692   mc6854_rfifo_push( device, mc6854->frame[ mc6854->fpos++ ] );
693   mc6854_rfifo_push( device, mc6854->frame[ mc6854->fpos++ ] );
694   if ( mc6854->fpos == mc6854->flen )
695      mc6854_rfifo_terminate( device );
696   return 0;
697}
698
699
700
701/************************** CPU interface ****************************/
702
703
704
705WRITE_LINE_DEVICE_HANDLER( mc6854_set_cts )
706{
707   mc6854_t* mc6854 = get_safe_token( device );
708   if ( ! mc6854->cts && state )
709      mc6854->sr1 |= CTS;
710   mc6854->cts = state;
711
712   if ( mc6854->cts )
713      mc6854->sr1 |= CTS;
714   else
715      mc6854->sr1 &= ~CTS;
716}
717
718
719
720WRITE_LINE_DEVICE_HANDLER( mc6854_set_dcd )
721{
722   mc6854_t* mc6854 = get_safe_token( device );
723   if ( ! mc6854->dcd && state )
724   {
725      mc6854->sr2 |= DCD;
726      /* partial reset */
727      mc6854->rstate = 0;
728      mc6854->rreg = 0;
729      mc6854->rsize = 0;
730      mc6854->rones = 0;
731   }
732   mc6854->dcd = state;
733}
734
735
736
737static void mc6854_update_sr2( mc6854_t* mc6854 )
738{
739   /* update RDA */
740   mc6854->sr2 |= RDA2;
741   if ( ! (mc6854->rfifo[ FIFO_SIZE - 1 ] & 0x100) )
742      mc6854->sr2 &= ~RDA2;
743   else if ( TWOBYTES && ! (mc6854->tfifo[ FIFO_SIZE - 2 ] & 0x100) )
744      mc6854->sr2 &= ~RDA2;
745
746   /* update AP */
747   if ( mc6854->rfifo[ FIFO_SIZE - 1 ] & 0x400 )
748      mc6854->sr2 |= AP;
749   else
750      mc6854->sr2 &= ~AP;
751}
752
753
754
755static void mc6854_update_sr1( mc6854_t* mc6854 )
756{
757   mc6854_update_sr2( mc6854 );
758
759   /* update S2RQ */
760   if ( mc6854->sr2 & 0x7f )
761      mc6854->sr1 |= S2RQ;
762   else
763      mc6854->sr1 &= ~S2RQ;
764
765   /* update TRDA (always prioritized by CTS) */
766   if ( TRESET || ( mc6854->sr1 & CTS ) )
767      mc6854->sr1 &= ~TDRA;
768   else
769   {
770      mc6854->sr1 |= TDRA;
771      if ( mc6854->tfifo[ 0 ] & 0x100 )
772         mc6854->sr1 &= ~TDRA;
773      else if ( TWOBYTES && (mc6854->tfifo[ 1 ] & 0x100) )
774         mc6854->sr1 &= ~TDRA;
775   }
776
777   /* update RDA */
778   if ( mc6854->sr2 & RDA2 )
779      mc6854->sr1 |= RDA;
780   else
781      mc6854->sr1 &= ~RDA;
782
783   /* update IRQ */
784   mc6854->sr1 &= ~IRQ;
785   if ( RIE && (mc6854->sr1 & (TU | TDRA) ) )
786      mc6854->sr1 |= IRQ;
787   if ( TIE )
788   {
789      if ( mc6854->sr1 & (S2RQ | RDA | CTS) )
790         mc6854->sr1 |= IRQ;
791      if ( mc6854->sr2 & (ERR | FV | DCD | OVRN | RABT | RIDLE | AP) )
792         mc6854->sr1 |= IRQ;
793   }
794
795   mc6854->out_irq_func((mc6854->sr1 & IRQ) ? ASSERT_LINE : CLEAR_LINE);
796}
797
798
799
800READ8_DEVICE_HANDLER ( mc6854_r )
801{
802   mc6854_t* mc6854 = get_safe_token( device );
803   switch ( offset )
804   {
805   case 0: /* status register 1 */
806      mc6854_update_sr1( mc6854 );
807      LOG(( "%f $%04x mc6854_r: get SR1=$%02X (rda=%i,s2rq=%i,fd=%i,cts=%i,tu=%i,tdra=%i,irq=%i)\n",
808            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->sr1,
809            ( mc6854->sr1 & RDA) ? 1 : 0, ( mc6854->sr1 & S2RQ) ? 1 : 0,
810            ( mc6854->sr1 & FD ) ? 1 : 0, ( mc6854->sr1 & CTS ) ? 1 : 0,
811            ( mc6854->sr1 & TU ) ? 1 : 0, ( mc6854->sr1 & TDRA) ? 1 : 0,
812            ( mc6854->sr1 & IRQ) ? 1 : 0 ));
813      return mc6854->sr1;
814
815   case 1: /* status register 2 */
816      mc6854_update_sr2( mc6854 );
817      LOG(( "%f $%04x mc6854_r: get SR2=$%02X (ap=%i,fv=%i,ridle=%i,rabt=%i,err=%i,dcd=%i,ovrn=%i,rda2=%i)\n",
818            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->sr2,
819            ( mc6854->sr2 & AP   ) ? 1 : 0, ( mc6854->sr2 & FV  ) ? 1 : 0,
820            ( mc6854->sr2 & RIDLE) ? 1 : 0, ( mc6854->sr2 & RABT) ? 1 : 0,
821            ( mc6854->sr2 & ERR  ) ? 1 : 0, ( mc6854->sr2 & DCD ) ? 1 : 0,
822            ( mc6854->sr2 & OVRN ) ? 1 : 0, ( mc6854->sr2 & RDA2) ? 1 : 0 ));
823      return mc6854->sr2;
824
825   case 2: /* receiver data register */
826   case 3:
827   {
828      UINT8 data = mc6854_rfifo_pop( device );
829      LOG(( "%f $%04x mc6854_r: get data $%02X\n",
830            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data ));
831      return data;
832   }
833
834   default:
835      logerror( "$%04x mc6854 invalid read offset %i\n", space.machine().firstcpu->pcbase( ), offset );
836   }
837   return 0;
838}
839
840
841
842WRITE8_DEVICE_HANDLER ( mc6854_w )
843{
844   mc6854_t* mc6854 = get_safe_token( device );
845   switch ( offset )
846   {
847   case 0: /* control register 1 */
848      mc6854->cr1 = data;
849      LOG(( "%f $%04x mc6854_w: set CR1=$%02X (ac=%i,irq=%c%c,%sreset=%c%c)\n",
850            space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr1,
851            AC ? 1 : 0,
852            RIE ? 'r' : '-', TIE ? 't' : '-',
853            DISCONTINUE ? "discontinue," : "",
854            RRESET ? 'r' : '-', TRESET ? 't' : '-'
855            ));
856      if ( mc6854->cr1 & 0xc )
857         logerror( "$%04x mc6854 DMA not handled (CR1=$%02X)\n",
858               space.machine().firstcpu->pcbase( ), mc6854->cr1 );
859      if ( DISCONTINUE )
860      {
861         /* abort receive FIFO but keeps shift register & synchro */
862         mc6854->rstate = 0;
863         memset( mc6854->rfifo, 0, sizeof( mc6854->rfifo ) );
864      }
865      if ( RRESET )
866      {
867         /* abort FIFO & synchro */
868         mc6854_rfifo_clear( device );
869         mc6854->sr1 &= ~FD;
870         mc6854->sr2 &= ~(AP | FV | RIDLE | RABT | ERR | OVRN | DCD);
871         if ( mc6854->dcd ) mc6854->sr2 |= DCD;
872      }
873      if ( TRESET )
874      {
875         mc6854_tfifo_clear( device );
876         mc6854->sr1 &= ~(TU | TDRA | CTS);
877         if ( mc6854->cts ) mc6854->sr1 |= CTS;
878      }
879      break;
880
881   case 1:
882      if ( AC )
883      {
884         /* control register 3 */
885         mc6854->cr3 = data;
886         LOG(( "%f $%04x mc6854_w: set CR3=$%02X (lcf=%i,aex=%i,idl=%i,fdse=%i,loop=%i,tst=%i,dtr=%i)\n",
887               space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr3,
888               LCF ? (CEX ? 16 : 8) : 0,  AEX ? 1 : 0,
889               IDL0 ? 0 : 1, FDSE ? 1 : 0, LOOP ? 1 : 0,
890               TST ? 1 : 0, DTR ? 1 : 0
891               ));
892         if ( LOOP )
893            logerror( "$%04x mc6854 loop mode not handled (CR3=$%02X)\n", space.machine().firstcpu->pcbase( ), mc6854->cr3 );
894         if ( TST )
895            logerror( "$%04x mc6854 test mode not handled (CR3=$%02X)\n", space.machine().firstcpu->pcbase( ), mc6854->cr3 );
896
897         mc6854->out_dtr_func( DTR ? 1 : 0 );
898
899      }
900      else
901      {
902         /* control register 2 */
903         mc6854->cr2 = data;
904         LOG(( "%f $%04x mc6854_w: set CR2=$%02X (pse=%i,bytes=%i,fmidle=%i,%s,tlast=%i,clr=%c%c,rts=%i)\n",
905               space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr2,
906               PSE ? 1 : 0,  TWOBYTES ? 2 : 1,  FMIDLE ? 1 : 0,
907               FCTDRA ? "fc" : "tdra", TLAST ? 1 : 0,
908               data & 0x20 ? 'r' : '-',  data & 0x40 ? 't' : '-',
909               RTS ? 1 : 0 ));
910         if ( PSE )
911            logerror( "$%04x mc6854 status prioritization not handled (CR2=$%02X)\n", space.machine().firstcpu->pcbase( ), mc6854->cr2 );
912         if ( TLAST )
913            mc6854_tfifo_terminate( device );
914         if ( data & 0x20 )
915         {
916            /* clear receiver status */
917            mc6854->sr1 &= ~FD;
918            mc6854->sr2 &= ~(AP | FV | RIDLE | RABT | ERR | OVRN | DCD);
919            if ( mc6854->dcd )
920               mc6854->sr2 |= DCD;
921         }
922         if ( data & 0x40 )
923         {
924            /* clear transmitter status */
925            mc6854->sr1 &= ~(TU | TDRA | CTS);
926            if ( mc6854->cts )
927               mc6854->sr1 |= CTS;
928         }
929
930         mc6854->out_rts_func( RTS ? 1 : 0 );
931      }
932      break;
933
934   case 2: /* transmitter data: continue data */
935      LOG(( "%f $%04xmc6854_w: push data=$%02X\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data ));
936      mc6854_tfifo_push( device, data );
937      break;
938
939   case 3:
940      if ( AC )
941      {
942         /* control register 4 */
943         mc6854->cr4 = data;
944         LOG(( "%f $%04x mc6854_w: set CR4=$%02X (interframe=%i,tlen=%i,rlen=%i,%s%s)\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr4,
945               TWOINTER ? 2 : 1,
946               TWL, RWL,
947               ABT ? ( ABTEX ? "abort-ext," : "abort,") : "",
948               NRZ ? "nrz" : "nrzi" ));
949         if ( ABT )
950         {
951            mc6854->tstate = 0;
952            mc6854_send_bits( device, 0xffff, ABTEX ? 16 : 8, 0 );
953            mc6854->flen = 0;
954         }
955      }
956      else
957      {
958         /* transmitter data: last data */
959         LOG(( "%f $%04x mc6854_w: push last-data=$%02X\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data ));
960         mc6854_tfifo_push( device, data );
961         mc6854_tfifo_terminate( device );
962      }
963      break;
964
965   default:
966      logerror( "$%04x mc6854 invalid write offset %i (data=$%02X)\n", space.machine().firstcpu->pcbase( ), offset, data );
967   }
968}
969
970WRITE_LINE_DEVICE_HANDLER( mc6854_rxc_w )
971{
972   // TODO
973}
974
975WRITE_LINE_DEVICE_HANDLER( mc6854_txc_w )
976{
977   // TODO
978}
979
980/************************ reset *****************************/
981
982static DEVICE_RESET( mc6854 )
983{
984   mc6854_t* mc6854 = get_safe_token( device );
985   LOG (( "mc6854 reset\n" ));
986   mc6854->cr1 = 0xc0; /* reset condition */
987   mc6854->cr2 = 0;
988   mc6854->cr3 = 0;
989   mc6854->cr4 = 0;
990   mc6854->sr1 = 0;
991   mc6854->sr2 = 0;
992   mc6854->cts = 0;
993   mc6854->dcd = 0;
994   mc6854_tfifo_clear( device );
995   mc6854_rfifo_clear( device );
996}
997
998
999
1000/************************ start *****************************/
1001
1002static DEVICE_START( mc6854 )
1003{
1004   mc6854_t* mc6854 = get_safe_token( device );
1005
1006   mc6854->iface = (const mc6854_interface*)device->static_config();
1007   mc6854->out_irq_func.resolve(mc6854->iface->out_irq_func, *device);
1008   mc6854->in_rxd_func.resolve(mc6854->iface->in_rxd_func, *device);
1009   mc6854->out_txd_func.resolve(mc6854->iface->out_txd_func, *device);
1010   mc6854->out_rts_func.resolve(mc6854->iface->out_rts_func, *device);
1011   mc6854->out_dtr_func.resolve(mc6854->iface->out_dtr_func, *device);
1012
1013   mc6854->ttimer = device->machine().scheduler().timer_alloc(FUNC(mc6854_tfifo_cb), (void*) device );
1014
1015   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr1 );
1016   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr2 );
1017   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr3 );
1018   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr4 );
1019   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->sr1 );
1020   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->sr2 );
1021   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cts );
1022   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->dcd );
1023   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->tstate );
1024   state_save_register_item_array( device->machine(), "mc6854", device->tag(), 0, mc6854->tfifo );
1025   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->tones );
1026   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rstate );
1027   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rreg );
1028   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rones );
1029   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rsize );
1030   state_save_register_item_array( device->machine(), "mc6854", device->tag(), 0, mc6854->rfifo );
1031   state_save_register_item_array( device->machine(), "mc6854", device->tag(), 0, mc6854->frame );
1032   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->flen );
1033   state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->fpos );
1034}
1035
1036
1037
1038const device_type MC6854 = &device_creator<mc6854_device>;
1039
1040mc6854_device::mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1041   : device_t(mconfig, MC6854, "Motorola MC6854 ADLC", tag, owner, clock)
1042{
1043   m_token = global_alloc_clear(mc6854_t);
1044}
1045
1046//-------------------------------------------------
1047//  device_config_complete - perform any
1048//  operations now that the configuration is
1049//  complete
1050//-------------------------------------------------
1051
1052void mc6854_device::device_config_complete()
1053{
1054}
1055
1056//-------------------------------------------------
1057//  device_start - device-specific startup
1058//-------------------------------------------------
1059
1060void mc6854_device::device_start()
1061{
1062   DEVICE_START_NAME( mc6854 )(this);
1063}
1064
1065//-------------------------------------------------
1066//  device_reset - device-specific reset
1067//-------------------------------------------------
1068
1069void mc6854_device::device_reset()
1070{
1071   DEVICE_RESET_NAME( mc6854 )(this);
1072}
trunk/src/mess/machine/mc6854.h
r21684r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2006
4
5  Motorola 6854 emulation (network interface).
6
7**********************************************************************/
8
9#ifndef MC6854_H
10#define MC6854_H
11
12class mc6854_device : public device_t
13{
14public:
15   mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
16   ~mc6854_device() { global_free(m_token); }
17
18   // access to legacy token
19   void *token() const { assert(m_token != NULL); return m_token; }
20protected:
21   // device-level overrides
22   virtual void device_config_complete();
23   virtual void device_start();
24   virtual void device_reset();
25private:
26   // internal state
27   void *m_token;
28};
29
30extern const device_type MC6854;
31
32
33/* we provide two interfaces:
34   - a bit-based interface:   out_tx, set_rx
35   - a frame-based interface: out_frame, send_frame
36
37   The bit-based interface is low-level and slow.
38   Use it to simulate the actual bits sent into the wires, e.g., to connect
39   the emulator to another bit-based emulated network device, or an actual
40   device.
41
42   The frame-based interface is higher-level and faster.
43   It passes bytes directly from one end to the other without bothering with
44   the actual bit-encoding, synchronization, and CRC.
45   Once completed, a frame is sent through out_frame. Aborted frames are not
46   transmitted at all. No start flag, stop flag, or crc bits are trasmitted.
47   send_frame makes a frame available to the CPU through the 6854 (it may
48   fail and return -1 if the 6854 is not ready to accept the frame; even
49   if the frame is accepted and 0 is returned, the CPU may abort it). Ony
50   full frames are accepted.
51*/
52
53
54/* ---------- configuration ------------ */
55
56struct mc6854_interface
57{
58   devcb_write_line  out_irq_func; /* interrupt request */
59
60   /* low-level, bit-based interface */
61   devcb_read_line   in_rxd_func; /* receive bit */
62   devcb_write_line  out_txd_func; /* transmit bit */
63
64   /* high-level, frame-based interface */
65   void ( * out_frame ) ( device_t *device, UINT8* data, int length );
66
67   /* control lines */
68   devcb_write_line  out_rts_func; /* 1 = transmitting, 0 = idle */
69   devcb_write_line  out_dtr_func; /* 1 = data transmit ready, 0 = busy */
70};
71
72
73#define MCFG_MC6854_ADD(_tag, _intrf) \
74   MCFG_DEVICE_ADD(_tag, MC6854, 0)          \
75   MCFG_DEVICE_CONFIG(_intrf)
76
77#define MCFG_MC6854_REMOVE(_tag)        \
78   MCFG_DEVICE_REMOVE(_tag)
79
80
81/* ---------- functions ------------ */
82/* interface to CPU via address/data bus*/
83extern DECLARE_READ8_DEVICE_HANDLER  ( mc6854_r );
84extern DECLARE_WRITE8_DEVICE_HANDLER ( mc6854_w );
85
86/* low-level, bit-based interface */
87WRITE_LINE_DEVICE_HANDLER( mc6854_set_rx );
88
89/* high-level, frame-based interface */
90extern int mc6854_send_frame( device_t *device, UINT8* data, int length ); /* ret -1 if busy */
91
92/* control lines */
93WRITE_LINE_DEVICE_HANDLER( mc6854_set_cts ); /* 1 = clear-to-send, 0 = busy */
94WRITE_LINE_DEVICE_HANDLER( mc6854_set_dcd ); /* 1 = carrier, 0 = no carrier */
95
96/* clock */
97WRITE_LINE_DEVICE_HANDLER( mc6854_rxc_w );
98WRITE_LINE_DEVICE_HANDLER( mc6854_txc_w );
99
100#endif
trunk/src/mess/machine/mc6846.c
r21684r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2006
4
5  Motorola 6846 emulation.
6
7  The MC6846 chip provides ROM (2048 bytes), I/O (8-bit directional data port +
8  2 control lines) and a programmable timer.
9  It may be interfaced with a M6809 cpu.
10  It is used in some Thomson computers.
11
12  Not yet implemented:
13  - external clock (CTC)
14  - latching of port on CP1
15  - gate input (CTG)
16  - timer comparison modes (frequency and pulse width)
17  - CP2 acknowledge modes
18
19**********************************************************************/
20
21#include "emu.h"
22#include "mc6846.h"
23
24#define VERBOSE 0
25
26
27
28/******************* internal chip data structure ******************/
29
30
31struct mc6846_t
32{
33   const mc6846_interface* iface;
34
35   /* registers */
36   UINT8    csr;      /* 0,4: combination status register */
37   UINT8    pcr;      /* 1:   peripheral control register */
38   UINT8    ddr;      /* 2:   data direction register */
39   UINT8    pdr;      /* 3:   peripheral data register (last cpu write) */
40   UINT8    tcr;      /* 5:   timer control register */
41
42   /* lines */
43   UINT8 cp1;         /* 1-bit input */
44   UINT8 cp2;         /* 1-bit input/output: last external write */
45   UINT8 cp2_cpu;     /* last cpu write */
46   UINT8 cto;         /* 1-bit timer output (unmasked) */
47
48   /* internal state */
49   UINT8  time_MSB; /* MSB buffer register */
50   UINT8  csr0_to_be_cleared;
51   UINT8  csr1_to_be_cleared;
52   UINT8  csr2_to_be_cleared;
53   UINT16 latch;   /* timer latch */
54   UINT16 preset;  /* preset value */
55   UINT8  timer_started;
56
57   /* timers */
58   emu_timer *interval; /* interval programmable timer */
59   emu_timer *one_shot; /* 1-us x factor one-shot timer */
60
61   /* CPU write to the outside through chip */
62   devcb_resolved_write8 out_port;  /* 8-bit output */
63   devcb_resolved_write8 out_cp1;   /* 1-bit output */
64   devcb_resolved_write8 out_cp2;   /* 1-bit output */
65
66   /* CPU read from the outside through chip */
67   devcb_resolved_read8 in_port; /* 8-bit input */
68
69   /* asynchronous timer output to outside world */
70   devcb_resolved_write8 out_cto; /* 1-bit output */
71
72   /* timer interrupt */
73   devcb_resolved_write_line irq;
74
75   int old_cif;
76   int old_cto;
77};
78
79
80
81/******************* utility function and macros ********************/
82
83#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
84
85#define PORT                                \
86   ((mc6846->pdr & mc6846->ddr) |                  \
87      ((!mc6846->in_port.isnull() ? mc6846->in_port( 0 ) : 0) & \
88      ~mc6846->ddr))
89
90#define CTO                             \
91   ((MODE == 0x30 || (mc6846->tcr & 0x80)) ? mc6846->cto : 0)
92
93#define MODE (mc6846->tcr & 0x38)
94
95#define FACTOR ((mc6846->tcr & 4) ? 8 : 1)
96
97
98
99INLINE mc6846_t* get_safe_token( device_t *device )
100{
101   assert( device != NULL );
102   assert( device->type() == MC6846 );
103   return (mc6846_t*) downcast<mc6846_device *>(device)->token();
104}
105
106
107INLINE UINT16 mc6846_counter( device_t *device )
108{
109   mc6846_t* mc6846 = get_safe_token( device );
110   if ( mc6846->timer_started )
111   {
112      attotime delay = mc6846->interval ->remaining( );
113      return delay.as_ticks(1000000) / FACTOR;
114   }
115   else
116      return mc6846->preset;
117}
118
119
120
121INLINE void mc6846_update_irq( device_t *device )
122{
123   mc6846_t* mc6846 = get_safe_token( device );
124   int cif = 0;
125   /* composite interrupt flag */
126   if ( ( (mc6846->csr & 1) && (mc6846->tcr & 0x40) ) ||
127         ( (mc6846->csr & 2) && (mc6846->pcr & 1) ) ||
128         ( (mc6846->csr & 4) && (mc6846->pcr & 8) && ! (mc6846->pcr & 0x20) ) )
129      cif = 1;
130   if ( mc6846->old_cif != cif )
131   {
132      LOG (( "%f: mc6846 interrupt %i (time=%i cp1=%i cp2=%i)\n",
133            device->machine().time().as_double(), cif,
134            mc6846->csr & 1, (mc6846->csr >> 1 ) & 1, (mc6846->csr >> 2 ) & 1 ));
135      mc6846->old_cif = cif;
136   }
137   if ( cif )
138   {
139      mc6846->csr |= 0x80;
140      if ( !mc6846->irq.isnull() )
141         mc6846->irq( 1 );
142   }
143   else
144   {
145      mc6846->csr &= ~0x80;
146      if ( !mc6846->irq.isnull() )
147         mc6846->irq( 0 );
148   }
149}
150
151
152
153INLINE void mc6846_update_cto ( device_t *device )
154{
155   mc6846_t* mc6846 = get_safe_token( device );
156   int cto = CTO;
157   if ( cto != mc6846->old_cto )
158   {
159      LOG (( "%f: mc6846 CTO set to %i\n", device->machine().time().as_double(), cto ));
160      mc6846->old_cto = cto;
161   }
162   if ( !mc6846->out_cto.isnull() )
163      mc6846->out_cto( 0, cto );
164}
165
166
167
168INLINE void mc6846_timer_launch ( device_t *device )
169{
170   mc6846_t* mc6846 = get_safe_token( device );
171   int delay = FACTOR * (mc6846->preset+1);
172   LOG (( "%f: mc6846 timer launch called, mode=%i, preset=%i (x%i)\n", device->machine().time().as_double(), MODE, mc6846->preset, FACTOR ));
173
174   if ( ! (mc6846->tcr & 2) )
175   {
176      logerror( "mc6846 external clock CTC not implemented\n" );
177   }
178
179   switch( MODE )
180   {
181   case 0x00:
182   case 0x10: /* continuous */
183      mc6846->cto = 0;
184      break;
185
186   case 0x20: /* single-shot */
187      mc6846->cto = 0;
188      mc6846->one_shot->reset( attotime::from_usec(FACTOR) );
189      break;
190
191   case 0x30:  /* cascaded single-shot */
192      break;
193
194   default:
195      logerror( "mc6846 timer mode %i not implemented\n", MODE );
196      mc6846->interval->reset(  );
197      mc6846->timer_started = 0;
198      return;
199   }
200
201   mc6846->interval->reset( attotime::from_usec(delay) );
202   mc6846->timer_started = 1;
203
204   mc6846->csr &= ~1;
205   mc6846_update_cto( device );
206   mc6846_update_irq( device );
207}
208
209
210
211/******************* timer callbacks *********************************/
212
213static TIMER_CALLBACK( mc6846_timer_expire )
214{
215   device_t* device = (device_t*) ptr;
216   mc6846_t* mc6846 = get_safe_token( device );
217   int delay = FACTOR * (mc6846->latch+1);
218
219   LOG (( "%f: mc6846 timer expire called, mode=%i, latch=%i (x%i)\n", device->machine().time().as_double(), MODE, mc6846->latch, FACTOR ));
220
221   /* latch => counter */
222   mc6846->preset = mc6846->latch;
223
224   if ( ! (mc6846->tcr & 2) )
225      logerror( "mc6846 external clock CTC not implemented\n" );
226
227   switch ( MODE )
228   {
229   case 0x00:
230   case 0x10: /* continuous */
231      mc6846->cto = 1 ^ mc6846->cto;
232      break;
233
234   case 0x20: /* single-shot */
235      mc6846->cto = 0;
236      break;
237
238   case 0x30:  /* cascaded single-shot */
239      mc6846->cto = ( mc6846->tcr & 0x80 ) ? 1 : 0;
240      break;
241
242   default:
243      logerror( "mc6846 timer mode %i not implemented\n", MODE );
244      mc6846->interval->reset(  );
245      mc6846->timer_started = 0;
246      return;
247   }
248
249   mc6846->interval->reset( attotime::from_usec(delay) );
250
251   mc6846->csr |= 1;
252   mc6846_update_cto( device );
253   mc6846_update_irq( device );
254}
255
256
257
258static TIMER_CALLBACK( mc6846_timer_one_shot )
259{
260   device_t* device = (device_t*) ptr;
261   mc6846_t* mc6846 = get_safe_token( device );
262   LOG (( "%f: mc6846 timer one shot called\n", device->machine().time().as_double() ));
263
264   /* 1 micro second after one-shot launch, we put cto to high */
265   mc6846->cto = 1;
266   mc6846_update_cto( device );
267}
268
269
270
271/************************** CPU interface ****************************/
272
273
274READ8_DEVICE_HANDLER ( mc6846_r )
275{
276   mc6846_t* mc6846 = get_safe_token( device );
277   switch ( offset )
278   {
279   case 0:
280   case 4:
281      LOG (( "$%04x %f: mc6846 CSR read $%02X intr=%i (timer=%i, cp1=%i, cp2=%i)\n",
282            space.machine().firstcpu->pcbase( ), space.machine().time().as_double(),
283            mc6846->csr, (mc6846->csr >> 7) & 1,
284            mc6846->csr & 1, (mc6846->csr >> 1) & 1, (mc6846->csr >> 2) & 1 ));
285      mc6846->csr0_to_be_cleared = mc6846->csr & 1;
286      mc6846->csr1_to_be_cleared = mc6846->csr & 2;
287      mc6846->csr2_to_be_cleared = mc6846->csr & 4;
288      return mc6846->csr;
289
290   case 1:
291      LOG (( "$%04x %f: mc6846 PCR read $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846->pcr ));
292      return mc6846->pcr;
293
294   case 2:
295      LOG (( "$%04x %f: mc6846 DDR read $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846->ddr ));
296      return mc6846->ddr;
297
298   case 3:
299      LOG (( "$%04x %f: mc6846 PORT read $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), PORT ));
300      if ( ! (mc6846->pcr & 0x80) )
301      {
302         if ( mc6846->csr1_to_be_cleared )
303            mc6846->csr &= ~2;
304         if ( mc6846->csr2_to_be_cleared )
305            mc6846->csr &= ~4;
306         mc6846_update_irq( device );
307         mc6846->csr1_to_be_cleared = 0;
308         mc6846->csr2_to_be_cleared = 0;
309      }
310      return PORT;
311
312   case 5:
313      LOG (( "$%04x %f: mc6846 TCR read $%02X\n",space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846->tcr ));
314      return mc6846->tcr;
315
316   case 6:
317      LOG (( "$%04x %f: mc6846 COUNTER hi read $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846_counter( device ) >> 8 ));
318      if ( mc6846->csr0_to_be_cleared )
319      {
320         mc6846->csr &= ~1;
321         mc6846_update_irq( device );
322      }
323      mc6846->csr0_to_be_cleared = 0;
324      return mc6846_counter( device ) >> 8;
325
326   case 7:
327      LOG (( "$%04x %f: mc6846 COUNTER low read $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846_counter( device ) & 0xff ));
328      if ( mc6846->csr0_to_be_cleared )
329      {
330         mc6846->csr &= ~1;
331         mc6846_update_irq( device );
332      }
333      mc6846->csr0_to_be_cleared = 0;
334      return mc6846_counter( device ) & 0xff;
335
336   default:
337      logerror( "$%04x mc6846 invalid read offset %i\n", space.machine().firstcpu->pcbase( ), offset );
338   }
339   return 0;
340}
341
342
343
344WRITE8_DEVICE_HANDLER ( mc6846_w )
345{
346   mc6846_t* mc6846 = get_safe_token( device );
347   switch ( offset )
348   {
349   case 0:
350   case 4:
351      /* CSR is read-only */
352      break;
353
354   case 1:
355   {
356      static const char *const cp2[8] =
357      {
358         "in,neg-edge", "in,neg-edge,intr", "in,pos-edge", "in,pos-edge,intr",
359         "out,intr-ack", "out,i/o-ack", "out,0", "out,1"
360      };
361      static const char *const cp1[8] =
362      {
363         "neg-edge", "neg-edge,intr", "pos-edge", "pos-edge,intr",
364         "latched,neg-edge", "latched,neg-edge,intr",
365         "latcged,pos-edge", "latcged,pos-edge,intr"
366      };
367      LOG (( "$%04x %f: mc6846 PCR write $%02X reset=%i cp2=%s cp1=%s\n",
368            space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), data,
369            (data >> 7) & 1, cp2[ (data >> 3) & 7 ], cp1[ data & 7 ] ));
370
371   }
372   mc6846->pcr = data;
373   if ( data & 0x80 )
374   {      /* data reset */
375      mc6846->pdr = 0;
376      mc6846->ddr = 0;
377      mc6846->csr &= ~6;
378      mc6846_update_irq( device );
379   }
380   if ( data & 4 )
381      logerror( "$%04x mc6846 CP1 latching not implemented\n", space.machine().firstcpu->pcbase( ) );
382   if (data & 0x20)
383   {
384      if (data & 0x10)
385      {
386         mc6846->cp2_cpu = (data >> 3) & 1;
387         if ( !mc6846->out_cp2.isnull() )
388            mc6846->out_cp2( 0, mc6846->cp2_cpu );
389      }
390      else
391         logerror( "$%04x mc6846 acknowledge not implemented\n", space.machine().firstcpu->pcbase( ) );
392   }
393   break;
394
395   case 2:
396      LOG (( "$%04x %f: mc6846 DDR write $%02X\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), data ));
397      if ( ! (mc6846->pcr & 0x80) )
398      {
399         mc6846->ddr = data;
400         if ( !mc6846->out_port.isnull() )
401            mc6846->out_port( 0, mc6846->pdr & mc6846->ddr );
402      }
403      break;
404
405   case 3:
406      LOG (( "$%04x %f: mc6846 PORT write $%02X (mask=$%02X)\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), data,mc6846->ddr ));
407      if ( ! (mc6846->pcr & 0x80) )
408      {
409         mc6846->pdr = data;
410         if ( !mc6846->out_port.isnull() )
411            mc6846->out_port( 0, mc6846->pdr & mc6846->ddr );
412         if ( mc6846->csr1_to_be_cleared && (mc6846->csr & 2) )
413         {
414            mc6846->csr &= ~2;
415            LOG (( "$%04x %f: mc6846 CP1 intr reset\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double() ));
416         }
417         if ( mc6846->csr2_to_be_cleared && (mc6846->csr & 4) )
418         {
419            mc6846->csr &= ~4;
420            LOG (( "$%04x %f: mc6846 CP2 intr reset\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double() ));
421         }
422         mc6846->csr1_to_be_cleared = 0;
423         mc6846->csr2_to_be_cleared = 0;
424         mc6846_update_irq( device );
425      }
426      break;
427
428   case 5:
429   {
430      static const char *const mode[8] =
431         {
432            "continuous", "cascaded", "continuous", "one-shot",
433            "freq-cmp", "freq-cmp", "pulse-cmp", "pulse-cmp"
434         };
435      LOG (( "$%04x %f: mc6846 TCR write $%02X reset=%i clock=%s scale=%i mode=%s out=%s\n",
436            space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), data,
437            (data >> 7) & 1, (data & 0x40) ? "extern" : "sys",
438            (data & 0x40) ? 1 : 8, mode[ (data >> 1) & 7 ],
439            (data & 1) ? "enabled" : "0" ));
440
441      mc6846->tcr = data;
442      if ( mc6846->tcr & 1 )
443      {
444         /* timer preset = initialization without launch */
445         mc6846->preset = mc6846->latch;
446         mc6846->csr &= ~1;
447         if ( MODE != 0x30 )
448            mc6846->cto = 0;
449         mc6846_update_cto( device );
450         mc6846->interval->reset(  );
451         mc6846->one_shot->reset(  );
452         mc6846->timer_started = 0;
453      }
454      else
455      {
456         /* timer launch */
457         if ( ! mc6846->timer_started )
458            mc6846_timer_launch( device );
459      }
460      mc6846_update_irq( device );
461   }
462   break;
463
464   case 6:
465      mc6846->time_MSB = data;
466      break;
467
468   case 7:
469      mc6846->latch = ( ((UINT16) mc6846->time_MSB) << 8 ) + data;
470      LOG (( "$%04x %f: mc6846 COUNT write %i\n", space.machine().firstcpu->pcbase( ), space.machine().time().as_double(), mc6846->latch  ));
471      if (!(mc6846->tcr & 0x38))
472      {
473         /* timer initialization */
474         mc6846->preset = mc6846->latch;
475         mc6846->csr &= ~1;
476         mc6846_update_irq( device );
477         mc6846->cto = 0;
478         mc6846_update_cto( device );
479         /* launch only if started */
480         if (!(mc6846->tcr & 1))
481            mc6846_timer_launch( device );
482      }
483      break;
484
485   default:
486      logerror( "$%04x mc6846 invalid write offset %i\n", space.machine().firstcpu->pcbase( ), offset );
487   }
488}
489
490
491
492/******************** outside world interface ************************/
493
494
495
496void mc6846_set_input_cp1 ( device_t *device, int data )
497{
498   mc6846_t* mc6846 = get_safe_token( device );
499   data = (data != 0 );
500   if ( data == mc6846->cp1 )
501      return;
502   mc6846->cp1 = data;
503   LOG (( "%f: mc6846 input CP1 set to %i\n",  device->machine().time().as_double(), data ));
504   if (( data &&  (mc6846->pcr & 2)) || (!data && !(mc6846->pcr & 2)))
505   {
506      mc6846->csr |= 2;
507      mc6846_update_irq( device );
508   }
509}
510
511void mc6846_set_input_cp2 ( device_t *device, int data )
512{
513   mc6846_t* mc6846 = get_safe_token( device );
514   data = (data != 0 );
515   if ( data == mc6846->cp2 )
516      return;
517   mc6846->cp2 = data;
518   LOG (( "%f: mc6846 input CP2 set to %i\n", device->machine().time().as_double(), data ));
519   if (mc6846->pcr & 0x20)
520   {
521      if (( data &&  (mc6846->pcr & 0x10)) || (!data && !(mc6846->pcr & 0x10)))
522      {
523         mc6846->csr |= 4;
524         mc6846_update_irq( device );
525      }
526   }
527}
528
529
530
531/************************ accessors **********************************/
532
533
534
535UINT8 mc6846_get_output_port ( device_t *device )
536{
537   mc6846_t* mc6846 = get_safe_token( device );
538   return PORT;
539}
540
541
542
543UINT8 mc6846_get_output_cto ( device_t *device )
544{
545   mc6846_t* mc6846 = get_safe_token( device );
546   return CTO;
547}
548
549
550
551UINT8 mc6846_get_output_cp2 ( device_t *device )
552{
553   mc6846_t* mc6846 = get_safe_token( device );
554   return mc6846->cp2_cpu;
555}
556
557
558
559UINT16 mc6846_get_preset ( device_t *device )
560{
561   mc6846_t* mc6846 = get_safe_token( device );
562   return mc6846->preset;
563}
564
565
566
567/************************ reset *****************************/
568
569
570static DEVICE_RESET( mc6846 )
571{
572   mc6846_t* mc6846 = get_safe_token( device );
573   LOG (( "mc6846_reset\n" ));
574   mc6846->cto   = 0;
575   mc6846->csr   = 0;
576   mc6846->pcr   = 0x80;
577   mc6846->ddr   = 0;
578   mc6846->pdr   = 0;
579   mc6846->tcr   = 1;
580   mc6846->cp1   = 0;
581   mc6846->cp2   = 0;
582   mc6846->cp2_cpu  = 0;
583   mc6846->latch    = 0xffff;
584   mc6846->preset   = 0xffff;
585   mc6846->time_MSB = 0;
586   mc6846->csr0_to_be_cleared = 0;
587   mc6846->csr1_to_be_cleared = 0;
588   mc6846->csr2_to_be_cleared = 0;
589   mc6846->timer_started = 0;
590   mc6846->interval->reset(  );
591   mc6846->one_shot->reset(  );
592}
593
594
595/************************ start *****************************/
596
597static DEVICE_START( mc6846 )
598{
599   mc6846_t* mc6846 = get_safe_token( device );
600
601   mc6846->iface = (const mc6846_interface*)device->static_config();
602   mc6846->interval = device->machine().scheduler().timer_alloc(FUNC(mc6846_timer_expire), (void*) device );
603   mc6846->one_shot = device->machine().scheduler().timer_alloc(FUNC(mc6846_timer_one_shot), (void*) device );
604
605   mc6846->out_port.resolve(mc6846->iface->out_port_func, *device);  /* 8-bit output */
606   mc6846->out_cp1.resolve(mc6846->iface->out_cp1_func, *device);   /* 1-bit output */
607   mc6846->out_cp2.resolve(mc6846->iface->out_cp2_func, *device);   /* 1-bit output */
608
609   /* CPU read from the outside through chip */
610   mc6846->in_port.resolve(mc6846->iface->in_port_func, *device); /* 8-bit input */
611
612   /* asynchronous timer output to outside world */
613   mc6846->out_cto.resolve(mc6846->iface->out_cto_func, *device); /* 1-bit output */
614
615   /* timer interrupt */
616   mc6846->irq.resolve(mc6846->iface->irq_func, *device);
617
618   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->csr );
619   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->pcr );
620   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->ddr );
621   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->pdr );
622   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->tcr );
623   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->cp1 );
624   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->cp2 );
625   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->cp2_cpu );
626   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->cto );
627   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->time_MSB );
628   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->csr0_to_be_cleared );
629   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->csr1_to_be_cleared );
630   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->csr2_to_be_cleared );
631   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->latch );
632   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->preset );
633   state_save_register_item( device->machine(), "mc6846", device->tag(), 0, mc6846->timer_started );
634}
635
636
637const device_type MC6846 = &device_creator<mc6846_device>;
638
639mc6846_device::mc6846_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
640   : device_t(mconfig, MC6846, "Motorola MC6846 programmable timer", tag, owner, clock)
641{
642   m_token = global_alloc_clear(mc6846_t);
643}
644
645//-------------------------------------------------
646//  device_config_complete - perform any
647//  operations now that the configuration is
648//  complete
649//-------------------------------------------------
650
651void mc6846_device::device_config_complete()
652{
653}
654
655//-------------------------------------------------
656//  device_start - device-specific startup
657//-------------------------------------------------
658
659void mc6846_device::device_start()
660{
661   DEVICE_START_NAME( mc6846 )(this);
662}
663
664//-------------------------------------------------
665//  device_reset - device-specific reset
666//-------------------------------------------------
667
668void mc6846_device::device_reset()
669{
670   DEVICE_RESET_NAME( mc6846 )(this);
671}
trunk/src/mess/machine/mc6846.h
r21684r21685
1/**********************************************************************
2
3  Copyright (C) Antoine Mine' 2006
4
5  Motorola 6846 timer emulation.
6
7**********************************************************************/
8
9#ifndef MC6846_H
10#define MC6846_H
11
12class mc6846_device : public device_t
13{
14public:
15   mc6846_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
16   ~mc6846_device() { global_free(m_token); }
17
18   // access to legacy token
19   void *token() const { assert(m_token != NULL); return m_token; }
20protected:
21   // device-level overrides
22   virtual void device_config_complete();
23   virtual void device_start();
24   virtual void device_reset();
25private:
26   // internal state
27   void *m_token;
28};
29
30extern const device_type MC6846;
31
32
33/* ---------- configuration ------------ */
34
35struct mc6846_interface
36{
37   /* CPU write to the outside through chip */
38   devcb_write8 out_port_func;  /* 8-bit output */
39   devcb_write8 out_cp1_func;   /* 1-bit output */
40   devcb_write8 out_cp2_func;   /* 1-bit output */
41
42   /* CPU read from the outside through chip */
43   devcb_read8 in_port_func; /* 8-bit input */
44
45   /* asynchronous timer output to outside world */
46   devcb_write8 out_cto_func; /* 1-bit output */
47
48   /* timer interrupt */
49   devcb_write_line irq_func;
50};
51
52
53#define MCFG_MC6846_ADD(_tag, _intrf) \
54   MCFG_DEVICE_ADD(_tag, MC6846, 0)          \
55   MCFG_DEVICE_CONFIG(_intrf)
56
57#define MCFG_MC6846_MODIFY(_tag, _intrf) \
58   MCFG_DEVICE_MODIFY(_tag)          \
59   MCFG_DEVICE_CONFIG(_intrf)
60
61#define MCFG_MC6846_REMOVE(_tag)        \
62   MCFG_DEVICE_REMOVE(_tag)
63
64
65/* ---------- functions ------------ */
66/* interface to CPU via address/data bus*/
67extern DECLARE_READ8_DEVICE_HANDLER  ( mc6846_r );
68extern DECLARE_WRITE8_DEVICE_HANDLER ( mc6846_w );
69
70/* asynchronous write from outside world into interrupt-generating pins */
71extern void mc6846_set_input_cp1 ( device_t *device, int data );
72extern void mc6846_set_input_cp2 ( device_t *device, int data );
73
74/* polling from outside world */
75extern UINT8  mc6846_get_output_port ( device_t *device );
76extern UINT8  mc6846_get_output_cto  ( device_t *device );
77extern UINT8  mc6846_get_output_cp2  ( device_t *device );
78
79/* partial access to internal state */
80extern UINT16 mc6846_get_preset ( device_t *device ); /* timer interval - 1 in us */
81
82#endif
trunk/src/mess/machine/wd11c00_17.c
r21684r21685
1/**********************************************************************
2
3    Western Digital WD11C00-17 PC/XT Host Interface Logic Device
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10#include "machine/wd11c00_17.h"
11
12
13
14//**************************************************************************
15//  MACROS / CONSTANTS
16//**************************************************************************
17
18#define LOG 1
19
20
21// status register
22#define STATUS_IRQ      0x20
23#define STATUS_DRQ      0x10
24#define STATUS_BUSY     0x08
25#define STATUS_C_D      0x04
26#define STATUS_I_O      0x02
27#define STATUS_REQ      0x01
28
29
30// mask register
31#define MASK_IRQ        0x02
32#define MASK_DMA        0x01
33
34
35
36//**************************************************************************
37//  DEVICE DEFINITIONS
38//**************************************************************************
39
40const device_type WD11C00_17 = &device_creator<wd11c00_17_device>;
41
42
43//-------------------------------------------------
44//  device_config_complete - perform any
45//  operations now that the configuration is
46//  complete
47//-------------------------------------------------
48
49void wd11c00_17_device::device_config_complete()
50{
51   // inherit a copy of the static data
52   const wd11c00_17_interface *intf = reinterpret_cast<const wd11c00_17_interface *>(static_config());
53   if (intf != NULL)
54      *static_cast<wd11c00_17_interface *>(this) = *intf;
55
56   // or initialize to defaults if none provided
57   else
58   {
59      memset(&m_out_irq5_cb, 0, sizeof(m_out_irq5_cb));
60      memset(&m_out_drq3_cb, 0, sizeof(m_out_drq3_cb));
61      memset(&m_out_mr_cb, 0, sizeof(m_out_mr_cb));
62      memset(&m_out_busy_cb, 0, sizeof(m_out_busy_cb));
63      memset(&m_out_req_cb, 0, sizeof(m_out_req_cb));
64      memset(&m_out_ra3_cb, 0, sizeof(m_out_ra3_cb));
65      memset(&m_in_rd322_cb, 0, sizeof(m_in_rd322_cb));
66      memset(&m_in_ramcs_cb, 0, sizeof(m_in_ramcs_cb));
67      memset(&m_out_ramwr_cb, 0, sizeof(m_out_ramwr_cb));
68      memset(&m_in_cs1010_cb, 0, sizeof(m_in_cs1010_cb));
69      memset(&m_out_cs1010_cb, 0, sizeof(m_out_cs1010_cb));
70   }
71}
72
73
74
75//**************************************************************************
76//  INLINE HELPERS
77//**************************************************************************
78
79//-------------------------------------------------
80//  check_interrupt -
81//-------------------------------------------------
82
83inline void wd11c00_17_device::check_interrupt()
84{
85   if (BIT(m_ra, 10))
86   {
87      m_status &= ~STATUS_DRQ;
88   }
89
90   int ra3 = BIT(m_ra, 3);
91
92   if (m_ra3 != ra3)
93   {
94      m_out_ra3_func(ra3 ? ASSERT_LINE : CLEAR_LINE);
95      m_ra3 = ra3;
96   }
97
98   int irq5 = ((m_status & STATUS_IRQ) && (m_mask & MASK_IRQ)) ? ASSERT_LINE : CLEAR_LINE;
99
100   if (m_irq5 != irq5)
101   {
102      m_out_irq5_func(irq5);
103      m_irq5 = irq5;
104   }
105
106   int drq3 = ((m_status & STATUS_DRQ) && (m_mask & MASK_DMA)) ? ASSERT_LINE : CLEAR_LINE;
107
108   if (m_drq3 != drq3)
109   {
110      m_out_drq3_func(drq3);
111      m_drq3 = drq3;
112   }
113
114   int busy = (m_status & STATUS_BUSY) ? 0 : 1;
115
116   if (m_busy != busy)
117   {
118      m_out_busy_func(busy);
119      m_busy = busy;
120   }
121
122   int req = (m_status & STATUS_REQ) ? 1 : 0;
123
124   if (m_req != req)
125   {
126      m_out_req_func(req);
127      m_req = req;
128   }
129}
130
131
132//-------------------------------------------------
133//  increment_address -
134//-------------------------------------------------
135
136inline void wd11c00_17_device::increment_address()
137{
138   m_ra++;
139   check_interrupt();
140}
141
142
143//-------------------------------------------------
144//  read_data -
145//-------------------------------------------------
146
147inline UINT8 wd11c00_17_device::read_data()
148{
149   UINT8 data = 0;
150
151   if (m_status & STATUS_BUSY)
152   {
153      data = m_in_ramcs_func(m_ra & 0x7ff);
154
155      increment_address();
156   }
157
158   return data;
159}
160
161
162//-------------------------------------------------
163//  write_data -
164//-------------------------------------------------
165
166inline void wd11c00_17_device::write_data(UINT8 data)
167{
168   if (m_status & STATUS_BUSY)
169   {
170      m_out_ramwr_func(m_ra & 0x7ff, data);
171
172      increment_address();
173   }
174}
175
176
177//-------------------------------------------------
178//  software_reset -
179//-------------------------------------------------
180
181inline void wd11c00_17_device::software_reset()
182{
183   m_out_mr_func(ASSERT_LINE);
184   m_out_mr_func(CLEAR_LINE);
185
186   device_reset();
187}
188
189
190//-------------------------------------------------
191//  select -
192//-------------------------------------------------
193
194inline void wd11c00_17_device::select()
195{
196   m_status = STATUS_BUSY | STATUS_C_D | STATUS_REQ;
197
198   check_interrupt();
199}
200
201
202
203//**************************************************************************
204//  LIVE DEVICE
205//**************************************************************************
206
207//-------------------------------------------------
208//  wd11c00_17_device - constructor
209//-------------------------------------------------
210
211wd11c00_17_device::wd11c00_17_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
212   : device_t(mconfig, WD11C00_17, "Western Digital WD11C00-17", tag, owner, clock),
213      m_status(0),
214      m_ra(0),
215      m_irq5(CLEAR_LINE),
216      m_drq3(CLEAR_LINE),
217      m_busy(1),
218      m_req(0),
219      m_ra3(0)
220{
221}
222
223
224//-------------------------------------------------
225//  device_start - device-specific startup
226//-------------------------------------------------
227
228void wd11c00_17_device::device_start()
229{
230   // resolve callbacks
231   m_out_irq5_func.resolve(m_out_irq5_cb, *this);
232   m_out_drq3_func.resolve(m_out_drq3_cb, *this);
233   m_out_mr_func.resolve(m_out_mr_cb, *this);
234   m_out_busy_func.resolve(m_out_busy_cb, *this);
235   m_out_req_func.resolve(m_out_req_cb, *this);
236   m_out_ra3_func.resolve(m_out_ra3_cb, *this);
237   m_in_rd322_func.resolve(m_in_rd322_cb, *this);
238   m_in_ramcs_func.resolve(m_in_ramcs_cb, *this);
239   m_out_ramwr_func.resolve(m_out_ramwr_cb, *this);
240   m_in_cs1010_func.resolve(m_in_cs1010_cb, *this);
241   m_out_cs1010_func.resolve(m_out_cs1010_cb, *this);
242}
243
244
245//-------------------------------------------------
246//  device_reset - device-specific reset
247//-------------------------------------------------
248
249void wd11c00_17_device::device_reset()
250{
251   m_status &= ~(STATUS_IRQ | STATUS_DRQ | STATUS_BUSY);
252   m_mask = 0;
253   m_ra = 0;
254
255   check_interrupt();
256}
257
258
259//-------------------------------------------------
260//  io_r -
261//-------------------------------------------------
262
263READ8_MEMBER( wd11c00_17_device::io_r )
264{
265   UINT8 data = 0xff;
266
267   switch (offset)
268   {
269   case 0: // Read Data, Board to Host
270      if (LOG) logerror("%s WD11C00-17 '%s' Read Data %03x:", machine().describe_context(), tag(), m_ra);
271      data = read_data();
272      if (LOG) logerror("%02x\n", data);
273      break;
274
275   case 1: // Read Board Hardware Status
276      data = m_status;
277      check_interrupt();
278      break;
279
280   case 2: // Read Drive Configuration Information
281      data = m_in_rd322_func(0);
282      break;
283
284   case 3: // Not Used
285      break;
286   }
287
288   return data;
289}
290
291
292//-------------------------------------------------
293//  io_w -
294//-------------------------------------------------
295
296WRITE8_MEMBER( wd11c00_17_device::io_w )
297{
298   switch (offset)
299   {
300   case 0: // Write Data, Host to Board
301      if (LOG) logerror("%s WD11C00-17 '%s' Write Data %03x:%02x\n", machine().describe_context(), tag(), m_ra, data);
302      write_data(data);
303      break;
304
305   case 1: // Board Software Reset
306      if (LOG) logerror("%s WD11C00-17 '%s' Software Reset\n", machine().describe_context(), tag());
307      software_reset();
308      break;
309
310   case 2: // Board Select
311      if (LOG) logerror("%s WD11C00-17 '%s' Select\n", machine().describe_context(), tag());
312      increment_address(); // HACK
313      select();
314      break;
315
316   case 3: // Set/Reset DMA, IRQ Masks
317      if (LOG) logerror("%s WD11C00-17 '%s' Mask IRQ %u DMA %u\n", machine().describe_context(), tag(), BIT(data, 1), BIT(data, 0));
318      m_mask = data;
319      check_interrupt();
320      break;
321   }
322}
323
324
325//-------------------------------------------------
326//  dack_r -
327//-------------------------------------------------
328
329UINT8 wd11c00_17_device::dack_r()
330{
331   return read_data();
332}
333
334
335//-------------------------------------------------
336//  dack_w -
337//-------------------------------------------------
338
339void wd11c00_17_device::dack_w(UINT8 data)
340{
341   write_data(data);
342}
343
344
345//-------------------------------------------------
346//  read -
347//-------------------------------------------------
348
349READ8_MEMBER( wd11c00_17_device::read )
350{
351   UINT8 data = 0;
352
353   switch (offset)
354   {
355   case 0x00:
356      if (LOG) logerror("%s WD11C00-17 '%s' Read RAM %03x:", machine().describe_context(), tag(), m_ra);
357      data = read_data();
358      if (LOG) logerror("%02x\n", data);
359      break;
360
361   case 0x20:
362      data = m_in_cs1010_func(m_ra >> 8);
363      break;
364   }
365
366   return data;
367}
368
369
370//-------------------------------------------------
371//  write -
372//-------------------------------------------------
373
374WRITE8_MEMBER( wd11c00_17_device::write )
375{
376   switch (offset)
377   {
378   case 0x00:
379      if (LOG) logerror("%s WD11C00-17 '%s' Write RAM %03x:%02x\n", machine().describe_context(), tag(), m_ra, data);
380      write_data(data);
381      if (m_ra > 0x400) m_ecc_not_0 = 0; // HACK
382      break;
383
384   case 0x20:
385      m_out_cs1010_func(m_ra >> 8, data);
386      break;
387
388   case 0x60:
389      m_ra = (data & 0x07) << 8;
390      if (LOG) logerror("%s WD11C00-17 '%s' RA %03x\n", machine().describe_context(), tag(), m_ra);
391      check_interrupt();
392      break;
393   }
394}
395
396
397//-------------------------------------------------
398//  ireq_w -
399//-------------------------------------------------
400
401WRITE_LINE_MEMBER( wd11c00_17_device::ireq_w )
402{
403   if (LOG) logerror("%s WD11C00-17 '%s' IREQ %u\n", machine().describe_context(), tag(), state);
404
405   if (state) m_status |= STATUS_REQ; else m_status &= ~STATUS_REQ;
406
407   if (m_status & STATUS_BUSY)
408   {
409      if (state)
410      {
411         m_status |= STATUS_IRQ | STATUS_I_O;
412      }
413      else
414      {
415         if (m_status & STATUS_I_O)
416         {
417            m_status &= ~(STATUS_BUSY | STATUS_I_O);
418         }
419      }
420   }
421
422   check_interrupt();
423}
424
425
426//-------------------------------------------------
427//  io_w -
428//-------------------------------------------------
429
430WRITE_LINE_MEMBER( wd11c00_17_device::io_w )
431{
432   if (LOG) logerror("%s WD11C00-17 '%s' I/O %u\n", machine().describe_context(), tag(), state);
433
434   if (state) m_status |= STATUS_I_O; else m_status &= ~STATUS_I_O;
435}
436
437
438//-------------------------------------------------
439//  cd_w -
440//-------------------------------------------------
441
442WRITE_LINE_MEMBER( wd11c00_17_device::cd_w )
443{
444   if (LOG) logerror("%s WD11C00-17 '%s' C/D %u\n", machine().describe_context(), tag(), state);
445
446   if (state) m_status |= STATUS_C_D; else m_status &= ~STATUS_C_D;
447}
448
449
450//-------------------------------------------------
451//  clct_w -
452//-------------------------------------------------
453
454WRITE_LINE_MEMBER( wd11c00_17_device::clct_w )
455{
456   if (LOG) logerror("%s WD11C00-17 '%s' CLCT %u\n", machine().describe_context(), tag(), state);
457
458   if (state)
459   {
460      m_ra &= 0xff00;
461      check_interrupt();
462   }
463}
464
465
466//-------------------------------------------------
467//  mode_w -
468//-------------------------------------------------
469
470WRITE_LINE_MEMBER( wd11c00_17_device::mode_w )
471{
472   if (LOG) logerror("%s WD11C00-17 '%s' MODE %u\n", machine().describe_context(), tag(), state);
473
474   m_mode = state;
475   m_ecc_not_0 = state; // HACK
476}
477
478
479//-------------------------------------------------
480//  busy_r -
481//-------------------------------------------------
482
483READ_LINE_MEMBER( wd11c00_17_device::busy_r )
484{
485   return (m_status & STATUS_BUSY) ? 0 : 1;
486}
487
488
489//-------------------------------------------------
490//  ecc_not_0_r -
491//-------------------------------------------------
492
493READ_LINE_MEMBER( wd11c00_17_device::ecc_not_0_r )
494{
495   return m_ecc_not_0;
496}
trunk/src/mess/machine/wd11c00_17.h
r21684r21685
1/**********************************************************************
2
3    Western Digital WD11C00-17 PC/XT Host Interface Logic Device
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10#pragma once
11
12#ifndef __WD11C00_17__
13#define __WD11C00_17__
14
15
16#include "emu.h"
17
18
19
20//**************************************************************************
21//  INTERFACE CONFIGURATION MACROS
22//**************************************************************************
23
24#define MCFG_WD11C00_17_ADD(_tag, _clock, _config) \
25   MCFG_DEVICE_ADD(_tag, WD11C00_17, _clock) \
26   MCFG_DEVICE_CONFIG(_config)
27
28
29#define WD11C00_17_INTERFACE(_name) \
30   const wd11c00_17_interface (_name) =
31
32
33
34//**************************************************************************
35//  TYPE DEFINITIONS
36//**************************************************************************
37
38// ======================> wd11c00_17_interface
39
40struct wd11c00_17_interface
41{
42   devcb_write_line    m_out_irq5_cb;
43   devcb_write_line    m_out_drq3_cb;
44   devcb_write_line    m_out_mr_cb;
45   devcb_write_line    m_out_busy_cb;
46   devcb_write_line    m_out_req_cb;
47   devcb_write_line    m_out_ra3_cb;
48   devcb_read8         m_in_rd322_cb;
49   devcb_read8         m_in_ramcs_cb;
50   devcb_write8        m_out_ramwr_cb;
51   devcb_read8         m_in_cs1010_cb;
52   devcb_write8        m_out_cs1010_cb;
53};
54
55
56// ======================> wd11c00_17_device
57
58class wd11c00_17_device :   public device_t,
59                     public wd11c00_17_interface
60{
61public:
62   // construction/destruction
63   wd11c00_17_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
64
65   DECLARE_READ8_MEMBER( io_r );
66   DECLARE_WRITE8_MEMBER( io_w );
67
68   UINT8 dack_r();
69   void dack_w(UINT8 data);
70
71   DECLARE_READ8_MEMBER( read );
72   DECLARE_WRITE8_MEMBER( write );
73
74   DECLARE_WRITE_LINE_MEMBER( ireq_w );
75   DECLARE_WRITE_LINE_MEMBER( io_w );
76   DECLARE_WRITE_LINE_MEMBER( cd_w );
77   DECLARE_WRITE_LINE_MEMBER( clct_w );
78   DECLARE_WRITE_LINE_MEMBER( mode_w );
79
80   DECLARE_READ_LINE_MEMBER( busy_r );
81   DECLARE_READ_LINE_MEMBER( ecc_not_0_r );
82
83protected:
84   // device-level overrides
85   virtual void device_start();
86   virtual void device_reset();
87   virtual void device_config_complete();
88
89private:
90   inline void check_interrupt();
91   inline void increment_address();
92   inline UINT8 read_data();
93   inline void write_data(UINT8 data);
94   inline void software_reset();
95   inline void select();
96
97   devcb_resolved_write_line   m_out_irq5_func;
98   devcb_resolved_write_line   m_out_drq3_func;
99   devcb_resolved_write_line   m_out_mr_func;
100   devcb_resolved_write_line   m_out_busy_func;
101   devcb_resolved_write_line   m_out_req_func;
102   devcb_resolved_write_line   m_out_ra3_func;
103   devcb_resolved_read8        m_in_rd322_func;
104   devcb_resolved_read8        m_in_ramcs_func;
105   devcb_resolved_write8       m_out_ramwr_func;
106   devcb_resolved_read8        m_in_cs1010_func;
107   devcb_resolved_write8       m_out_cs1010_func;
108
109   UINT8 m_status;
110   UINT8 m_mask;
111
112   offs_t m_ra;
113
114   int m_mode;
115   int m_ecc_not_0;
116
117   int m_irq5;
118   int m_drq3;
119   int m_busy;
120   int m_req;
121   int m_ra3;
122};
123
124
125// device type definition
126extern const device_type WD11C00_17;
127
128#endif
trunk/src/mess/machine/wd2010.c
r21684r21685
1/**********************************************************************
2
3    Western Digital WD2010 Winchester Disk Controller
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10#include "machine/wd2010.h"
11
12
13
14//**************************************************************************
15//  MACROS / CONSTANTS
16//**************************************************************************
17
18#define LOG 1
19
20
21// task file
22enum
23{
24   TASK_FILE_ERROR = 1,
25   TASK_FILE_WRITE_PRECOMP_CYLINDER = TASK_FILE_ERROR,
26   TASK_FILE_SECTOR_COUNT,
27   TASK_FILE_SECTOR_NUMBER,
28   TASK_FILE_CYLINDER_LOW,
29   TASK_FILE_CYLINDER_HIGH,
30   TASK_FILE_SDH_REGISTER,
31   TASK_FILE_STATUS,
32   TASK_FILE_COMMAND = TASK_FILE_STATUS
33};
34
35#define WRITE_PRECOMP_CYLINDER \
36   (m_task_file[TASK_FILE_WRITE_PRECOMP_CYLINDER] * 4)
37
38#define SECTOR_COUNT \
39   ((m_task_file[TASK_FILE_SECTOR_COUNT] + 1) * 256)
40
41#define SECTOR_NUMBER \
42   (m_task_file[TASK_FILE_SECTOR_NUMBER])
43
44#define CYLINDER \
45   (((m_task_file[TASK_FILE_CYLINDER_HIGH] & 0x07) << 8) | m_task_file[TASK_FILE_CYLINDER_LOW])
46
47#define HEAD \
48   (m_task_file[TASK_FILE_SDH_REGISTER] & 0x07)
49
50#define DRIVE \
51   ((m_task_file[TASK_FILE_SDH_REGISTER] >> 3) & 0x03)
52
53static const int SECTOR_SIZES[4] = { 256, 512, 1024, 128 };
54
55#define SECTOR_SIZE \
56   SECTOR_SIZES[(m_task_file[TASK_FILE_SDH_REGISTER] >> 5) & 0x03]
57
58
59// status register
60#define STATUS_BSY      0x80
61#define STATUS_RDY      0x40
62#define STATUS_WF       0x20
63#define STATUS_SC       0x10
64#define STATUS_DRQ      0x08
65#define STATUS_DWC      0x04
66#define STATUS_CIP      0x02
67#define STATUS_ERR      0x01
68
69
70// error register
71#define ERROR_BB        0x80
72#define ERROR_CRC_ECC   0x40
73#define ERROR_ID        0x10
74#define ERROR_AC        0x04
75#define ERROR_TK        0x02
76#define ERROR_DM        0x01
77
78
79// command register
80#define COMMAND_MASK                0xf0
81#define COMMAND_RESTORE             0x10
82#define COMMAND_SEEK                0x70
83#define COMMAND_READ_SECTOR         0x20
84#define COMMAND_WRITE_SECTOR        0x30
85#define COMMAND_SCAN_ID             0x40
86#define COMMAND_WRITE_FORMAT        0x50
87#define COMMAND_COMPUTE_CORRECTION  0x08
88#define COMMAND_SET_PARAMETER_MASK  0xfe
89#define COMMAND_SET_PARAMETER       0x00
90
91
92
93//**************************************************************************
94//  DEVICE DEFINITIONS
95//**************************************************************************
96
97const device_type WD2010 = &device_creator<wd2010_device>;
98
99
100//-------------------------------------------------
101//  device_config_complete - perform any
102//  operations now that the configuration is
103//  complete
104//-------------------------------------------------
105
106void wd2010_device::device_config_complete()
107{
108   // inherit a copy of the static data
109   const wd2010_interface *intf = reinterpret_cast<const wd2010_interface *>(static_config());
110   if (intf != NULL)
111      *static_cast<wd2010_interface *>(this) = *intf;
112
113   // or initialize to defaults if none provided
114   else
115   {
116      memset(&m_out_intrq_cb, 0, sizeof(m_out_intrq_cb));
117      memset(&m_out_bdrq_cb, 0, sizeof(m_out_bdrq_cb));
118      memset(&m_out_bcr_cb, 0, sizeof(m_out_bcr_cb));
119      memset(&m_in_bcs_cb, 0, sizeof(m_in_bcs_cb));
120      memset(&m_out_bcs_cb, 0, sizeof(m_out_bcs_cb));
121      memset(&m_out_dirin_cb, 0, sizeof(m_out_dirin_cb));
122      memset(&m_out_step_cb, 0, sizeof(m_out_step_cb));
123      memset(&m_out_rwc_cb, 0, sizeof(m_out_rwc_cb));
124      memset(&m_in_drdy_cb, 0, sizeof(m_in_drdy_cb));
125      memset(&m_in_index_cb, 0, sizeof(m_in_index_cb));
126      memset(&m_in_wf_cb, 0, sizeof(m_in_wf_cb));
127      memset(&m_in_tk000_cb, 0, sizeof(m_in_tk000_cb));
128      memset(&m_in_sc_cb, 0, sizeof(m_in_sc_cb));
129   }
130}
131
132
133
134//**************************************************************************
135//  LIVE DEVICE
136//**************************************************************************
137
138//-------------------------------------------------
139//  wd2010_device - constructor
140//-------------------------------------------------
141
142wd2010_device::wd2010_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
143   : device_t(mconfig, WD2010, "Western Digital WD2010", tag, owner, clock),
144   m_status(0),
145   m_error(0)
146{
147}
148
149
150//-------------------------------------------------
151//  device_start - device-specific startup
152//-------------------------------------------------
153
154void wd2010_device::device_start()
155{
156   // resolve callbacks
157   m_out_intrq_func.resolve(m_out_intrq_cb, *this);
158   m_out_bdrq_func.resolve(m_out_bdrq_cb, *this);
159   m_out_bcr_func.resolve(m_out_bcr_cb, *this);
160   m_in_bcs_func.resolve(m_in_bcs_cb, *this);
161   m_out_bcs_func.resolve(m_out_bcs_cb, *this);
162   m_out_dirin_func.resolve(m_out_dirin_cb, *this);
163   m_out_step_func.resolve(m_out_step_cb, *this);
164   m_out_rwc_func.resolve(m_out_rwc_cb, *this);
165   m_in_drdy_func.resolve(m_in_drdy_cb, *this);
166   m_in_index_func.resolve(m_in_index_cb, *this);
167   m_in_wf_func.resolve(m_in_wf_cb, *this);
168   m_in_tk000_func.resolve(m_in_tk000_cb, *this);
169   m_in_sc_func.resolve(m_in_sc_cb, *this);
170}
171
172
173//-------------------------------------------------
174//  device_reset - device-specific reset
175//-------------------------------------------------
176
177void wd2010_device::device_reset()
178{
179}
180
181
182//-------------------------------------------------
183//  read -
184//-------------------------------------------------
185
186READ8_MEMBER( wd2010_device::read )
187{
188   UINT8 data = 0;
189
190   switch (offset)
191   {
192   case TASK_FILE_ERROR:
193      data = m_error;
194      break;
195
196   case TASK_FILE_STATUS:
197      m_out_intrq_func(CLEAR_LINE);
198      data = m_status | STATUS_RDY | STATUS_SC;
199      break;
200
201   default:
202      data = m_task_file[offset];
203      break;
204   }
205
206   return data;
207}
208
209
210//-------------------------------------------------
211//  write -
212//-------------------------------------------------
213
214WRITE8_MEMBER( wd2010_device::write )
215{
216   m_task_file[offset] = data;
217
218   switch (offset)
219   {
220   case TASK_FILE_WRITE_PRECOMP_CYLINDER:
221      if (LOG) logerror("%s WD2010 '%s' Write Precomp Cylinder: %u\n", machine().describe_context(), tag(), WRITE_PRECOMP_CYLINDER);
222      break;
223
224   case TASK_FILE_SECTOR_COUNT:
225      if (LOG) logerror("%s WD2010 '%s' Sector Count: %u\n", machine().describe_context(), tag(), SECTOR_COUNT);
226      break;
227
228   case TASK_FILE_SECTOR_NUMBER:
229      if (LOG) logerror("%s WD2010 '%s' Sector Number: %u\n", machine().describe_context(), tag(), SECTOR_NUMBER);
230      break;
231
232   case TASK_FILE_CYLINDER_LOW:
233      if (LOG) logerror("%s WD2010 '%s' Cylinder Low: %u\n", machine().describe_context(), tag(), CYLINDER);
234      break;
235
236   case TASK_FILE_CYLINDER_HIGH:
237      if (LOG) logerror("%s WD2010 '%s' Cylinder Low: %u\n", machine().describe_context(), tag(), CYLINDER);
238      break;
239
240   case TASK_FILE_SDH_REGISTER:
241      if (LOG)
242      {
243         logerror("%s WD2010 '%s' Head: %u\n", machine().describe_context(), tag(), HEAD);
244         logerror("%s WD2010 '%s' Drive: %u\n", machine().describe_context(), tag(), DRIVE);
245         logerror("%s WD2010 '%s' Sector Size: %u\n", machine().describe_context(), tag(), SECTOR_SIZE);
246      }
247      break;
248
249   case TASK_FILE_COMMAND:
250      if (data == COMMAND_COMPUTE_CORRECTION)
251      {
252         if (LOG) logerror("%s WD2010 '%s' COMPUTE CORRECTION\n", machine().describe_context(), tag());
253         compute_correction(data);
254      }
255      else if ((data & COMMAND_SET_PARAMETER_MASK) == COMMAND_SET_PARAMETER)
256      {
257         if (LOG) logerror("%s WD2010 '%s' SET PARAMETER\n", machine().describe_context(), tag());
258         set_parameter(data);
259      }
260      else
261      {
262         switch (data & COMMAND_MASK)
263         {
264         case COMMAND_RESTORE:
265            if (LOG) logerror("%s WD2010 '%s' RESTORE\n", machine().describe_context(), tag());
266            restore(data);
267            break;
268
269         case COMMAND_SEEK:
270            if (LOG) logerror("%s WD2010 '%s' SEEK\n", machine().describe_context(), tag());
271            seek(data);
272            break;
273
274         case COMMAND_READ_SECTOR:
275            if (LOG) logerror("%s WD2010 '%s' READ SECTOR\n", machine().describe_context(), tag());
276            read_sector(data);
277            break;
278
279         case COMMAND_WRITE_SECTOR:
280            if (LOG) logerror("%s WD2010 '%s' WRITE SECTOR\n", machine().describe_context(), tag());
281            write_sector(data);
282            break;
283
284         case COMMAND_SCAN_ID:
285            if (LOG) logerror("%s WD2010 '%s' SCAN ID\n", machine().describe_context(), tag());
286            scan_id(data);
287            break;
288
289         case COMMAND_WRITE_FORMAT:
290            if (LOG) logerror("%s WD2010 '%s' WRITE FORMAT\n", machine().describe_context(), tag());
291            format(data);
292            break;
293         }
294      }
295      break;
296   }
297}
298
299
300//-------------------------------------------------
301//  compute_correction -
302//-------------------------------------------------
303
304void wd2010_device::compute_correction(UINT8 data)
305{
306}
307
308
309//-------------------------------------------------
310//  set_parameter -
311//-------------------------------------------------
312
313void wd2010_device::set_parameter(UINT8 data)
314{
315}
316
317
318//-------------------------------------------------
319//  restore -
320//-------------------------------------------------
321
322void wd2010_device::restore(UINT8 data)
323{
324   // reset INTRQ, errors, set BUSY, CIP
325   m_out_intrq_func(CLEAR_LINE);
326   m_error = 0;
327   m_status = STATUS_BSY | STATUS_CIP;
328
329   // reset RWC, set direction=OUT, store step rate
330   m_out_rwc_func(0);
331   m_out_dirin_func(0);
332
333   int step_pulses = 0;
334
335   while (step_pulses < 2048)
336   {
337      while (!m_in_sc_func())
338      {
339         // drive not ready or write fault?
340         if (!m_in_drdy_func() || m_in_wf_func())
341         {
342            // pulse BCR, set AC, INTRQ, reset BSY, CIP
343            m_out_bcr_func(0);
344            m_out_bcr_func(1);
345            m_error = ERROR_AC;
346            m_status = (m_in_drdy_func() << 6) | (m_in_wf_func() << 5) | STATUS_ERR;
347            m_out_intrq_func(ASSERT_LINE);
348            return;
349         }
350      }
351
352      if (m_in_tk000_func())
353      {
354         // pulse BCR, set INTRQ, reset BSY, CIP
355         m_out_bcr_func(0);
356         m_out_bcr_func(1);
357         m_status &= ~(STATUS_BSY | STATUS_CIP);
358         m_out_intrq_func(ASSERT_LINE);
359         return;
360      }
361
362      if (step_pulses == 2047)
363      {
364         // set TK000 error
365         m_error = ERROR_TK;
366         m_status |= STATUS_ERR;
367
368         // pulse BCR, set INTRQ, reset BSY, CIP
369         m_out_bcr_func(0);
370         m_out_bcr_func(1);
371         m_status &= ~(STATUS_BSY | STATUS_CIP);
372         m_out_intrq_func(ASSERT_LINE);
373         return;
374      }
375
376      // issue a step pulse
377      m_out_step_func(1);
378      m_out_step_func(0);
379      step_pulses++;
380   }
381}
382
383
384//-------------------------------------------------
385//  seek -
386//-------------------------------------------------
387
388void wd2010_device::seek(UINT8 data)
389{
390}
391
392
393//-------------------------------------------------
394//  read_sector -
395//-------------------------------------------------
396
397void wd2010_device::read_sector(UINT8 data)
398{
399}
400
401
402//-------------------------------------------------
403//  write_sector -
404//-------------------------------------------------
405
406void wd2010_device::write_sector(UINT8 data)
407{
408}
409
410
411//-------------------------------------------------
412//  scan_id -
413//-------------------------------------------------
414
415void wd2010_device::scan_id(UINT8 data)
416{
417}
418
419
420//-------------------------------------------------
421//  format -
422//-------------------------------------------------
423
424void wd2010_device::format(UINT8 data)
425{
426}
trunk/src/mess/machine/wd2010.h
r21684r21685
1/**********************************************************************
2
3    Western Digital WD2010 Winchester Disk Controller
4
5    Copyright MESS Team.
6    Visit http://mamedev.org for licensing and usage restrictions.
7
8**********************************************************************/
9
10#pragma once
11
12#ifndef __WD2010__
13#define __WD2010__
14
15
16#include "emu.h"
17
18
19
20//**************************************************************************
21//  INTERFACE CONFIGURATION MACROS
22//**************************************************************************
23
24#define MCFG_WD2010_ADD(_tag, _clock, _config) \
25   MCFG_DEVICE_ADD(_tag, WD2010, _clock) \
26   MCFG_DEVICE_CONFIG(_config)
27
28
29#define WD2010_INTERFACE(_name) \
30   const wd2010_interface (_name) =
31
32
33
34//**************************************************************************
35//  TYPE DEFINITIONS
36//**************************************************************************
37
38// ======================> wd2010_interface
39
40struct wd2010_interface
41{
42   devcb_write_line    m_out_intrq_cb;
43   devcb_write_line    m_out_bdrq_cb;
44   devcb_write_line    m_out_bcr_cb;
45   devcb_read8         m_in_bcs_cb;
46   devcb_write8        m_out_bcs_cb;
47   devcb_write_line    m_out_dirin_cb;
48   devcb_write_line    m_out_step_cb;
49   devcb_write_line    m_out_rwc_cb;
50   devcb_read_line     m_in_drdy_cb;
51   devcb_read_line     m_in_index_cb;
52   devcb_read_line     m_in_wf_cb;
53   devcb_read_line     m_in_tk000_cb;
54   devcb_read_line     m_in_sc_cb;
55};
56
57
58// ======================> wd2010_device
59
60class wd2010_device :   public device_t,
61                  public wd2010_interface
62{
63public:
64   // construction/destruction
65   wd2010_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
66
67   DECLARE_READ8_MEMBER( read );
68   DECLARE_WRITE8_MEMBER( write );
69
70protected:
71   // device-level overrides
72   virtual void device_start();
73   virtual void device_reset();
74   virtual void device_config_complete();
75
76private:
77   void compute_correction(UINT8 data);
78   void set_parameter(UINT8 data);
79   void restore(UINT8 data);
80   void seek(UINT8 data);
81   void read_sector(UINT8 data);
82   void write_sector(UINT8 data);
83   void scan_id(UINT8 data);
84   void format(UINT8 data);
85
86   devcb_resolved_write_line   m_out_intrq_func;
87   devcb_resolved_write_line   m_out_bdrq_func;
88   devcb_resolved_write_line   m_out_bcr_func;
89   devcb_resolved_read8        m_in_bcs_func;
90   devcb_resolved_write8       m_out_bcs_func;
91   devcb_resolved_write_line   m_out_dirin_func;
92   devcb_resolved_write_line   m_out_step_func;
93   devcb_resolved_write_line   m_out_rwc_func;
94   devcb_resolved_read_line    m_in_drdy_func;
95   devcb_resolved_read_line    m_in_index_func;
96   devcb_resolved_read_line    m_in_wf_func;
97   devcb_resolved_read_line    m_in_tk000_func;
98   devcb_resolved_read_line    m_in_sc_func;
99
100   UINT8 m_status;
101   UINT8 m_error;
102   UINT8 m_task_file[8];
103};
104
105
106// device type definition
107extern const device_type WD2010;
108
109#endif
trunk/src/mess/machine/c65.c
r21684r21685
99
1010#include "includes/cbm.h"
1111#include "includes/c65.h"
12#include "includes/c64_legacy.h"
1312#include "cpu/m6502/m4510.h"
1413#include "sound/mos6581.h"
1514#include "machine/6526cia.h"
r21684r21685
994993DRIVER_INIT_MEMBER(c65_state,c65)
995994{
996995   m_dma.version = 2;
997   c64_legacy_driver_init();
998996   c65_common_driver_init(machine());
999997}
1000998
1001999DRIVER_INIT_MEMBER(c65_state,c65pal)
10021000{
10031001   m_dma.version = 1;
1004   c64_legacy_driver_init();
10051002   c65_common_driver_init(machine());
10061003   m_pal = 1;
10071004}

Previous 199869 Revisions Next


© 1997-2024 The MAME Team