From 1bc2b0472856ce10a189c791bbbce66d0d6f9764 Mon Sep 17 00:00:00 2001 From: Sandro Ronco Date: Sat, 29 Jun 2019 23:44:25 +0200 Subject: tascr30: add display, inputs and SmartBoard. [Sandro Ronco] Machines promoted to working ---------------------------- Tasc ChessSystem R30 [Sandro Ronco] --- src/devices/video/t6963c.cpp | 197 +++++++++++++++-- src/devices/video/t6963c.h | 24 ++ src/mame/drivers/tasc.cpp | 98 +++++++- src/mame/layout/tascr30.lay | 480 ++++++++++++++++++++++++++++++++++++++++ src/mame/machine/smartboard.cpp | 282 +++++++++++++++++++++++ src/mame/machine/smartboard.h | 60 +++++ 6 files changed, 1110 insertions(+), 31 deletions(-) create mode 100644 src/mame/layout/tascr30.lay create mode 100644 src/mame/machine/smartboard.cpp create mode 100644 src/mame/machine/smartboard.h (limited to 'src') diff --git a/src/devices/video/t6963c.cpp b/src/devices/video/t6963c.cpp index 0a07a1a7553..7e62d70c0e8 100644 --- a/src/devices/video/t6963c.cpp +++ b/src/devices/video/t6963c.cpp @@ -10,6 +10,9 @@ #include "emu.h" #include "t6963c.h" +//#define VERBOSE 1 +#include "logmacro.h" + //************************************************************************** // GLOBAL VARIABLES //************************************************************************** @@ -38,6 +41,16 @@ t6963c_device::t6963c_device(const machine_config &mconfig, const char *tag, dev , m_data(0) , m_adp(0) , m_auto_mode(auto_mode::NONE) + , m_graphic_home(0) + , m_text_home(0) + , m_graphic_area(0) + , m_text_area(0) + , m_cgram_offset(0) + , m_mode(0) + , m_display_mode(0) + , m_font_size(6) + , m_number_cols(40) + , m_number_lines(8) { } @@ -66,6 +79,16 @@ void t6963c_device::device_start() save_item(NAME(m_data)); save_item(NAME(m_adp)); save_item(NAME(m_auto_mode)); + save_item(NAME(m_graphic_home)); + save_item(NAME(m_text_home)); + save_item(NAME(m_graphic_area)); + save_item(NAME(m_text_area)); + save_item(NAME(m_cgram_offset)); + save_item(NAME(m_mode)); + save_item(NAME(m_display_mode)); + save_item(NAME(m_font_size)); + save_item(NAME(m_number_cols)); + save_item(NAME(m_number_lines)); } @@ -76,6 +99,15 @@ void t6963c_device::device_start() void t6963c_device::device_reset() { m_auto_mode = auto_mode::NONE; + m_data = 0; + m_adp = 0; + m_graphic_home = 0; + m_text_home = 0; + m_graphic_area = 0; + m_text_area = 0; + m_cgram_offset = 0; + m_mode = 0; + m_display_mode = 0; } @@ -105,11 +137,11 @@ void t6963c_device::write(offs_t offset, u8 data) // Data register if (m_auto_mode == auto_mode::WRITE) { - logerror("%s: Auto write %02X to %04X\n", machine().describe_context(), data, m_adp); + LOG("%s: Auto write %02X to %04X\n", machine().describe_context(), data, m_adp); m_display_ram->write_byte(m_adp++, data); } else - m_data = (u16(data) << 8) | (data >> 8); + m_data = (u16(data) << 8) | (m_data >> 8); } } @@ -129,14 +161,16 @@ void t6963c_device::do_command(u8 cmd) break; case 0x02: - logerror("%s: Setting offset register for CG RAM at %04X to %04XH\n", + LOG("%s: Setting offset register for CG RAM at %04X to %04XH\n", machine().describe_context(), (m_data & 0x1f) << 11, (m_data & 0x1f) << 11 | 0x7ff); + + m_cgram_offset = (m_data & 0x1f) << 11; break; case 0x04: - logerror("%s: Setting address pointer = %04X\n", machine().describe_context(), m_data); + LOG("%s: Setting address pointer = %04X\n", machine().describe_context(), m_data); m_adp = m_data; break; @@ -147,37 +181,51 @@ void t6963c_device::do_command(u8 cmd) } else if ((cmd & 0xfd) == 0x40) { - logerror("%s: Setting %s home address = %04X\n", machine().describe_context(), + LOG("%s: Setting %s home address = %04X\n", machine().describe_context(), BIT(cmd, 1) ? "graphic" : "text", m_data); + + if (BIT(cmd, 1)) + m_graphic_home = m_data; + else + m_text_home = m_data; } else if ((cmd & 0xfd) == 0x41) { - logerror("%s: Setting %s area = %d columns\n", machine().describe_context(), + LOG("%s: Setting %s area = %d columns\n", machine().describe_context(), BIT(cmd, 1) ? "graphic" : "text", m_data); + + + if (BIT(cmd, 1)) + m_graphic_area = m_data; + else + m_text_area = m_data; } else if ((cmd & 0xf0) == 0x80) { - logerror("%s: %s mode, %s\n", machine().describe_context(), + LOG("%s: %s mode, %s\n", machine().describe_context(), (cmd & 0x07) == 0x00 ? "OR" : (cmd & 0x07) == 0x01 ? "EXOR" : (cmd & 0x07) == 0x03 ? "AND" : (cmd & 0x07) == 0x04 ? "Text attribute" : "Unknown", BIT(cmd, 3) ? "external CG RAM" : "internal CG ROM"); + + m_mode = cmd & 0x0f; } else if ((cmd & 0xf0) == 0x90) { if (cmd == 0x90) - logerror("%s: Display off\n", machine().describe_context()); + LOG("%s: Display off\n", machine().describe_context()); else - logerror("%s: Text %s, graphic %s, cursor %s, blink %s\n", + LOG("%s: Text %s, graphic %s, cursor %s, blink %s\n", machine().describe_context(), BIT(cmd, 3) ? "on" : "off", BIT(cmd, 2) ? "on" : "off", BIT(cmd, 1) ? "on" : "off", BIT(cmd, 0) ? "on" : "off"); + m_display_mode = cmd & 0x0f; } else if ((cmd & 0xf8) == 0xa0) { @@ -185,20 +233,19 @@ void t6963c_device::do_command(u8 cmd) } else if ((cmd & 0xfe) == 0xb0) { - logerror("%s: Set data auto %s\n", machine().describe_context(), BIT(cmd, 0) ? "read" : "write"); + LOG("%s: Set data auto %s\n", machine().describe_context(), BIT(cmd, 0) ? "read" : "write"); m_auto_mode = BIT(cmd, 0) ? auto_mode::READ : auto_mode::WRITE; } else if (cmd == 0xb2) { - logerror("%s: Auto reset\n", machine().describe_context()); + LOG("%s: Auto reset\n", machine().describe_context()); m_auto_mode = auto_mode::NONE; } else if ((cmd & 0xf0) == 0xc0) { if (BIT(cmd, 0)) { - logerror("%s: Read data from %04X and %s ADP\n", machine().describe_context(), - BIT(cmd, 0) ? "read" : "write", + LOG("%s: Read data from %04X and %s ADP\n", machine().describe_context(), m_adp, (cmd & 0x0e) == 0x00 ? "increment" : (cmd & 0x0e) == 0x02 ? "decrement" @@ -207,7 +254,7 @@ void t6963c_device::do_command(u8 cmd) } else { - logerror("%s: Write %02X to %04X and %s ADP\n", machine().describe_context(), + LOG("%s: Write %02X to %04X and %s ADP\n", machine().describe_context(), m_data >> 8, m_adp, (cmd & 0x0e) == 0x00 ? "increment" @@ -216,11 +263,12 @@ void t6963c_device::do_command(u8 cmd) : "invalid"); m_display_ram->write_byte(m_adp, m_data >> 8); - if ((cmd & 0x0e) == 0x00) - ++m_adp; - else if ((cmd & 0x0e) == 0x02) - --m_adp; } + + if ((cmd & 0x0e) == 0x00) + ++m_adp; + else if ((cmd & 0x0e) == 0x02) + --m_adp; } else if (cmd == 0xe0) { @@ -232,9 +280,17 @@ void t6963c_device::do_command(u8 cmd) } else if ((cmd & 0xf0) == 0xf0) { - logerror("%s: %s bit %d\n", machine().describe_context(), + LOG("%s: %s bit %d\n", machine().describe_context(), BIT(cmd, 3) ? "Set" : "Reset", cmd & 0x07); + + u8 data = m_display_ram->read_byte(m_adp); + if (BIT(cmd, 3)) + data |= 1 << (cmd & 0x07); + else + data &= ~(1 << (cmd & 0x07)); + + m_display_ram->write_byte(m_adp, data); } else { @@ -242,6 +298,88 @@ void t6963c_device::do_command(u8 cmd) } } +void t6963c_device::set_fs(u8 data) +{ + m_font_size = 8 - (data & 3); +} + +void t6963c_device::set_md(u8 data) +{ + // MD0, MD1 + m_number_lines = 8 - (data & 3) * 2; + + if (BIT(data, 4)) // MDS + m_number_lines += 8; + + switch((data >> 2) & 3) // MD2, MD3 + { + case 0: m_number_cols = 32; break; + case 1: m_number_cols = 40; break; + case 2: m_number_cols = 64; break; + case 3: m_number_cols = 80; break; + } +} + + +uint32_t t6963c_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + bitmap.fill(0, cliprect); + + // Text layer + if (BIT(m_display_mode, 3)) + for(int y=0; yread_byte(m_text_home + y * m_number_cols + x); + + for(int cy=0; cy<8; cy++) + { + u8 data; + if (!BIT(m_mode, 3)) + { + if (c < 0x80) + data = m_cgrom[c * 8 + cy]; + else + data = m_display_ram->read_byte(m_cgram_offset + (c & 0x7f) * 8 + cy); + } + else + data = m_display_ram->read_byte(m_cgram_offset + c * 8 + cy); + + for(int cx=0; cxread_byte(m_graphic_home + y * m_number_cols + x); + for(int i=0; iset_md(4); // 8 lines x 40 columns + m_lcdc->set_fs(m_fs << 1); // font size 6x8 or 8x8 } @@ -277,6 +420,12 @@ void lm24014h_device::ram_map(address_map &map) map(0x0000, 0x1fff).ram(); // TC5564AFL-15 } +void lm24014h_device::lcd_palette(palette_device &palette) const +{ + palette.set_pen_color(0, rgb_t(138, 146, 148)); + palette.set_pen_color(1, rgb_t(92, 83, 88)); +} + //------------------------------------------------- // device_add_mconfig - add device-specific @@ -287,6 +436,16 @@ void lm24014h_device::device_add_mconfig(machine_config &config) { T6963C(config, m_lcdc, 0); // XTAL is unknown m_lcdc->set_addrmap(0, &lm24014h_device::ram_map); + + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); + screen.set_refresh_hz(50); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); + screen.set_size(240, 64); + screen.set_visarea(0, 240-1, 0, 64-1); + screen.set_screen_update("lcdc", FUNC(t6963c_device::screen_update)); + screen.set_palette("palette"); + + PALETTE(config, "palette", FUNC(lm24014h_device::lcd_palette), 2); } diff --git a/src/devices/video/t6963c.h b/src/devices/video/t6963c.h index 6eabc1bc4c0..3cc0018f81b 100644 --- a/src/devices/video/t6963c.h +++ b/src/devices/video/t6963c.h @@ -12,6 +12,10 @@ #pragma once +#include "emupal.h" +#include "screen.h" + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -35,6 +39,12 @@ public: u8 read(offs_t offset); void write(offs_t offset, u8 data); + // Display configurations + void set_md(u8 data); // MD0, MD1, MD2, MD3, MDS + void set_fs(u8 data); // FS0, FS1 + + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + static constexpr feature_type unemulated_features() { return feature::GRAPHICS; } protected: @@ -58,6 +68,16 @@ private: u16 m_data; u16 m_adp; auto_mode m_auto_mode; + u16 m_graphic_home; + u16 m_text_home; + u16 m_graphic_area; + u16 m_text_area; + u16 m_cgram_offset; + u8 m_mode; + u8 m_display_mode; + u8 m_font_size; + u8 m_number_cols; + u8 m_number_lines; }; // ======================> lm24014h_device @@ -71,6 +91,7 @@ public: // CPU read/write access u8 read(offs_t offset) { return m_lcdc->read(offset); } void write(offs_t offset, u8 data) { m_lcdc->write(offset, data); } + void set_fs(u8 data) { m_fs = data & 1; } protected: // device-specific overrides @@ -78,12 +99,15 @@ protected: virtual void device_add_mconfig(machine_config &config) override; virtual const tiny_rom_entry *device_rom_region() const override; + void lcd_palette(palette_device &palette) const; + private: // internal configuration void ram_map(address_map &map); // internal LCD controller required_device m_lcdc; + int m_fs; }; // device type declarations diff --git a/src/mame/drivers/tasc.cpp b/src/mame/drivers/tasc.cpp index 671c521eedc..06988487ecb 100644 --- a/src/mame/drivers/tasc.cpp +++ b/src/mame/drivers/tasc.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:hap +// copyright-holders:hap, Sandro Ronco /****************************************************************************** Tasc ChessSystem @@ -27,14 +27,22 @@ references: - https://www.schach-computer.info/wiki/index.php?title=Tasc_SmartBoard - https://www.miclangschach.de/index.php?n=Main.TascR30 -TODO: -- everything +notes: +- holding LEFT+RIGHT on boot load the QC TestMode +- holding UP+DOWN on boot load the TestMode ******************************************************************************/ #include "emu.h" #include "cpu/arm/arm.h" +#include "machine/nvram.h" +#include "machine/smartboard.h" #include "machine/timer.h" +#include "video/t6963c.h" +#include "sound/spkrdev.h" +#include "speaker.h" + +#include "tascr30.lh" namespace { @@ -45,9 +53,14 @@ public: tasc_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), + m_lcd(*this, "lcd"), + m_smartboard(*this, "smartboard"), m_rom(*this, "maincpu"), + m_speaker(*this, "speaker"), m_mainram(*this, "mainram"), - m_disable_bootrom(*this, "disable_bootrom") + m_disable_bootrom(*this, "disable_bootrom"), + m_inputs(*this, "IN.%u", 0U), + m_out_leds(*this, "pled%u", 0U) { } void tasc(machine_config &config); @@ -59,13 +72,19 @@ protected: private: // devices/pointers required_device m_maincpu; + required_device m_lcd; + required_device m_smartboard; required_region_ptr m_rom; + required_device m_speaker; required_shared_ptr m_mainram; required_device m_disable_bootrom; + required_ioport_array<4> m_inputs; + output_finder<2> m_out_leds; void main_map(address_map &map); bool m_bootrom_enabled; + uint32_t m_mux; TIMER_DEVICE_CALLBACK_MEMBER(disable_bootrom) { m_bootrom_enabled = false; } // I/O handlers @@ -76,12 +95,15 @@ private: void tasc_state::machine_start() { + m_out_leds.resolve(); save_item(NAME(m_bootrom_enabled)); + save_item(NAME(m_mux)); } void tasc_state::machine_reset() { m_bootrom_enabled = true; + m_mux = 0; } @@ -96,23 +118,41 @@ READ32_MEMBER(tasc_state::bootrom_r) READ32_MEMBER(tasc_state::p1000_r) { - logerror("p1000_r\n"); - // disconnect bootrom from the bus after next opcode if (m_bootrom_enabled && !m_disable_bootrom->enabled() && !machine().side_effects_disabled()) m_disable_bootrom->adjust(m_maincpu->cycles_to_attotime(5)); - return 0; + uint32_t data = m_smartboard->read(); + + for(int i=0; i<4; i++) + { + if (BIT(m_mux, i)) + data |= (m_inputs[i]->read() << 24); + } + + return data; } WRITE32_MEMBER(tasc_state::p1000_w) { - // similar to risc2500 where msb is select, lsb is data - logerror("p1000_w: %02X %02X\n", data >> 24, data & 0xff); + if (ACCESSING_BITS_24_31) + { + if (BIT(data, 27)) + m_lcd->write(BIT(data, 26), data & 0xff); + + m_smartboard->write((data >> 24) & 0xff); + } + else + { + m_out_leds[0] = BIT(data, 0); + m_out_leds[1] = BIT(data, 1); + m_speaker->level_w((data >> 2) & 3); + } + + COMBINE_DATA(&m_mux); } - /****************************************************************************** Address Maps ******************************************************************************/ @@ -123,7 +163,7 @@ void tasc_state::main_map(address_map &map) map(0x00000000, 0x0000000b).r(FUNC(tasc_state::bootrom_r)); map(0x01000000, 0x01000003).rw(FUNC(tasc_state::p1000_r), FUNC(tasc_state::p1000_w)); map(0x02000000, 0x0203ffff).rom().region("maincpu", 0); - //map(0x03000000, 0x03003fff).ram(); + map(0x03000000, 0x0307ffff).ram().share("nvram").umask32(0x000000ff); } @@ -133,6 +173,25 @@ void tasc_state::main_map(address_map &map) ******************************************************************************/ static INPUT_PORTS_START( tasc ) + PORT_START("IN.0") + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_G) PORT_NAME("PLAY") + PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_LEFT) PORT_NAME("LEFT") + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED) + + PORT_START("IN.1") + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("BACK") + PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("RIGHT") + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED) + + PORT_START("IN.2") + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_M) PORT_NAME("MENU") + PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_UP) PORT_NAME("UP") + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_NAME("Left Clock") + + PORT_START("IN.3") + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER) PORT_NAME("ENTER") + PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_DOWN) PORT_NAME("DOWN") + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) PORT_NAME("Right Clock") INPUT_PORTS_END @@ -150,6 +209,21 @@ void tasc_state::tasc(machine_config &config) m_maincpu->set_periodic_int(FUNC(tasc_state::irq1_line_hold), attotime::from_hz(250)); TIMER(config, "disable_bootrom").configure_generic(FUNC(tasc_state::disable_bootrom)); + + NVRAM(config, "nvram", nvram_device::DEFAULT_NONE); + + LM24014H(config, m_lcd, 0); + m_lcd->set_fs(1); // font size 6x8 + + TASC_SB30(config, m_smartboard, 0); + + config.set_default_layout(layout_tascr30); + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + static const int16_t speaker_levels[3] = { 0, 32767, -32768 }; + SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.75); + m_speaker->set_levels(3, speaker_levels); } @@ -189,4 +263,4 @@ ROM_END ******************************************************************************/ // YEAR NAME PARENT CMP MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS -CONS( 1993, tascr30, 0, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +CONS( 1993, tascr30, 0, 0, tasc, tasc, tasc_state, empty_init, "Tasc", "ChessSystem R30", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) diff --git a/src/mame/layout/tascr30.lay b/src/mame/layout/tascr30.lay new file mode 100644 index 00000000000..180f01fb6f8 --- /dev/null +++ b/src/mame/layout/tascr30.lay @@ -0,0 +1,480 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mame/machine/smartboard.cpp b/src/mame/machine/smartboard.cpp new file mode 100644 index 00000000000..7dd37e2ac54 --- /dev/null +++ b/src/mame/machine/smartboard.cpp @@ -0,0 +1,282 @@ +// license:BSD-3-Clause +// copyright-holders:Sandro Ronco +/****************************************************************************** + + Tasc SmartBoard + + The SmartBoard can detect which piece is present on a specific square, more + info on the technology used in the piece recognition system can be found in + the US patent 5,129,654 + +******************************************************************************/ + +#include "emu.h" +#include "smartboard.h" + +enum +{ + SB30_WHITE_KNIGHT1 = 0, + SB30_WHITE_KNIGHT2 = 1, + SB30_BLACK_KING = 2, + SB30_WHITE_KING = 3, + SB30_BLACK_QUEEN = 4, + SB30_WHITE_QUEEN = 5, + SB30_BLACK_ROOK1 = 6, + SB30_BLACK_ROOK2 = 7, + SB30_WHITE_ROOK1 = 8, + SB30_WHITE_ROOK2 = 9, + SB30_BLACK_BISHOP1 = 10, + SB30_BLACK_BISHOP2 = 11, + SB30_WHITE_BISHOP1 = 12, + SB30_WHITE_BISHOP2 = 13, + SB30_BLACK_KNIGHT1 = 14, + SB30_BLACK_KNIGHT2 = 15, + SB30_WHITE_PAWN1 = 16, + SB30_WHITE_PAWN2 = 17, + SB30_WHITE_PAWN3 = 18, + SB30_WHITE_PAWN4 = 19, + SB30_WHITE_PAWN5 = 20, + SB30_WHITE_PAWN6 = 21, + SB30_WHITE_PAWN7 = 22, + SB30_WHITE_PAWN8 = 23, + SB30_BLACK_PAWN1 = 24, + SB30_BLACK_PAWN2 = 25, + SB30_BLACK_PAWN3 = 26, + SB30_BLACK_PAWN4 = 27, + SB30_BLACK_PAWN5 = 28, + SB30_BLACK_PAWN6 = 29, + SB30_BLACK_PAWN7 = 30, + SB30_BLACK_PAWN8 = 31, +}; + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(TASC_SB30, tasc_sb30_device, "tasc_sb30", "Tasc SmartBoard SB30") + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// tasc_sb30_device - constructor +//------------------------------------------------- + +tasc_sb30_device::tasc_sb30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, TASC_SB30, tag, owner, clock) + , m_board(*this, "board") + , m_out_leds(*this, "led_%u%u", 0U, 0U) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void tasc_sb30_device::device_start() +{ + m_out_leds.resolve(); + m_leds_off_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(tasc_sb30_device::leds_off_cb), this)); + + save_item(NAME(m_data)); + save_item(NAME(m_position)); + save_item(NAME(m_shift)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void tasc_sb30_device::device_reset() +{ + m_data = 0; + m_position = 0; + m_shift = 0; +} + + +//------------------------------------------------- +// device_add_mconfig - add device-specific +// machine configuration +//------------------------------------------------- + +void tasc_sb30_device::device_add_mconfig(machine_config &config) +{ + SENSORBOARD(config, m_board); + m_board->set_type(sensorboard_device::INDUCTIVE); + m_board->set_max_id(32); + m_board->set_mod_enable(false); + m_board->init_cb().set(FUNC(tasc_sb30_device::init_cb)); + m_board->spawn_cb().set(FUNC(tasc_sb30_device::spawn_cb)); +} + + +TIMER_CALLBACK_MEMBER(tasc_sb30_device::leds_off_cb) +{ + for (int y=0; y<9; y++) + for (int x=0; x<9; x++) + m_out_leds[y][x] = 0; +} + +void tasc_sb30_device::init_cb(int state) +{ + m_board->clear_board(); + m_board->write_piece(0, 0, 1 + SB30_WHITE_ROOK1); + m_board->write_piece(7, 0, 1 + SB30_WHITE_ROOK2); + m_board->write_piece(1, 0, 1 + SB30_WHITE_KNIGHT1); + m_board->write_piece(6, 0, 1 + SB30_WHITE_KNIGHT2); + m_board->write_piece(2, 0, 1 + SB30_WHITE_BISHOP1); + m_board->write_piece(5, 0, 1 + SB30_WHITE_BISHOP2); + m_board->write_piece(3, 0, 1 + SB30_WHITE_QUEEN); + m_board->write_piece(4, 0, 1 + SB30_WHITE_KING); + m_board->write_piece(0, 7, 1 + SB30_BLACK_ROOK1); + m_board->write_piece(7, 7, 1 + SB30_BLACK_ROOK2); + m_board->write_piece(1, 7, 1 + SB30_BLACK_KNIGHT1); + m_board->write_piece(6, 7, 1 + SB30_BLACK_KNIGHT2); + m_board->write_piece(2, 7, 1 + SB30_BLACK_BISHOP1); + m_board->write_piece(5, 7, 1 + SB30_BLACK_BISHOP2); + m_board->write_piece(3, 7, 1 + SB30_BLACK_QUEEN); + m_board->write_piece(4, 7, 1 + SB30_BLACK_KING); + + for (int x = 0; x < 8; x++) + { + m_board->write_piece(x, 1, 1 + SB30_WHITE_PAWN1 + x); + m_board->write_piece(x, 6, 1 + SB30_BLACK_PAWN1 + x); + } +} + +bool tasc_sb30_device::piece_available(uint8_t id) +{ + for (int y=0; y<8; y++) + for (int x=0; x<8; x++) + { + if (m_board->read_piece(x, y) == id) + return false; + } + + return true; +} + +uint8_t tasc_sb30_device::spawn_cb(offs_t offset) +{ + int piece_id = -1; + if (offset == 1) + { + for (int p = 0; p < 8; p++) + if (piece_available(1 + SB30_WHITE_PAWN1 + p)) + { + piece_id = SB30_WHITE_PAWN1 + p; + break; + } + } + else if (offset == 7) + { + for (int p = 0; p < 8; p++) + if (piece_available(1 + SB30_BLACK_PAWN1 + p)) + { + piece_id = SB30_BLACK_PAWN1 + p; + break; + } + } + else if (offset == 2) + { + if (piece_available(1 + SB30_WHITE_KNIGHT1)) piece_id = SB30_WHITE_KNIGHT1; + else if (piece_available(1 + SB30_WHITE_KNIGHT2)) piece_id = SB30_WHITE_KNIGHT2; + } + else if (offset == 3) + { + if (piece_available(1 + SB30_WHITE_BISHOP1)) piece_id = SB30_WHITE_BISHOP1; + else if (piece_available(1 + SB30_WHITE_BISHOP2)) piece_id = SB30_WHITE_BISHOP2; + } + else if (offset == 4) + { + if (piece_available(1 + SB30_WHITE_ROOK1)) piece_id = SB30_WHITE_ROOK1; + else if (piece_available(1 + SB30_WHITE_ROOK2)) piece_id = SB30_WHITE_ROOK2; + } + else if (offset == 5) + piece_id = SB30_WHITE_QUEEN; + + else if (offset == 6 && piece_available(1 + SB30_WHITE_KING)) + piece_id = SB30_WHITE_KING; + + else if (offset == 8) + { + if (piece_available(1 + SB30_BLACK_KNIGHT1)) piece_id = SB30_BLACK_KNIGHT1; + else if (piece_available(1 + SB30_BLACK_KNIGHT2)) piece_id = SB30_BLACK_KNIGHT2; + } + else if (offset == 9) + { + if (piece_available(1 + SB30_BLACK_BISHOP1)) piece_id = SB30_BLACK_BISHOP1; + else if (piece_available(1 + SB30_BLACK_BISHOP2)) piece_id = SB30_BLACK_BISHOP2; + } + + else if (offset == 10) + { + if (piece_available(1 + SB30_BLACK_ROOK1)) piece_id = SB30_BLACK_ROOK1; + else if (piece_available(1 + SB30_BLACK_ROOK2)) piece_id = SB30_BLACK_ROOK2; + } + else if (offset == 11) + piece_id = SB30_BLACK_QUEEN; + + else if (offset == 12 && piece_available(1 + SB30_BLACK_KING)) + piece_id = SB30_BLACK_KING; + + if (piece_id >= 0) + return piece_id + 1; + else + return 0; // not available +} + +uint8_t tasc_sb30_device::read() +{ + int x = (m_position & 0x3f) / 8; + int y = (m_position & 0x3f) % 8; + int piece_id = m_board->read_sensor(7 - x, 7 - y); + + // each piece is identified by a single bit in a 32-bit sequence, if multiple bits are active the MSB is used + uint32_t sb30_id = 0; + if (piece_id > 0) + sb30_id = 1UL << (piece_id - 1); + + return BIT(sb30_id, m_shift & 0x1f); +} + + +void tasc_sb30_device::write(uint8_t data) +{ + if (BIT(data, 3) && !BIT(m_data, 3)) + m_position = 0; + + if (BIT(data, 7) && BIT(data, 6) && !BIT(m_data, 6)) + { + out_led(m_position); + m_leds_off_timer->adjust(attotime::from_hz(5)); + } + + if (!BIT(data, 7) && BIT(m_data, 7)) + { + m_position++; + if (m_position & 0x40) + { + m_shift++; + if (m_position & 1) + m_shift = 0; + } + } + + m_data = data; +} + + +void tasc_sb30_device::out_led(int pos) +{ + pos &= 0x3f; + int x = pos / 8; + int y = pos % 8; + m_out_leds[y + 0][x + 0] = 1; + m_out_leds[y + 0][x + 1] = 1; + m_out_leds[y + 1][x + 0] = 1; + m_out_leds[y + 1][x + 1] = 1; +} diff --git a/src/mame/machine/smartboard.h b/src/mame/machine/smartboard.h new file mode 100644 index 00000000000..e42981b7d4d --- /dev/null +++ b/src/mame/machine/smartboard.h @@ -0,0 +1,60 @@ +// license:BSD-3-Clause +// copyright-holders:Sandro Ronco +/********************************************************************** + + Tasc SmartBoard + +*********************************************************************/ + +#ifndef MAME_MACHINE_SMARTBOARD_H +#define MAME_MACHINE_SMARTBOARD_H + +#pragma once + +#include "machine/sensorboard.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> tasc_sb30_device + +class tasc_sb30_device : public device_t +{ +public: + // construction/destruction + tasc_sb30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + uint8_t read(); + void write(uint8_t data); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + +private: + TIMER_CALLBACK_MEMBER(leds_off_cb); + void out_led(int pos); + bool piece_available(uint8_t id); + void init_cb(int state); + uint8_t spawn_cb(offs_t offset); + + required_device m_board; + output_finder<9,9> m_out_leds; + emu_timer * m_leds_off_timer; + uint8_t m_data; + uint8_t m_position; + uint8_t m_shift; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(TASC_SB30, tasc_sb30_device) + + +#endif // MAME_MACHINE_SMARTBOARD_H -- cgit v1.2.3