summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/roc10937.cpp
blob: e50c0a487104aff7ab767a47cad85b54307837f6 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                  






                                                                       
                

                     


                    

















                                                    
                                                        
                                                               
                                                                        

  
                                        
                                  






















































                                                          
                                         


                                         
                                                 
                                        
                                                 
                                         


                                         

  
 
                                                                           



















                                  
                                                                                                                                 


                                                   
 

 
 
                                  
 


                                                                                                    
                                      



                                       
                                 

                                      

                                
                                
                                
 
 
                                  
 
                         






                           
                   

                   
 

                                                                   


                                                                           
                                                   
 
                                                                                                                         
 


                                                                           
                                      
 
                         
 
 
                                    
 
                                                                                                    

 
                                        

                           

 
                                        
 


                       
                                       
 





                                                                                           
 
 
                                          

                            
         















                                                         
         
                       


                                                                           







                                                                                                                   
 

 

                                                                                                               
 
 
 

                                                                                                                 
 

 

                                                                                                               
 

 
                                        









                                                                   
 









                                                              
                 


                         
                     












                                                                             
 






                                                                 
         

 

                                                                                                                 
 
 
 
                                          
 


                                                         
                                                      
                                                                   


                                                              
                                     
 

                                                              


                                                              
                                                     


                                                             

                                                         


                 

                                                                                



                                       

                                                             

                                     
                                                             

                                       
                                                             

                                     
                         
                                                           


                                 

                                                                             
 

                                                                 
                         
                                                 


                         

         
// license:BSD-3-Clause
// copyright-holders:James Wallace
/**********************************************************************

    Rockwell 10937/10957 interface and emulation by J.Wallace
    OKI MSC1937 is a clone of this chip

**********************************************************************/

#include "emu.h"
#include "roc10937.h"

#include <algorithm>


/*
   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_t 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 -
			//                     /.
	0x2230, // 0010 0010 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
};

rocvfd_device::rocvfd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, type, tag, owner, clock),
	m_outputs(),
	m_port_val(0)
{
}


void rocvfd_device::device_start()
{
	m_outputs = std::make_unique<output_finder<16> >(*this, "vfd%u", unsigned(m_port_val * 16));
	m_outputs->resolve();

	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_brightness));
	save_item(NAME(m_count));
	save_item(NAME(m_sclk));
	save_item(NAME(m_data));
	save_item(NAME(m_duty));
	save_item(NAME(m_disp));
}

void rocvfd_device::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;
	m_sclk = 0;
	m_data = 0;

	std::fill(std::begin(m_chars), std::end(m_chars), 0);
	std::fill(std::begin(*m_outputs), std::end(*m_outputs), 0);
}

///////////////////////////////////////////////////////////////////////////
uint32_t rocvfd_device::set_display(uint32_t segin)
{
	return bitswap<32>(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_device::device_post_load()
{
	update_display();
}

void rocvfd_device::update_display()
{
	std::transform(std::begin(m_chars), std::end(m_chars), std::begin(*m_outputs), set_display);
}

WRITE_LINE_MEMBER( rocvfd_device::sclk )
{
	shift_clock(state);
}

WRITE_LINE_MEMBER( rocvfd_device::data )
{
	m_data = state;
}

WRITE_LINE_MEMBER( rocvfd_device::por )
{
	//If line goes low, reset mode is engaged, until such a time as it goes high again.
	if (!state)
	{
		reset();
	}
}


void rocvfd_device::shift_clock(int state)
{
	if (m_sclk != state)
	{
		//Clock data on FALLING edge
		if (!m_sclk)
		{
			m_shift_data <<= 1;

			if ( m_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();

		}
	}
	m_sclk = state;
}

///////////////////////////////////////////////////////////////////////////
DEFINE_DEVICE_TYPE(ROC10937, roc10937_device, "roc10937", "Rockwell 10937 VFD controller") // and compatible
DEFINE_DEVICE_TYPE(MSC1937,  msc1937_device,  "msc1937",  "OKI MSC1937 VFD controller")
DEFINE_DEVICE_TYPE(MIC10937, mic10937_device, "mic10937", "Micrel MIC10937 VFD controller")
DEFINE_DEVICE_TYPE(ROC10957, roc10957_device, "roc10957", "Rockwell 10957 VFD controller") // and compatible
DEFINE_DEVICE_TYPE(S16LF01,  s16lf01_device,  "s16lf01",  "Samsung 16LF01 Series VFD controller") // and compatible

roc10937_device::roc10937_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: rocvfd_device(mconfig, ROC10937, tag, owner, clock)
{
}

msc1937_device::msc1937_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: rocvfd_device(mconfig, MSC1937, tag, owner, clock)
{
}

mic10937_device::mic10937_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: rocvfd_device(mconfig, MIC10937, tag, owner, clock)
{
}

s16lf01_device::s16lf01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: rocvfd_device(mconfig, S16LF01, tag, owner, clock)
{
}

void rocvfd_device::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;
		}
	}
}

roc10957_device::roc10957_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: rocvfd_device(mconfig, ROC10957, tag, owner, clock)
{
}

void roc10957_device::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.  Bit 6 is a "don't care" bit except for PNT and TAIL.
		data &= 0x7F;

		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;
		}
	}
}