mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
added Philips PCF2100 LCD Driver (nw)
This commit is contained in:
parent
4af78838ad
commit
d708a86325
@ -745,6 +745,18 @@ if (VIDEOS["PCD8544"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
--
|
||||
--@src/devices/video/pcf2100.h,VIDEOS["PCF2100"] = true
|
||||
--------------------------------------------------
|
||||
|
||||
if (VIDEOS["PCF2100"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/video/pcf2100.cpp",
|
||||
MAME_DIR .. "src/devices/video/pcf2100.h",
|
||||
}
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
--
|
||||
--@src/devices/video/polylgcy.h,VIDEOS["POLY"] = true
|
||||
|
@ -342,6 +342,7 @@ VIDEOS["MC6845"] = true
|
||||
--VIDEOS["MSM6255"] = true
|
||||
--VIDEOS["MOS6566"] = true
|
||||
VIDEOS["PC_VGA"] = true
|
||||
--VIDEOS["PCF2100"] = true
|
||||
VIDEOS["POLY"] = true
|
||||
VIDEOS["PSX"] = true
|
||||
VIDEOS["RAMDAC"] = true
|
||||
|
@ -371,6 +371,7 @@ VIDEOS["MSM6255"] = true
|
||||
VIDEOS["MOS6566"] = true
|
||||
VIDEOS["PC_VGA"] = true
|
||||
VIDEOS["PCD8544"] = true
|
||||
VIDEOS["PCF2100"] = true
|
||||
--VIDEOS["POLY"] = true
|
||||
VIDEOS["PSX"] = true
|
||||
VIDEOS["RAMDAC"] = true
|
||||
|
@ -64,7 +64,8 @@ void hlcd0515_device::device_start()
|
||||
|
||||
// timer
|
||||
m_lcd_timer = timer_alloc();
|
||||
m_lcd_timer->adjust(attotime::from_hz(clock() / 2), 0, attotime::from_hz(clock() / 2));
|
||||
attotime period = attotime::from_hz(clock() / 2);
|
||||
m_lcd_timer->adjust(period, 0, period);
|
||||
|
||||
// zerofill
|
||||
m_cs = 0;
|
||||
@ -98,7 +99,7 @@ void hlcd0515_device::device_start()
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_timer - handler timer events
|
||||
// device_timer - handle timer events
|
||||
//-------------------------------------------------
|
||||
|
||||
void hlcd0515_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
|
@ -24,7 +24,6 @@ DEFINE_DEVICE_TYPE(LC7582, lc7582_device, "lc7582", "Sanyo LC7582 LCD Driver")
|
||||
|
||||
lc7582_device::lc7582_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
device_t(mconfig, LC7582, tag, owner, clock),
|
||||
m_latch{0, 0},
|
||||
m_write_segs(*this)
|
||||
{ }
|
||||
|
||||
|
@ -59,7 +59,7 @@ private:
|
||||
int m_duty = 0;
|
||||
int m_addsp = 0;
|
||||
u64 m_shift = 0;
|
||||
u64 m_latch[2];
|
||||
u64 m_latch[2] = { 0, 0 };
|
||||
|
||||
// callbacks
|
||||
devcb_write64 m_write_segs;
|
||||
|
119
src/devices/video/pcf2100.cpp
Normal file
119
src/devices/video/pcf2100.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:hap
|
||||
/*
|
||||
|
||||
Philips PCF2100 family LCD Driver
|
||||
|
||||
PCF2100: 2*20 LCD segments
|
||||
PCF2110: 2*30 LCD segments, S31,S32 are LED outputs
|
||||
PCF2111: 2*32 LCD segments
|
||||
PCF2112: 1*32 LCD segments
|
||||
|
||||
OSC is R/C, 2100/10/11: 60-100Hz, 2112: 30-50Hz
|
||||
Actual segment output frequency is divided by number of LCD commons.
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "video/pcf2100.h"
|
||||
|
||||
|
||||
DEFINE_DEVICE_TYPE(PCF2100, pcf2100_device, "pcf2100", "Philips PCF2100 LCD Driver")
|
||||
DEFINE_DEVICE_TYPE(PCF2110, pcf2110_device, "pcf2110", "Philips PCF2110 LCD Driver")
|
||||
DEFINE_DEVICE_TYPE(PCF2111, pcf2111_device, "pcf2111", "Philips PCF2111 LCD Driver")
|
||||
DEFINE_DEVICE_TYPE(PCF2112, pcf2112_device, "pcf2112", "Philips PCF2112 LCD Driver")
|
||||
|
||||
//-------------------------------------------------
|
||||
// constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
pcf2100_device::pcf2100_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bpmax, u8 smax) :
|
||||
device_t(mconfig, type, tag, owner, clock),
|
||||
m_bpmax(bpmax), m_smax(smax), m_write_segs(*this)
|
||||
{ }
|
||||
|
||||
pcf2100_device::pcf2100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
pcf2100_device(mconfig, PCF2100, tag, owner, clock, 2, 20)
|
||||
{ }
|
||||
|
||||
pcf2110_device::pcf2110_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
pcf2100_device(mconfig, PCF2110, tag, owner, clock, 2, 32)
|
||||
{ }
|
||||
|
||||
pcf2111_device::pcf2111_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
pcf2100_device(mconfig, PCF2111, tag, owner, clock, 2, 32)
|
||||
{ }
|
||||
|
||||
pcf2112_device::pcf2112_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
||||
pcf2100_device(mconfig, PCF2112, tag, owner, clock, 1, 32)
|
||||
{ }
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void pcf2100_device::device_start()
|
||||
{
|
||||
// resolve callbacks
|
||||
m_write_segs.resolve_safe();
|
||||
|
||||
// timer
|
||||
m_lcd_timer = timer_alloc();
|
||||
attotime period = attotime::from_hz(clock());
|
||||
m_lcd_timer->adjust(period, 0, period);
|
||||
|
||||
// register for savestates
|
||||
save_item(NAME(m_shift));
|
||||
save_item(NAME(m_count));
|
||||
save_item(NAME(m_bpout));
|
||||
save_item(NAME(m_latch));
|
||||
save_item(NAME(m_clb));
|
||||
save_item(NAME(m_data));
|
||||
save_item(NAME(m_dlen));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// handlers
|
||||
//-------------------------------------------------
|
||||
|
||||
void pcf2100_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
// transfer latches to output
|
||||
m_write_segs(m_bpout, m_latch[m_bpout]);
|
||||
m_bpout = (m_bpout + 1) % m_bpmax;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(pcf2100_device::clb_w)
|
||||
{
|
||||
state = (state) ? 1 : 0;
|
||||
bool rise = state && !m_clb;
|
||||
m_clb = state;
|
||||
|
||||
if (!rise)
|
||||
return;
|
||||
|
||||
if (m_dlen)
|
||||
{
|
||||
// before shifting data, test leading 0 at start
|
||||
if ((m_data && m_count == 0) || m_count > (m_smax + 2))
|
||||
return;
|
||||
|
||||
m_shift |= u64(m_data) << m_count;
|
||||
m_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_count == (m_smax + 2))
|
||||
{
|
||||
// transfer to latches
|
||||
int dest = BIT(m_shift, m_smax + 1) ? 0 : 1;
|
||||
u64 mask = (u64(1) << m_smax) - 1;
|
||||
m_latch[dest] = m_shift >> 1 & mask;
|
||||
}
|
||||
|
||||
m_shift = 0;
|
||||
m_count = 0;
|
||||
}
|
||||
}
|
94
src/devices/video/pcf2100.h
Normal file
94
src/devices/video/pcf2100.h
Normal file
@ -0,0 +1,94 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:hap
|
||||
/*
|
||||
|
||||
Philips PCF2100 family LCD Driver
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MAME_VIDEO_PCF2100_H
|
||||
#define MAME_VIDEO_PCF2100_H
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
|
||||
pinout reference (brief)
|
||||
see datasheet for details, pin numbers differ per chip
|
||||
|
||||
inputs:
|
||||
|
||||
OSC = oscillator input
|
||||
CLB = clock burst
|
||||
DATA = data line
|
||||
DLEN = data line enable
|
||||
|
||||
outputs:
|
||||
|
||||
S: LCD driver outputs
|
||||
BP1/BP2: backplane drivers (LCD commons)
|
||||
|
||||
*/
|
||||
|
||||
class pcf2100_device : public device_t
|
||||
{
|
||||
public:
|
||||
pcf2100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
// configuration helpers
|
||||
auto write_segs() { return m_write_segs.bind(); }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(clb_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(data_w) { m_data = (state) ? 1 : 0; }
|
||||
DECLARE_WRITE_LINE_MEMBER(dlen_w) { m_dlen = (state) ? 1 : 0; }
|
||||
|
||||
protected:
|
||||
pcf2100_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bpmax, u8 smax);
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
emu_timer *m_lcd_timer;
|
||||
|
||||
const u8 m_bpmax; // number of BP pins
|
||||
const u8 m_smax; // number of S pins
|
||||
u64 m_shift = 0;
|
||||
u8 m_count = 0;
|
||||
u8 m_bpout = 0;
|
||||
u32 m_latch[2] = { 0, 0 };
|
||||
|
||||
// pin state
|
||||
int m_clb = 0;
|
||||
int m_data = 0;
|
||||
int m_dlen = 0;
|
||||
|
||||
// callbacks
|
||||
devcb_write32 m_write_segs;
|
||||
};
|
||||
|
||||
class pcf2110_device : public pcf2100_device
|
||||
{
|
||||
public:
|
||||
pcf2110_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
};
|
||||
|
||||
class pcf2111_device : public pcf2100_device
|
||||
{
|
||||
public:
|
||||
pcf2111_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
};
|
||||
|
||||
class pcf2112_device : public pcf2100_device
|
||||
{
|
||||
public:
|
||||
pcf2112_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(PCF2100, pcf2100_device)
|
||||
DECLARE_DEVICE_TYPE(PCF2110, pcf2110_device)
|
||||
DECLARE_DEVICE_TYPE(PCF2111, pcf2111_device)
|
||||
DECLARE_DEVICE_TYPE(PCF2112, pcf2112_device)
|
||||
|
||||
#endif // MAME_VIDEO_PCF2100_H
|
@ -20,7 +20,7 @@ Hardware:
|
||||
#include "machine/timer.h"
|
||||
#include "sound/dac.h"
|
||||
#include "sound/volt_reg.h"
|
||||
#include "video/pwm.h"
|
||||
#include "video/pcf2100.h"
|
||||
#include "speaker.h"
|
||||
|
||||
// internal artwork
|
||||
@ -35,7 +35,7 @@ public:
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_dac(*this, "dac")
|
||||
, m_board(*this, "board")
|
||||
, m_display(*this, "display")
|
||||
, m_lcd(*this, "lcd")
|
||||
, m_inputs(*this, "IN.%u", 0)
|
||||
, m_digits(*this, "digit%u", 0U)
|
||||
, m_leds(*this, "led%u", 0U)
|
||||
@ -49,6 +49,7 @@ protected:
|
||||
|
||||
void mondial68k_mem(address_map &map);
|
||||
|
||||
DECLARE_WRITE32_MEMBER(lcd_s_w);
|
||||
DECLARE_WRITE8_MEMBER(lcd_dlen_w);
|
||||
DECLARE_WRITE8_MEMBER(lcd_clb_w);
|
||||
DECLARE_WRITE8_MEMBER(lcd_data_w);
|
||||
@ -61,14 +62,13 @@ protected:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<dac_bit_interface> m_dac;
|
||||
required_device<sensorboard_device> m_board;
|
||||
required_device<pwm_display_device> m_display;
|
||||
required_device<pcf2112_device> m_lcd;
|
||||
required_ioport_array<4> m_inputs;
|
||||
output_finder<8> m_digits;
|
||||
output_finder<4> m_digits;
|
||||
output_finder<16> m_leds;
|
||||
|
||||
uint8_t m_input_mux;
|
||||
uint8_t m_board_mux;
|
||||
uint8_t m_lcd_shift;
|
||||
uint8_t m_dac_data;
|
||||
};
|
||||
|
||||
@ -80,7 +80,6 @@ void mondial68k_state::machine_start()
|
||||
|
||||
save_item(NAME(m_input_mux));
|
||||
save_item(NAME(m_board_mux));
|
||||
save_item(NAME(m_lcd_shift));
|
||||
save_item(NAME(m_dac_data));
|
||||
}
|
||||
|
||||
@ -88,7 +87,6 @@ void mondial68k_state::machine_reset()
|
||||
{
|
||||
m_input_mux = 0;
|
||||
m_board_mux = 0;
|
||||
m_lcd_shift = 0;
|
||||
m_dac_data = 0;
|
||||
}
|
||||
|
||||
@ -104,27 +102,29 @@ TIMER_DEVICE_CALLBACK_MEMBER(mondial68k_state::refresh_leds)
|
||||
m_leds[0 + i] = 0;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( mondial68k_state::lcd_clb_w )
|
||||
WRITE32_MEMBER(mondial68k_state::lcd_s_w)
|
||||
{
|
||||
if (BIT(data, 0))
|
||||
m_lcd_shift++;
|
||||
// output LCD digits (note: last digit DP segment is unused)
|
||||
for (int i=0; i<4; i++)
|
||||
m_digits[i] = bitswap<8>((data & 0x7fffffff) >> (8 * i), 7,4,5,0,1,2,3,6);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( mondial68k_state::lcd_dlen_w )
|
||||
WRITE8_MEMBER(mondial68k_state::lcd_clb_w)
|
||||
{
|
||||
m_lcd_shift = 0;
|
||||
m_lcd->clb_w(data & 1);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( mondial68k_state::lcd_data_w )
|
||||
WRITE8_MEMBER(mondial68k_state::lcd_dlen_w)
|
||||
{
|
||||
if (m_lcd_shift > 0 && m_lcd_shift < 0x21)
|
||||
{
|
||||
m_display->write_element((m_lcd_shift - 1) / 8, (m_lcd_shift - 1) % 8, BIT(data, 0));
|
||||
m_display->update();
|
||||
}
|
||||
m_lcd->dlen_w(data & 1);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( mondial68k_state::speaker_w )
|
||||
WRITE8_MEMBER(mondial68k_state::lcd_data_w)
|
||||
{
|
||||
m_lcd->data_w(data & 1);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(mondial68k_state::speaker_w)
|
||||
{
|
||||
m_dac_data ^= 1;
|
||||
m_dac->write(m_dac_data);
|
||||
@ -172,14 +172,15 @@ READ8_MEMBER(mondial68k_state::inputs_r)
|
||||
void mondial68k_state::mondial68k_mem(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x00ffff).rom();
|
||||
map(0x800000, 0x800001).r(FUNC(mondial68k_state::inputs_r));
|
||||
map(0x820000, 0x820001).w(FUNC(mondial68k_state::lcd_clb_w));
|
||||
map(0x820002, 0x820003).w(FUNC(mondial68k_state::lcd_data_w));
|
||||
map(0x820004, 0x820005).w(FUNC(mondial68k_state::lcd_dlen_w));
|
||||
map(0x800000, 0x800000).r(FUNC(mondial68k_state::inputs_r));
|
||||
map(0x820000, 0x82000f).nopr();
|
||||
map(0x820000, 0x820000).w(FUNC(mondial68k_state::lcd_clb_w));
|
||||
map(0x820002, 0x820002).w(FUNC(mondial68k_state::lcd_data_w));
|
||||
map(0x820004, 0x820004).w(FUNC(mondial68k_state::lcd_dlen_w));
|
||||
map(0x82000c, 0x82000d).nopw();
|
||||
map(0x82000e, 0x82000f).w(FUNC(mondial68k_state::speaker_w));
|
||||
map(0x840000, 0x840001).w(FUNC(mondial68k_state::input_mux_w));
|
||||
map(0x860000, 0x860001).w(FUNC(mondial68k_state::board_mux_w));
|
||||
map(0x82000e, 0x82000e).w(FUNC(mondial68k_state::speaker_w));
|
||||
map(0x840000, 0x840000).w(FUNC(mondial68k_state::input_mux_w));
|
||||
map(0x860000, 0x860000).w(FUNC(mondial68k_state::board_mux_w));
|
||||
map(0xc00000, 0xc03fff).ram();
|
||||
}
|
||||
|
||||
@ -233,10 +234,8 @@ void mondial68k_state::mondial68k(machine_config &config)
|
||||
m_board->set_delay(attotime::from_msec(100));
|
||||
|
||||
/* video hardware */
|
||||
PWM_DISPLAY(config, m_display).set_size(4, 8);
|
||||
m_display->set_segmask(0xf, 0xff);
|
||||
m_display->set_segmask(0x8, 0x7f); // last digit: DP segment unused
|
||||
m_display->output_digit().set([this](offs_t offset, u8 data) { m_digits[offset] = bitswap<8>(data, 7,4,5,0,1,2,3,6); });
|
||||
PCF2112(config, m_lcd, 50); // frequency guessed
|
||||
m_lcd->write_segs().set(FUNC(mondial68k_state::lcd_s_w));
|
||||
config.set_default_layout(layout_mephisto_mondial68k);
|
||||
|
||||
/* sound hardware */
|
||||
|
@ -14,7 +14,8 @@
|
||||
- holding CL+INFO+BOOK on boot load the test mode
|
||||
|
||||
TODO:
|
||||
- split driver into several files? need to make PCF2112T device
|
||||
- split driver into several files?
|
||||
- use PCF2112T device (it has 2 of them)
|
||||
- why are megaiv/smondial2 beeps noisy?
|
||||
- add Monte Carlo IV (non-LE)
|
||||
- add MM 1000 module
|
||||
|
@ -12,7 +12,7 @@
|
||||
* (http://worstconsole.blogspot.ca/2012/12/the-worstconsoleever.html)
|
||||
* Note a spare dead GIC has been given to Lord Nightmare and should be sent for decap!
|
||||
*
|
||||
* The Unisonc Champion is the only known GI "Gimini Mid-Range 8950 Programmable Game Set"
|
||||
* The Unisonic Champion is the only known GI "Gimini Mid-Range 8950 Programmable Game Set"
|
||||
* to ever reach the market, and only in limited quantities (aprox 500 units ever built)
|
||||
*
|
||||
* Architecture:
|
||||
|
@ -45,9 +45,9 @@
|
||||
|
||||
for a total of (12*20*16) = 3840 RAM reads (3 clocks per read at 1.79MHz)
|
||||
|
||||
Then it relingishes control to the CPU by raising BUSREQ.
|
||||
Then it relinquishes control to the CPU by raising BUSREQ.
|
||||
|
||||
Cloking in more detail: (in 1.79MHz clocks)
|
||||
Clocking in more detail: (in 1.79MHz clocks)
|
||||
boot:
|
||||
busy:1 5360 clocks
|
||||
busy:0 22116 clocks
|
||||
@ -257,9 +257,9 @@ void gic_device::sound_stream_update(sound_stream &stream, stream_sample_t **inp
|
||||
stream_sample_t *buffer = outputs[0];
|
||||
|
||||
//Audio is basic and badly implemented (doubt that was the intent)
|
||||
//The datasheet list the 3 different frequencies the GIC can generate: 500,1000 and 2000Hz
|
||||
//The datasheet lists the 3 different frequencies the GIC can generate: 500,1000 and 2000Hz
|
||||
//but it is clear (for an audio guy at least) that the resulting spectrum
|
||||
//is not a pure square wav. In fact, the counter is reset on vertical sync!
|
||||
//is not a pure square wave. In fact, the counter is reset on vertical sync!
|
||||
//http://twitter.com/plgDavid/status/527269086016077825
|
||||
//...thus creating a buzzing sound.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user