summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Felipe CorrĂȘa da Silva Sanches <fsanches@metamaquina.com.br>2017-08-22 22:53:00 -0300
committer Vas Crabb <cuavas@users.noreply.github.com>2017-08-23 11:53:00 +1000
commitf2407286b14d2fad789a207045cba2a0e20c94dd (patch)
tree54b16fc11b43cea6c2199f1a50590af70e565050
parent14891e3c99ba76bf8ff2048a1c1d5497ab16a1a8 (diff)
new drivers for "Control ID x628" fingerprint-reader and for the NT7534 LCD controller (#2583)
* initial skelethon: ControlID X628 fingerprint reader * first draft of an implementation of the NT7534 device (LCD controller) * fix emulation of ControlID x628 + NT7534 LCD controller * cidx628: fix LCD color palette on Control ID x628 driver * Adding a header with details of the hardware. This is the first MAME driver with an LCD controlled by a NT7534 chip, so I wrote an initial implementation of that new device.
-rw-r--r--scripts/src/video.lua12
-rw-r--r--scripts/target/mame/mess.lua2
-rw-r--r--src/devices/video/nt7534.cpp355
-rw-r--r--src/devices/video/nt7534.h93
-rw-r--r--src/mame/drivers/controlid.cpp136
-rw-r--r--src/mame/mame.lst3
6 files changed, 601 insertions, 0 deletions
diff --git a/scripts/src/video.lua b/scripts/src/video.lua
index 5bf85c6650d..f883a45f592 100644
--- a/scripts/src/video.lua
+++ b/scripts/src/video.lua
@@ -270,6 +270,18 @@ end
--------------------------------------------------
--
+--@src/devices/video/nt7534.h,VIDEOS["NT7534"] = true
+--------------------------------------------------
+
+if (VIDEOS["NT7534"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/video/nt7534.cpp",
+ MAME_DIR .. "src/devices/video/nt7534.h",
+ }
+end
+
+--------------------------------------------------
+--
--@src/devices/video/hd44102.h,VIDEOS["HD44102"] = true
--------------------------------------------------
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index e985419a17e..be5ab241ff1 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -294,6 +294,7 @@ VIDEOS["EF9365"] = true
VIDEOS["GF4500"] = true
--VIDEOS+= EPIC12"] = true
--VIDEOS+= FIXFREQ"] = true
+VIDEOS["NT7534"] = true
VIDEOS["HD44102"] = true
VIDEOS["HD44352"] = true
VIDEOS["HD44780"] = true
@@ -3411,6 +3412,7 @@ files {
MAME_DIR .. "src/mame/drivers/cd2650.cpp",
MAME_DIR .. "src/mame/drivers/cdc721.cpp",
MAME_DIR .. "src/mame/drivers/codata.cpp",
+ MAME_DIR .. "src/mame/drivers/controlid.cpp",
MAME_DIR .. "src/mame/drivers/cortex.cpp",
MAME_DIR .. "src/mame/drivers/cosmicos.cpp",
MAME_DIR .. "src/mame/includes/cosmicos.h",
diff --git a/src/devices/video/nt7534.cpp b/src/devices/video/nt7534.cpp
new file mode 100644
index 00000000000..543115f8fe8
--- /dev/null
+++ b/src/devices/video/nt7534.cpp
@@ -0,0 +1,355 @@
+// license:BSD-3-Clause
+// copyright-holders:Felipe Sanches, Sandro Ronco
+/***************************************************************************
+
+ NT7534 LCD controller
+
+ TODO:
+ - determine video timings and busy flag duration
+
+***************************************************************************/
+
+#include "emu.h"
+#include "video/nt7534.h"
+
+#define VERBOSE 1
+#include "logmacro.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NT7534, nt7534_device, "nt7534", "NT7534 LCD Controller")
+
+
+//-------------------------------------------------
+// nt7534_device - constructor
+//-------------------------------------------------
+
+nt7534_device::nt7534_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : nt7534_device(mconfig, NT7534, tag, owner, clock)
+{
+}
+
+nt7534_device::nt7534_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void nt7534_device::device_start()
+{
+ m_busy_timer = timer_alloc(TIMER_BUSY);
+
+ // state saving
+ save_item(NAME(m_busy_flag));
+ save_item(NAME(m_page));
+ save_item(NAME(m_column));
+ save_item(NAME(m_dr));
+ save_item(NAME(m_ir));
+ save_item(NAME(m_display_on));
+ save_item(NAME(m_display_start_line));
+ save_item(NAME(m_direction));
+ save_item(NAME(m_data_len));
+ save_item(NAME(m_ddram));
+ save_item(NAME(m_nibble));
+ save_item(NAME(m_rs_state));
+ save_item(NAME(m_rw_state));
+ save_item(NAME(m_backup_column));
+ save_item(NAME(m_read_modify_write));
+ save_item(NAME(m_adc));
+ save_item(NAME(m_reverse));
+ save_item(NAME(m_entire_display_on));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void nt7534_device::device_reset()
+{
+ memset(m_ddram, 0x00, sizeof(m_ddram));
+
+ m_page = 0;
+ m_column = 0;
+ m_dr = 0;
+ m_ir = 0;
+ m_display_on = false;
+ m_entire_display_on = false;
+ m_direction = 1;
+ m_adc = true;
+ m_read_modify_write = false;
+ m_reverse = false;
+ m_data_len = 8;
+ m_nibble = false;
+ m_rs_state = 0;
+ m_rw_state = 0;
+
+ set_busy_flag(1520);
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void nt7534_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case TIMER_BUSY:
+ m_busy_flag = false;
+ break;
+ }
+}
+
+
+//**************************************************************************
+// HELPERS
+//**************************************************************************
+
+void nt7534_device::set_busy_flag(uint16_t usec)
+{
+ m_busy_flag = true;
+ m_busy_timer->adjust( attotime::from_usec( usec ) );
+}
+
+void nt7534_device::update_nibble(int rs, int rw)
+{
+ if (m_rs_state != rs || m_rw_state != rw)
+ {
+ m_rs_state = rs;
+ m_rw_state = rw;
+ m_nibble = false;
+ }
+
+ m_nibble = !m_nibble;
+}
+
+//**************************************************************************
+// device interface
+//**************************************************************************
+
+uint32_t nt7534_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ bitmap.fill(0, cliprect);
+
+ for (uint16_t x = 0; x < 132; x++)
+ {
+ uint16_t px = m_adc ? x : 131 - x;
+ for (uint8_t y = 0; y < 65; y++)
+ {
+ uint8_t py = (y + m_display_start_line - 32) % 65;
+ uint8_t page = py/8;
+ bitmap.pix16(y, x) = BIT(m_ddram[page*132 + px], py%8);
+ }
+ }
+
+ return 0;
+}
+
+READ8_MEMBER(nt7534_device::read)
+{
+ switch (offset & 0x01)
+ {
+ case 0: return control_read(space, 0);
+ case 1: return data_read(space, 0);
+ }
+
+ return 0;
+}
+
+WRITE8_MEMBER(nt7534_device::write)
+{
+ switch (offset & 0x01)
+ {
+ case 0: control_write(space, 0, data); break;
+ case 1: data_write(space, 0, data); break;
+ }
+}
+
+WRITE8_MEMBER(nt7534_device::control_write)
+{
+ if (m_data_len == 4)
+ {
+ update_nibble(0, 0);
+
+ if (m_nibble)
+ {
+ m_ir = data & 0xF0;
+ return;
+ }
+ else
+ {
+ m_ir |= ((data >> 4) & 0x0F);
+ }
+ }
+ else
+ {
+ m_ir = data;
+ }
+
+ if (m_ir == 0xE2)
+ {
+ // Reset
+ memset(m_ddram, 0x00, sizeof(m_ddram));
+ m_page = 0;
+ m_column = 0;
+ LOG("NT7534: Reset \n");
+ return;
+ }
+ else if ((m_ir & 0xFE) == 0xAE)
+ {
+ // Display ON/OFF
+ m_display_on = m_ir & 1;
+ LOG("NT7534: Display %s\n", m_display_on ? "ON" : "OFF");
+ return;
+ }
+ else if ((m_ir & 0xC0) == 0x40)
+ {
+ // Display Start Line Set
+ m_display_start_line = m_ir & 0x3F;
+ LOG("NT7534: Display Start Line: %d\n", m_display_start_line);
+ return;
+ }
+ else if ((m_ir & 0xF0) == 0xB0)
+ {
+ // set Page Address
+ m_page = m_ir & 0x0F;
+
+ LOG("NT7534: set Page address %x\n", m_page);
+ return;
+ }
+ else if ((m_ir & 0xF0) == 0x10)
+ {
+ // Set column address MSB
+ m_column = (m_column & 0x0F) | ((m_ir & 0x0F) << 4);
+
+ LOG("NT7534: set column address MSB %x\n", (m_column >> 4) & 0x0F);
+ return;
+ }
+ else if ((m_ir & 0xF0) == 0x00)
+ {
+ // Set column address LSB
+ m_column = (m_column & 0xF0) | (m_ir & 0x0F);
+
+ LOG("NT7534: set column address LSB %x\n", m_column & 0x0F);
+ return;
+ }
+ else if ((m_ir & 0xFE) == 0xA0)
+ {
+ // ADC Select
+ m_adc = m_ir & 1;
+ LOG("NT7534: ADC: %d\n", m_adc);
+ return;
+ }
+ else if ((m_ir & 0xFE) == 0xA6)
+ {
+ // Normal/Reverse Display
+ m_reverse = m_ir & 1;
+ LOG("NT7534: Display Reverse ? %s\n", m_reverse ? "Yes" : "No");
+ return;
+ }
+ else if ((m_ir & 0xFE) == 0xA4)
+ {
+ // Entire display ON
+ m_entire_display_on = m_ir & 1;
+ LOG("NT7534: Entire Display ON ? %s\n", m_entire_display_on ? "Yes" : "No");
+ return;
+ }
+ else if (m_ir == 0xE0)
+ {
+ // Enable Read-Modify-Write
+ m_read_modify_write = true;
+ m_backup_column = m_column;
+ LOG("NT7534: Enable Read-Modify-Write. Backup column: %d\n", m_backup_column);
+ return;
+ }
+ else if (m_ir == 0xEE)
+ {
+ // Disable Read-Modify-Write
+ m_read_modify_write = false;
+ m_column = m_backup_column; // restore column value
+ LOG("NT7534: Disable Read-Modify-Write.\n");
+ return;
+ }
+}
+
+READ8_MEMBER(nt7534_device::control_read)
+{
+ if (m_data_len == 4)
+ {
+ if (!machine().side_effect_disabled())
+ update_nibble(0, 1);
+
+ if (m_nibble)
+ return (m_busy_flag ? 0x80 : 0);
+ else
+ return 0; //TODO: review this.
+ }
+ else
+ {
+ return (m_busy_flag ? 0x80 : 0);
+ }
+}
+
+WRITE8_MEMBER(nt7534_device::data_write)
+{
+// if (m_busy_flag)
+// {
+// logerror("NT7534: Ignoring data write %02x due to busy flag\n", data);
+// return;
+// }
+
+ if (m_data_len == 4)
+ {
+ update_nibble(1, 0);
+
+ if (m_nibble)
+ {
+ m_dr = data & 0xF0;
+ return;
+ }
+ else
+ {
+ m_dr |= ((data >> 4) & 0x0F);
+ }
+ }
+ else
+ {
+ m_dr = data;
+ }
+
+ LOG("NT7534: RAM write %x %x '%c'\n", m_page*132 + m_column, m_dr, isprint(m_dr) ? m_dr : '.');
+
+ m_ddram[m_page*132 + m_column] = m_dr;
+
+ if (m_column < 131)
+ m_column++;
+
+ set_busy_flag(41);
+}
+
+READ8_MEMBER(nt7534_device::data_read)
+{
+ uint8_t data = m_ddram[m_page*132 + m_column];
+ if (m_read_modify_write == false && m_column < 131)
+ m_column++;
+
+ if (m_data_len == 4)
+ {
+ if (!machine().side_effect_disabled())
+ update_nibble(1, 1);
+
+ if (m_nibble)
+ return data & 0xF0;
+ else
+ data = (data << 4) & 0xF0;
+ }
+
+ return data;
+}
diff --git a/src/devices/video/nt7534.h b/src/devices/video/nt7534.h
new file mode 100644
index 00000000000..198e6291157
--- /dev/null
+++ b/src/devices/video/nt7534.h
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Felipe Sanches, Sandro Ronco
+/***************************************************************************
+
+ NT7534 LCD controller
+
+***************************************************************************/
+
+#ifndef MAME_VIDEO_NT7534_H
+#define MAME_VIDEO_NT7534_H
+
+#pragma once
+
+
+#define MCFG_NT7534_ADD( _tag ) \
+ MCFG_DEVICE_ADD( _tag, NT7534, 0 )
+
+#define MCFG_NT7534_PIXEL_UPDATE_CB(_class, _method) \
+ nt7534_device::static_set_pixel_update_cb(*device, nt7534_device::pixel_update_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner)));
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+#define NT7534_PIXEL_UPDATE(name) void name(bitmap_ind16 &bitmap, uint8_t line, uint8_t pos, uint8_t y, uint8_t x, int state)
+
+
+// ======================> nt7534_device
+
+class nt7534_device : public device_t
+{
+public:
+ typedef device_delegate<void (bitmap_ind16 &bitmap, uint8_t line, uint8_t pos, uint8_t y, uint8_t x, int state)> pixel_update_delegate;
+
+ // construction/destruction
+ nt7534_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static void static_set_pixel_update_cb(device_t &device, pixel_update_delegate &&cb) { downcast<nt7534_device &>(device).m_pixel_update_cb = std::move(cb); }
+
+ // device interface
+ virtual DECLARE_WRITE8_MEMBER(write);
+ virtual DECLARE_READ8_MEMBER(read);
+ virtual DECLARE_WRITE8_MEMBER(control_write);
+ virtual DECLARE_READ8_MEMBER(control_read);
+ virtual DECLARE_WRITE8_MEMBER(data_write);
+ virtual DECLARE_READ8_MEMBER(data_read);
+
+ const uint8_t *render();
+ virtual uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+
+protected:
+ nt7534_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+private:
+ // internal helper
+ void set_busy_flag(uint16_t usec);
+ void update_nibble(int rs, int rw);
+
+ // internal state
+ static constexpr device_timer_id TIMER_BUSY = 0;
+
+ emu_timer * m_busy_timer;
+
+ pixel_update_delegate m_pixel_update_cb; // pixel update callback
+
+ bool m_busy_flag;
+ uint8_t m_ddram[9*132]; // internal display data RAM
+ uint8_t m_page; // page address
+ uint16_t m_column; // column address
+ uint16_t m_backup_column; // column address
+ uint8_t m_display_start_line;
+ uint8_t m_dr; // data register
+ uint8_t m_ir; // instruction register
+ bool m_display_on; // display on/off
+ bool m_entire_display_on;
+ bool m_reverse; // Reverse display
+ bool m_read_modify_write;
+ bool m_adc;
+ int m_direction; // auto increment/decrement (-1 or +1)
+ uint8_t m_data_len; // interface data length 4 or 8 bit
+ int m_rs_state;
+ int m_rw_state;
+ bool m_nibble;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(NT7534, nt7534_device)
+
+#endif // MAME_VIDEO_NT7534_H
diff --git a/src/mame/drivers/controlid.cpp b/src/mame/drivers/controlid.cpp
new file mode 100644
index 00000000000..835488230cd
--- /dev/null
+++ b/src/mame/drivers/controlid.cpp
@@ -0,0 +1,136 @@
+// license:BSD-3-Clause
+// copyright-holder:FelipeSanches
+//
+// Control ID x628
+//
+// This is a fingerprint reader device
+//
+// TODO: Emulate the other CPU board (supposedly runs the Linux kernel on
+// a dedicated SoC targeting image-processing typically used on
+// fingerprint readers). The SoC is labelled ZKSoftware ZK6001
+// and someone online suggested it may be a rebranded device from
+// Ingenic, so likely a MIPS32 or MIPS64.
+//
+// It has a 32Mb flash-rom and an ethernet controller
+// (model is Realtek RTL8201BL)
+//
+// While the 8051 board has a tiny buzzer (and a battery-backed RAM)
+// the other PCB interfaces with an audio speaker.
+//
+// There's also an RJ45 connector (ethernet port) as well as a
+// DB9 connector which seems to be used for a serial interface.
+//
+// Finally, there are 2 LEDs, a 128x64 LCD with blueish backlight
+// and a keypad with the following layout:
+//
+// 1 2 3 ESC
+// 4 5 6 MENU
+// 7 8 9 UP-ARROW
+// . 0 OK DOWN-ARROW
+
+#include "emu.h"
+#include "cpu/mcs51/mcs51.h"
+#include "video/nt7534.h"
+#include "screen.h"
+
+class controlidx628_state : public driver_device
+{
+public:
+ controlidx628_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag),
+ m_lcdc(*this, "nt7534") { }
+ DECLARE_WRITE8_MEMBER( p0_w );
+ DECLARE_WRITE8_MEMBER( p1_w );
+ DECLARE_PALETTE_INIT( controlidx628 );
+
+ required_device<nt7534_device> m_lcdc;
+private:
+ uint8_t p0_data;
+ uint8_t p1_data;
+};
+
+
+/*************************
+* Memory map information *
+*************************/
+
+static ADDRESS_MAP_START( prog_map, AS_PROGRAM, 8, controlidx628_state )
+ AM_RANGE(0x0000, 0x1fff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( io_map, AS_IO, 8, controlidx628_state )
+ AM_RANGE(0x8000, 0xffff) AM_RAM
+
+// /* Ports start here */
+ AM_RANGE(MCS51_PORT_P0, MCS51_PORT_P0) AM_WRITE(p0_w)
+ AM_RANGE(MCS51_PORT_P1, MCS51_PORT_P1) AM_WRITE(p1_w)
+// AM_RANGE(MCS51_PORT_P2, MCS51_PORT_P2) AM_RAM
+// AM_RANGE(MCS51_PORT_P3, MCS51_PORT_P3) AM_RAM
+ADDRESS_MAP_END
+
+
+WRITE8_MEMBER( controlidx628_state::p0_w )
+{
+ p0_data = data;
+}
+
+WRITE8_MEMBER( controlidx628_state::p1_w )
+{
+ if ((BIT(p1_data, 6) == 0) && (BIT(data, 6) == 1)) // on raising-edge of bit 6
+ {
+ m_lcdc->write(space, BIT(data, 7), p0_data);
+ }
+ p1_data = data;
+}
+
+/*************************
+* Input ports *
+*************************/
+
+//static INPUT_PORTS_START( controlidx628 )
+//INPUT_PORTS_END
+
+PALETTE_INIT_MEMBER(controlidx628_state, controlidx628)
+{
+ // These colors were selected from a photo of the display
+ // using the color-picker in Inkscape:
+ palette.set_pen_color(0, rgb_t(0x06, 0x61, 0xEE));
+ palette.set_pen_color(1, rgb_t(0x00, 0x23, 0x84));
+}
+
+/*************************
+* Machine Driver *
+*************************/
+
+static MACHINE_CONFIG_START( controlidx628 )
+ // basic machine hardware
+ MCFG_CPU_ADD("maincpu", I80C32, XTAL_11_0592MHz) /* Actually the board has an Atmel AT89S52 mcu. */
+ MCFG_CPU_PROGRAM_MAP(prog_map)
+ MCFG_CPU_IO_MAP(io_map)
+
+ /* video hardware */
+ MCFG_SCREEN_ADD("screen", LCD)
+ MCFG_SCREEN_REFRESH_RATE(50)
+ MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
+ MCFG_SCREEN_SIZE(132, 65)
+ MCFG_SCREEN_VISIBLE_AREA(3, 130, 0, 63)
+ MCFG_SCREEN_UPDATE_DEVICE("nt7534", nt7534_device, screen_update)
+ MCFG_SCREEN_PALETTE("palette")
+
+ MCFG_PALETTE_ADD("palette", 2)
+ MCFG_PALETTE_INIT_OWNER(controlidx628_state, controlidx628)
+
+ MCFG_NT7534_ADD("nt7534")
+MACHINE_CONFIG_END
+
+
+/*************************
+* Rom Load *
+*************************/
+
+ROM_START( cidx628 )
+ ROM_REGION( 0x2000, "maincpu", 0 )
+ ROM_LOAD( "controlid_x628.u1", 0x0000, 0x2000, CRC(500d79b4) SHA1(5522115f2da622db389e067fcdd4bccb7aa8561a) )
+ROM_END
+
+COMP(200?, cidx628, 0, 0, controlidx628, 0, controlidx628_state, 0, "ControlID", "X628", MACHINE_NOT_WORKING|MACHINE_NO_SOUND)
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index e52a59a3bb6..201c680f451 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -32017,6 +32017,9 @@ qtsbc //
@source:quakeat.cpp
quake // (c) 19?? Lazer-Tron / iD Software
+@source:controlid.cpp
+cidx628 // 200? Control ID X628
+
@source:quantum.cpp
quantum // 136016 (c) 1982 // made by Gencomp
quantum1 // 136016 (c) 1982 // made by Gencomp