diff options
Diffstat (limited to 'src/devices/machine/smartboard.cpp')
-rw-r--r-- | src/devices/machine/smartboard.cpp | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/src/devices/machine/smartboard.cpp b/src/devices/machine/smartboard.cpp new file mode 100644 index 00000000000..d699b1306df --- /dev/null +++ b/src/devices/machine/smartboard.cpp @@ -0,0 +1,336 @@ +// license:BSD-3-Clause +// copyright-holders:Sandro Ronco, hap +/****************************************************************************** + +Tasc SmartBoard SB30 (analog) + +Chessboard controller for use with Tasc R30 chesscomputer, or as PC peripheral. + +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 + +SmartBoard I is SB30 (81 LEDs, analog chesspieces) +SmartBoard II is SB20 (64 LEDs, digital chesspieces) +SmartBoard III is SB30 again, but digital + +SB20 and the newer SB30 are not emulated. They're on different hardware, with +embedded CPU to reduce I/O overhead. Note, those are not compatible with old +versions of Tasc R30. + +******************************************************************************/ + +#include "emu.h" +#include "smartboard.h" + +// SB30 chesspiece IDs: 0-31 (+1 for MAME sensorboard_device) +enum +{ + SB30_WHITE_KNIGHT1 = 1, + SB30_WHITE_KNIGHT2, + SB30_BLACK_KING, + SB30_WHITE_KING, + SB30_BLACK_QUEEN, + SB30_WHITE_QUEEN, + SB30_BLACK_ROOK1, + SB30_BLACK_ROOK2, + SB30_WHITE_ROOK1, + SB30_WHITE_ROOK2, + SB30_BLACK_BISHOP1, + SB30_BLACK_BISHOP2, + SB30_WHITE_BISHOP1, + SB30_WHITE_BISHOP2, + SB30_BLACK_KNIGHT1, + SB30_BLACK_KNIGHT2, + SB30_WHITE_PAWN1, + SB30_WHITE_PAWN2, + SB30_WHITE_PAWN3, + SB30_WHITE_PAWN4, + SB30_WHITE_PAWN5, + SB30_WHITE_PAWN6, + SB30_WHITE_PAWN7, + SB30_WHITE_PAWN8, + SB30_BLACK_PAWN1, + SB30_BLACK_PAWN2, + SB30_BLACK_PAWN3, + SB30_BLACK_PAWN4, + SB30_BLACK_PAWN5, + SB30_BLACK_PAWN6, + SB30_BLACK_PAWN7, + SB30_BLACK_PAWN8 +}; + + +DEFINE_DEVICE_TYPE(TASC_SB30, tasc_sb30_device, "tasc_sb30", "Tasc SmartBoard SB30") + +//------------------------------------------------- +// tasc_sb30_device - constructor +//------------------------------------------------- + +tasc_sb30_device::tasc_sb30_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, TASC_SB30, tag, owner, clock) + , m_board(*this, "board") + , m_out_leds(*this, "sb30_led_%u.%u", 0U, 0U) + , m_conf(*this, "CONF") + , m_data_out(*this) + , m_led_out(*this) +{ } + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void tasc_sb30_device::device_start() +{ + if (m_led_out.isunset()) + m_out_leds.resolve(); + + // zerofill + m_data0 = 0; + m_data1 = 0; + m_output = 0; + m_scan_pending = false; + m_pos = 0; + std::fill_n(m_squares, std::size(m_squares), 0); + + // register for savestates + save_item(NAME(m_data0)); + save_item(NAME(m_data1)); + save_item(NAME(m_output)); + save_item(NAME(m_scan_pending)); + save_item(NAME(m_pos)); + save_item(NAME(m_squares)); +} + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +static INPUT_PORTS_START( smartboard ) + PORT_START("CONF") + PORT_CONFNAME( 0x01, 0x00, "Duplicate Piece IDs" ) + PORT_CONFSETTING( 0x00, DEF_STR( No ) ) + PORT_CONFSETTING( 0x01, DEF_STR( Yes ) ) +INPUT_PORTS_END + +ioport_constructor tasc_sb30_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(smartboard); +} + + +//------------------------------------------------- +// 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->init_cb().set(FUNC(tasc_sb30_device::init_cb)); + m_board->spawn_cb().set(FUNC(tasc_sb30_device::spawn_cb)); +} + + +//------------------------------------------------- +// sensorboard_device interface +//------------------------------------------------- + +void tasc_sb30_device::init_cb(u8 data) +{ + m_board->clear_board(); + m_board->write_piece(0, 0, SB30_WHITE_ROOK1); + m_board->write_piece(7, 0, SB30_WHITE_ROOK2); + m_board->write_piece(1, 0, SB30_WHITE_KNIGHT1); + m_board->write_piece(6, 0, SB30_WHITE_KNIGHT2); + m_board->write_piece(2, 0, SB30_WHITE_BISHOP1); + m_board->write_piece(5, 0, SB30_WHITE_BISHOP2); + m_board->write_piece(3, 0, SB30_WHITE_QUEEN); + m_board->write_piece(4, 0, SB30_WHITE_KING); + m_board->write_piece(0, 7, SB30_BLACK_ROOK1); + m_board->write_piece(7, 7, SB30_BLACK_ROOK2); + m_board->write_piece(1, 7, SB30_BLACK_KNIGHT1); + m_board->write_piece(6, 7, SB30_BLACK_KNIGHT2); + m_board->write_piece(2, 7, SB30_BLACK_BISHOP1); + m_board->write_piece(5, 7, SB30_BLACK_BISHOP2); + m_board->write_piece(3, 7, SB30_BLACK_QUEEN); + m_board->write_piece(4, 7, SB30_BLACK_KING); + + for (int x = 0; x < 8; x++) + { + m_board->write_piece(x, 1, SB30_WHITE_PAWN1 + x); + m_board->write_piece(x, 6, SB30_BLACK_PAWN1 + x); + } +} + +bool tasc_sb30_device::piece_available(u8 id) +{ + for (int y = 0; y < 8; y++) + for (int x = 0; x < 8; x++) + { + if (m_board->read_piece(x, y) == id) + return bool(m_conf->read() & 1); + } + + return true; +} + +u8 tasc_sb30_device::spawn_cb(offs_t offset) +{ + int piece_id = 0; + + // While most software works fine as long as color and piece type can be distinguished, + // each individual chesspiece is expected to have a unique id. + switch (offset) + { + case 1+0: + for (int p = 0; p < 8; p++) + if (piece_available(SB30_WHITE_PAWN1 + p)) + { + piece_id = SB30_WHITE_PAWN1 + p; + break; + } + break; + + case 1+6: + for (int p = 0; p < 8; p++) + if (piece_available(SB30_BLACK_PAWN1 + p)) + { + piece_id = SB30_BLACK_PAWN1 + p; + break; + } + break; + + case 2+0: + if (piece_available(SB30_WHITE_KNIGHT1)) + piece_id = SB30_WHITE_KNIGHT1; + else if (piece_available(SB30_WHITE_KNIGHT2)) + piece_id = SB30_WHITE_KNIGHT2; + break; + + case 2+6: + if (piece_available(SB30_BLACK_KNIGHT1)) + piece_id = SB30_BLACK_KNIGHT1; + else if (piece_available(SB30_BLACK_KNIGHT2)) + piece_id = SB30_BLACK_KNIGHT2; + break; + + case 3+0: + if (piece_available(SB30_WHITE_BISHOP1)) + piece_id = SB30_WHITE_BISHOP1; + else if (piece_available(SB30_WHITE_BISHOP2)) + piece_id = SB30_WHITE_BISHOP2; + break; + + case 3+6: + if (piece_available(SB30_BLACK_BISHOP1)) + piece_id = SB30_BLACK_BISHOP1; + else if (piece_available(SB30_BLACK_BISHOP2)) + piece_id = SB30_BLACK_BISHOP2; + break; + + case 4+0: + if (piece_available(SB30_WHITE_ROOK1)) + piece_id = SB30_WHITE_ROOK1; + else if (piece_available(SB30_WHITE_ROOK2)) + piece_id = SB30_WHITE_ROOK2; + break; + + case 4+6: + if (piece_available(SB30_BLACK_ROOK1)) + piece_id = SB30_BLACK_ROOK1; + else if (piece_available(SB30_BLACK_ROOK2)) + piece_id = SB30_BLACK_ROOK2; + break; + + case 5+0: + if (piece_available(SB30_WHITE_QUEEN)) + piece_id = SB30_WHITE_QUEEN; + break; + + case 5+6: + if (piece_available(SB30_BLACK_QUEEN)) + piece_id = SB30_BLACK_QUEEN; + break; + + case 6+0: + if (piece_available(SB30_WHITE_KING)) + piece_id = SB30_WHITE_KING; + break; + + case 6+6: + if (piece_available(SB30_BLACK_KING)) + piece_id = SB30_BLACK_KING; + break; + + default: + break; + } + + return piece_id; +} + + +//------------------------------------------------- +// I/O handlers +//------------------------------------------------- + +void tasc_sb30_device::data0_w(int state) +{ + state = state ? 1 : 0; + + if (!state && m_data0) + { + if (m_scan_pending) + { + for (int i = 0; i < 64; i++) + { + // each piece is identified by a single bit in a 32-bit sequence + int piece_id = m_board->read_sensor(i >> 3 ^ 7, ~i & 7); + m_squares[i] = piece_id ? (1 << (piece_id - 1)) : 0; + } + + m_scan_pending = false; + m_pos = 0; + update_output(); + } + else + { + // output board led(s) + if (m_led_out.isunset()) + m_out_leds[m_pos & 7][m_pos >> 3 & 7] = m_data1; + else + m_led_out(m_pos & 0x3f, m_data1); + } + } + + m_data0 = state; +} + +void tasc_sb30_device::data1_w(int state) +{ + state = state ? 1 : 0; + + // clock position counter + if (!state && m_data1) + { + m_pos++; + + if (m_data0) + m_scan_pending = true; + + update_output(); + } + + m_data1 = state; +} + +void tasc_sb30_device::update_output() +{ + m_output = BIT(m_squares[m_pos & 0x3f], m_pos >> 6 & 0x1f); + m_data_out(m_output); +} |