1 // license:BSD-3-Clause
2 // copyright-holders:hap
3 /*
4 
5 Hughes HLCD 0438 LCD Driver
6 32 segment outputs, may also be used as a column driver
7 
8 LCD pin can be driven manually, or oscillating.
9 
10 */
11 
12 #include "emu.h"
13 #include "video/hlcd0438.h"
14 
15 
16 DEFINE_DEVICE_TYPE(HLCD0438, hlcd0438_device, "hlcd0438", "Hughes HLCD 0438 LCD Driver")
17 
18 //-------------------------------------------------
19 //  constructor
20 //-------------------------------------------------
21 
hlcd0438_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)22 hlcd0438_device::hlcd0438_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
23 	device_t(mconfig, HLCD0438, tag, owner, clock),
24 	m_write_segs(*this), m_write_data(*this)
25 { }
26 
27 
28 //-------------------------------------------------
29 //  device_start - device-specific startup
30 //-------------------------------------------------
31 
device_start()32 void hlcd0438_device::device_start()
33 {
34 	// resolve callbacks
35 	m_write_segs.resolve_safe();
36 	m_write_data.resolve_safe();
37 
38 	// timer (when LCD pin is oscillator)
39 	m_lcd_timer = timer_alloc();
40 	attotime period = (clock() != 0) ? attotime::from_hz(2 * clock()) : attotime::never;
41 	m_lcd_timer->adjust(period, 0, period);
42 
43 	// register for savestates
44 	save_item(NAME(m_data_in));
45 	save_item(NAME(m_data_out));
46 	save_item(NAME(m_clk));
47 	save_item(NAME(m_load));
48 	save_item(NAME(m_lcd));
49 	save_item(NAME(m_shift));
50 	save_item(NAME(m_latch));
51 }
52 
53 
54 //-------------------------------------------------
55 //  handlers
56 //-------------------------------------------------
57 
clock_w(int state)58 void hlcd0438_device::clock_w(int state)
59 {
60 	state = state ? 1 : 0;
61 
62 	// shift on falling edge
63 	if (m_clk && !state)
64 	{
65 		// DATA OUT pin follows carry out
66 		m_data_out = BIT(m_shift, 31);
67 
68 		m_shift = m_shift << 1 | m_data_in;
69 
70 		m_write_data(m_data_out);
71 		load_w(m_load);
72 	}
73 
74 	m_clk = state;
75 }
76 
load_w(int state)77 void hlcd0438_device::load_w(int state)
78 {
79 	m_load = state ? 1 : 0;
80 
81 	// load to output latches while LOAD pin is high
82 	if (m_load)
83 		m_latch = m_shift;
84 }
85 
lcd_w(int state)86 void hlcd0438_device::lcd_w(int state)
87 {
88 	state = state ? 1 : 0;
89 
90 	// LCD pin drives backplate
91 	if (state != m_lcd)
92 		m_write_segs(m_lcd, m_latch);
93 
94 	m_lcd = state;
95 }
96