mirror of
https://github.com/holub/mame
synced 2025-06-05 12:26:35 +03:00
366 lines
8.8 KiB
C
366 lines
8.8 KiB
C
/**********************************************************************
|
|
|
|
Rockwell 10937/10957 interface and emulation by J.Wallace
|
|
OKI MSC1937 is a clone of this chip
|
|
|
|
**********************************************************************/
|
|
|
|
#include "emu.h"
|
|
#include "roc10937.h"
|
|
|
|
/*
|
|
Rockwell 10937 16 segment charset lookup table
|
|
0 1
|
|
---- ----
|
|
|\ | /|
|
|
7 | \F |8 /9| 2
|
|
| \ | / |
|
|
-E-- --A-
|
|
| / | \ |
|
|
6 | /D |C \B| 3
|
|
|/ | \|
|
|
---- ---- .11
|
|
5 4 ,10
|
|
|
|
In 14 segment mode, 0 represents the whole top line,
|
|
and 5 the bottom line, allowing both modes to share
|
|
a charset.
|
|
|
|
Note that, although we call this a '16 segment' display,
|
|
we actually have 18 segments, including the semicolon portions.
|
|
16-bit tables are used to hold the main characters, the rest are OR'd in
|
|
*/
|
|
|
|
static const UINT16 roc10937charset[]=
|
|
{ // FEDC BA98 7654 3210
|
|
0x507F, // 0101 0000 0111 1111 @.
|
|
0x44CF, // 0100 0100 1100 1111 A.
|
|
0x153F, // 0001 0101 0011 1111 B.
|
|
0x00F3, // 0000 0000 1111 0011 C.
|
|
0x113F, // 0001 0001 0011 1111 D.
|
|
0x40F3, // 0100 0000 1111 0011 E.
|
|
0x40C3, // 0100 0000 1100 0011 F.
|
|
0x04FB, // 0000 0100 1111 1011 G.
|
|
0x44CC, // 0100 0100 1100 1100 H.
|
|
0x1133, // 0001 0001 0011 0011 I.
|
|
0x007C, // 0000 0000 0111 1100 J.
|
|
0x4AC0, // 0100 1010 1100 0000 K.
|
|
0x00F0, // 0000 0000 1111 0000 L.
|
|
0x82CC, // 1000 0010 1100 1100 M.
|
|
0x88CC, // 1000 1000 1100 1100 N.
|
|
0x00FF, // 0000 0000 1111 1111 O.
|
|
0x44C7, // 0100 0100 1100 0111 P.
|
|
0x08FF, // 0000 1000 1111 1111 Q.
|
|
0x4CC7, // 0100 1100 1100 0111 R.
|
|
0x44BB, // 0100 0100 1011 1011 S.
|
|
0x1103, // 0001 0001 0000 0011 T.
|
|
0x00FC, // 0000 0000 1111 1100 U.
|
|
0x22C0, // 0010 0010 1100 0000 V.
|
|
0x28CC, // 0010 1000 1100 1100 W.
|
|
0xAA00, // 1010 1010 0000 0000 X.
|
|
0x9200, // 1001 0010 0000 0000 Y.
|
|
0x2233, // 0010 0010 0011 0011 Z.
|
|
0x00E1, // 0000 0000 1110 0001 [.
|
|
0x8800, // 1000 1000 0000 0000 \.
|
|
0x001E, // 0000 0000 0001 1110 ].
|
|
0x2800, // 0010 1000 0000 0000 ^.
|
|
0x0030, // 0000 0000 0011 0000 _.
|
|
0x0000, // 0000 0000 0000 0000 dummy.
|
|
0x8121, // 1000 0001 0010 0001 !.
|
|
0x0180, // 0000 0001 1000 0000 ".
|
|
0x553C, // 0101 0101 0011 1100 #.
|
|
0x55BB, // 0101 0101 1011 1011 $.
|
|
0x7799, // 0111 0111 1001 1001 %.
|
|
0xC979, // 1100 1001 0111 1001 &.
|
|
0x0200, // 0000 0010 0000 0000 '.
|
|
0x0A00, // 0000 1010 0000 0000 (.
|
|
0xA050, // 1010 0000 0000 0000 ).
|
|
0xFF00, // 1111 1111 0000 0000 *.
|
|
0x5500, // 0101 0101 0000 0000 +.
|
|
0x0000, // 0000 0000 0000 0000 ;. (Set separately)
|
|
0x4400, // 0100 0100 0000 0000 --.
|
|
0x0000, // 0000 0000 0000 0000 . .(Set separately)
|
|
0x2200, // 0010 0010 0000 0000 /.
|
|
0x22FF, // 0010 0010 1111 1111 0.
|
|
0x1100, // 0001 0001 0000 0000 1.
|
|
0x4477, // 0100 0100 0111 0111 2.
|
|
0x443F, // 0100 0100 0011 1111 3.
|
|
0x448C, // 0100 0100 1000 1100 4.
|
|
0x44BB, // 0100 0100 1011 1011 5.
|
|
0x44FB, // 0100 0100 1111 1011 6.
|
|
0x000F, // 0000 0000 0000 1111 7.
|
|
0x44FF, // 0100 0100 1111 1111 8.
|
|
0x44BF, // 0100 0100 1011 1111 9.
|
|
0x0021, // 0000 0000 0010 0001 -
|
|
// -.
|
|
0x2001, // 0010 0000 0000 0001 -
|
|
// /.
|
|
0x2430, // 0010 0100 0011 0000 <.
|
|
0x4430, // 0100 0100 0011 0000 =.
|
|
0x8830, // 1000 1000 0011 0000 >.
|
|
0x1407, // 0001 0100 0000 0111 ?.
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static const int roc10937poslut[]=
|
|
{
|
|
1,//0
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
8,
|
|
9,
|
|
10,
|
|
11,
|
|
12,
|
|
13,
|
|
14,
|
|
15,
|
|
0//15
|
|
};
|
|
|
|
const device_type ROC10937 = &device_creator<roc10937_t>;
|
|
|
|
rocvfd_t::rocvfd_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
|
|
device_t(mconfig, type, name, tag, owner, clock, shortname, source)
|
|
{
|
|
m_port_val=0;
|
|
m_reversed=0;
|
|
}
|
|
|
|
|
|
void rocvfd_t::static_set_value(device_t &device, int val)
|
|
{
|
|
rocvfd_t &roc = downcast<rocvfd_t &>(device);
|
|
roc.m_port_val = val;
|
|
}
|
|
|
|
void rocvfd_t::static_set_zero(device_t &device, bool reversed)
|
|
{
|
|
rocvfd_t &roc = downcast<rocvfd_t &>(device);
|
|
roc.m_reversed = reversed;
|
|
}
|
|
|
|
void rocvfd_t::device_start()
|
|
{
|
|
save_item(NAME(m_port_val));
|
|
save_item(NAME(m_reversed));
|
|
save_item(NAME(m_cursor_pos));
|
|
save_item(NAME(m_window_size));
|
|
save_item(NAME(m_shift_count));
|
|
save_item(NAME(m_shift_data));
|
|
save_item(NAME(m_pcursor_pos));
|
|
save_item(NAME(m_chars));
|
|
save_item(NAME(m_outputs));
|
|
save_item(NAME(m_brightness));
|
|
save_item(NAME(m_count));
|
|
save_item(NAME(m_duty));
|
|
save_item(NAME(m_disp));
|
|
|
|
|
|
device_reset();
|
|
}
|
|
|
|
void rocvfd_t::device_reset()
|
|
{
|
|
m_cursor_pos = 0;
|
|
m_window_size = 16;
|
|
m_shift_count = 0;
|
|
m_shift_data = 0;
|
|
m_pcursor_pos = 0;
|
|
m_brightness =31;
|
|
m_count=0;
|
|
m_duty=31;
|
|
m_disp = 0;
|
|
|
|
memset(m_chars, 0, sizeof(m_chars));
|
|
memset(m_outputs, 0, sizeof(m_outputs));
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
UINT32 rocvfd_t::set_display(UINT32 segin)
|
|
{
|
|
return BITSWAP32(segin, 31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,11,9,15,13,12,8,10,14,7,6,5,4,3,2,1,0);
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void rocvfd_t::device_post_load()
|
|
{
|
|
for (int i =0; i<16; i++)
|
|
{
|
|
output_set_indexed_value("vfd", (m_port_val*16) + i, m_outputs[i]);
|
|
}
|
|
}
|
|
|
|
void rocvfd_t::update_display()
|
|
{
|
|
for (int i =0; i<16; i++)
|
|
{
|
|
if (m_reversed)
|
|
{
|
|
m_outputs[i] = set_display(m_chars[15-i]);
|
|
}
|
|
else
|
|
{
|
|
m_outputs[i] = set_display(m_chars[i]);
|
|
}
|
|
output_set_indexed_value("vfd", (m_port_val*16) + i, m_outputs[i]);
|
|
}
|
|
}
|
|
|
|
void rocvfd_t::shift_data(int data)
|
|
{
|
|
m_shift_data <<= 1;
|
|
|
|
if ( !data ) m_shift_data |= 1;
|
|
|
|
if ( ++m_shift_count >= 8 )
|
|
{
|
|
write_char(m_shift_data);
|
|
m_shift_count = 0;
|
|
m_shift_data = 0;
|
|
}
|
|
update_display();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
roc10937_t::roc10937_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
|
: rocvfd_t(mconfig, ROC10937, "Rockwell 10937 VFD controller and compatible", tag, owner, clock, "roc10937", __FILE__)
|
|
{
|
|
m_port_val=0;
|
|
m_reversed=0;
|
|
}
|
|
|
|
const device_type MSC1937 = &device_creator<msc1937_t>;
|
|
|
|
msc1937_t::msc1937_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
|
: rocvfd_t(mconfig, MSC1937, "OKI MSC1937 VFD controller", tag, owner, clock, "msc1937", __FILE__)
|
|
{
|
|
m_port_val=0;
|
|
m_reversed=0;
|
|
}
|
|
|
|
void rocvfd_t::write_char(int data)
|
|
{
|
|
if ( data & 0x80 )
|
|
{ // Control data received
|
|
if ( (data & 0xF0) == 0xA0 ) // 1010 xxxx
|
|
{ // 1 010 xxxx Buffer Pointer control
|
|
m_cursor_pos = roc10937poslut[data & 0x0F];
|
|
}
|
|
else if ( (data & 0xF0) == 0xC0 ) // 1100 xxxx
|
|
{ // 1100 xxxx Set number of digits
|
|
data &= 0x0F;
|
|
|
|
if ( data == 0 ) m_window_size = 16;
|
|
else m_window_size = data;
|
|
}
|
|
else if ( (data & 0xE0) == 0xE0 ) // 111x xxxx
|
|
{ // 111x xxxx Set duty cycle ( brightness )
|
|
m_brightness = (data & 0x1F);
|
|
}
|
|
else if ( (data & 0xE0) == 0x80 ) // 100x ---
|
|
{ // 100x xxxx Test mode
|
|
m_duty =4;
|
|
}
|
|
}
|
|
else
|
|
{ // Display data
|
|
// data &= 0x3F;
|
|
|
|
switch ( data )
|
|
{
|
|
case 0x2C: // ;
|
|
m_chars[m_pcursor_pos] |= (1<<16);//.
|
|
m_chars[m_pcursor_pos] |= (1<<17);//,
|
|
break;
|
|
case 0x2E: //
|
|
m_chars[m_pcursor_pos] |= (1<<16);//.
|
|
break;
|
|
default :
|
|
m_pcursor_pos = m_cursor_pos;
|
|
m_chars[m_cursor_pos] = roc10937charset[data & 0x3F];
|
|
|
|
m_cursor_pos++;
|
|
if ( m_cursor_pos > (m_window_size -1) )
|
|
{
|
|
m_cursor_pos = 0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
const device_type ROC10957 = &device_creator<roc10957_t>;
|
|
|
|
roc10957_t::roc10957_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
|
: rocvfd_t(mconfig, ROC10957, "Rockwell 10957 VFD controller and compatible", tag, owner, clock, "roc10957", __FILE__)
|
|
{
|
|
m_port_val=0;
|
|
m_reversed=0;
|
|
}
|
|
|
|
void roc10957_t::write_char(int data)
|
|
{
|
|
if ( data & 0x80 )
|
|
{ // Control data received
|
|
if ( (data & 0xF0) == 0xA0 ) // 1010 xxxx
|
|
{ // 1 010 xxxx Buffer Pointer control
|
|
m_cursor_pos = roc10937poslut[data & 0x0F];
|
|
}
|
|
else if ( (data & 0xF0) == 0xC0 ) // 1100 xxxx
|
|
{ // 1100 xxxx Set number of digits
|
|
data &= 0x0F;
|
|
|
|
if ( data == 0 ) m_window_size = 16;
|
|
else m_window_size = data;
|
|
}
|
|
else if ( (data & 0xE0) == 0xE0 ) // 111x xxxx
|
|
{ // 111x xxxx Set duty cycle ( brightness )
|
|
m_brightness = (data & 0x1F);
|
|
}
|
|
else if ( (data & 0xE0) == 0x80 ) // 100x ---
|
|
{ // 100x xxxx Test mode
|
|
popmessage("TEST MODE ENABLED!");
|
|
m_duty = 4;
|
|
}
|
|
}
|
|
else
|
|
{ // Display data
|
|
data &= 0x3F;
|
|
|
|
switch ( data )
|
|
{
|
|
case 0x2C: // ;
|
|
m_chars[m_pcursor_pos] |= (1<<16);//.
|
|
m_chars[m_pcursor_pos] |= (1<<17);//,
|
|
break;
|
|
case 0x2E: //
|
|
m_chars[m_pcursor_pos] |= (1<<16);//.
|
|
break;
|
|
case 0x6C: // ;
|
|
m_chars[m_pcursor_pos] |= (1<<16);//.
|
|
break;
|
|
case 0x6E: //
|
|
{
|
|
m_chars[m_pcursor_pos] = 0;
|
|
}
|
|
break;
|
|
default :
|
|
m_pcursor_pos = m_cursor_pos;
|
|
m_chars[m_cursor_pos] = roc10937charset[data & 0x3F];
|
|
|
|
m_cursor_pos++;
|
|
if ( m_cursor_pos > (m_window_size -1) )
|
|
{
|
|
m_cursor_pos = 0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|