1 // license:BSD-3-Clause
2 // copyright-holders:hap
3 /*
4 
5 Hughes HLCD 0538(A)/0539(A) LCD Driver
6 
7 0538: 8 rows, 26 columns
8 0539: 0 rows, 34 columns
9 
10 "LCD" pin can be used in 2 modes, either direct drive, or as an oscillator.
11 In latter case, output frequency is approximately 1/RC.
12 
13 TODO:
14 - the only difference between 0538/0539 is row pins voltage levels?
15 
16 */
17 
18 #include "emu.h"
19 #include "video/hlcd0538.h"
20 
21 
22 DEFINE_DEVICE_TYPE(HLCD0538, hlcd0538_device, "hlcd0538", "Hughes HLCD 0538 LCD Driver")
23 DEFINE_DEVICE_TYPE(HLCD0539, hlcd0539_device, "hlcd0539", "Hughes HLCD 0539 LCD Driver")
24 
25 //-------------------------------------------------
26 //  constructor
27 //-------------------------------------------------
28 
hlcd0538_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,u32 clock)29 hlcd0538_device::hlcd0538_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
30 	device_t(mconfig, type, tag, owner, clock),
31 	m_write_cols(*this), m_write_interrupt(*this)
32 { }
33 
hlcd0538_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)34 hlcd0538_device::hlcd0538_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
35 	hlcd0538_device(mconfig, HLCD0538, tag, owner, clock)
36 { }
37 
hlcd0539_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)38 hlcd0539_device::hlcd0539_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
39 	hlcd0538_device(mconfig, HLCD0539, tag, owner, clock)
40 { }
41 
42 
43 //-------------------------------------------------
44 //  device_start - device-specific startup
45 //-------------------------------------------------
46 
device_start()47 void hlcd0538_device::device_start()
48 {
49 	// resolve callbacks
50 	m_write_cols.resolve_safe();
51 	m_write_interrupt.resolve_safe();
52 
53 	// timer (when LCD pin is oscillator)
54 	m_lcd_timer = timer_alloc();
55 	attotime period = (clock() != 0) ? attotime::from_hz(2 * clock()) : attotime::never;
56 	m_lcd_timer->adjust(period, 0, period);
57 
58 	// register for savestates
59 	save_item(NAME(m_lcd));
60 	save_item(NAME(m_clk));
61 	save_item(NAME(m_data));
62 	save_item(NAME(m_shift));
63 }
64 
65 
66 //-------------------------------------------------
67 //  handlers
68 //-------------------------------------------------
69 
WRITE_LINE_MEMBER(hlcd0538_device::clk_w)70 WRITE_LINE_MEMBER(hlcd0538_device::clk_w)
71 {
72 	state = (state) ? 1 : 0;
73 
74 	// clock in data on falling edge
75 	if (!state && m_clk)
76 		m_shift = (m_shift << 1 | m_data) & u64(0x3ffffffff);
77 
78 	m_clk = state;
79 }
80 
WRITE_LINE_MEMBER(hlcd0538_device::lcd_w)81 WRITE_LINE_MEMBER(hlcd0538_device::lcd_w)
82 {
83 	state = (state) ? 1 : 0;
84 
85 	// transfer to latches on rising edge
86 	if (state && !m_lcd)
87 	{
88 		m_write_cols(0, m_shift);
89 		m_shift = 0;
90 	}
91 
92 	m_lcd = state;
93 
94 	// interrupt output follows lcd input
95 	m_write_interrupt(state);
96 }
97