From 74efa92cda3d41bb2c6cbcc64248f0e13f0b1813 Mon Sep 17 00:00:00 2001 From: cracyc Date: Thu, 23 Jun 2016 14:16:47 -0500 Subject: [PATCH] dec_lk201: keyclick [Bavarese] tll: all irqs (nw) --- src/devices/cpu/t11/t11.cpp | 59 ++++++++------- src/devices/cpu/t11/t11.h | 4 +- src/mame/drivers/atarisy2.cpp | 16 ++-- src/mame/drivers/galgame.cpp | 4 +- src/mame/drivers/vt240.cpp | 28 +------ src/mame/machine/dec_lk201.cpp | 130 +++++++++++++++++++++++++++++---- src/mame/machine/dec_lk201.h | 34 +++++---- 7 files changed, 185 insertions(+), 90 deletions(-) diff --git a/src/devices/cpu/t11/t11.cpp b/src/devices/cpu/t11/t11.cpp index 5db830866ee..86b79d91d04 100644 --- a/src/devices/cpu/t11/t11.cpp +++ b/src/devices/cpu/t11/t11.cpp @@ -191,38 +191,41 @@ static const struct irq_table_entry irq_table[] = { 7<<5, 0x60 } }; -void t11_device::t11_check_irqs() +void t11_device::t11_check_irqs(int prio) { - const struct irq_table_entry *irq = &irq_table[m_irq_state & 15]; - int priority = PSW & 0xe0; + int i, priority = PSW & 0xe0; - /* compare the priority of the interrupt to the PSW */ - if (irq->priority > priority) + for(i = prio; i < 16; i++) { - int vector = irq->vector; - int new_pc, new_psw; - - /* call the callback; if we don't get -1 back, use the return value as our vector */ - int new_vector = standard_irq_callback(m_irq_state & 15); - if (new_vector != -1) - vector = new_vector; - - /* fetch the new PC and PSW from that vector */ - assert((vector & 3) == 0); - new_pc = RWORD(vector); - new_psw = RWORD(vector + 2); - - /* push the old state, set the new one */ - PUSH(PSW); - PUSH(PC); - PCD = new_pc; - PSW = new_psw; - t11_check_irqs(); - - /* count cycles and clear the WAIT flag */ - m_icount -= 114; - m_wait_state = 0; + if(((m_irq_state >> i) & 1) && (irq_table[i].priority > priority)) + break; } + if(i >= 16) + return; + + int vector = irq_table[i].vector; + int new_pc, new_psw; + + /* call the callback; if we don't get -1 back, use the return value as our vector */ + int new_vector = standard_irq_callback(i); + if (new_vector != -1) + vector = new_vector; + + /* fetch the new PC and PSW from that vector */ + assert((vector & 3) == 0); + new_pc = RWORD(vector); + new_psw = RWORD(vector + 2); + + /* push the old state, set the new one */ + PUSH(PSW); + PUSH(PC); + PCD = new_pc; + PSW = new_psw; + t11_check_irqs(i + 1); + + /* count cycles and clear the WAIT flag */ + m_icount -= 114; + m_wait_state = 0; } diff --git a/src/devices/cpu/t11/t11.h b/src/devices/cpu/t11/t11.h index 55d11c9666a..9cb7c80970f 100644 --- a/src/devices/cpu/t11/t11.h +++ b/src/devices/cpu/t11/t11.h @@ -76,7 +76,7 @@ protected: PAIR m_psw; UINT16 m_initial_pc; UINT8 m_wait_state; - UINT8 m_irq_state; + UINT16 m_irq_state; int m_icount; address_space *m_program; direct_read_data *m_direct; @@ -88,7 +88,7 @@ protected: inline void WWORD(int addr, int data); inline void PUSH(int val); inline int POP(); - void t11_check_irqs(); + void t11_check_irqs(int prio = 0); typedef void ( t11_device::*opcode_func )(UINT16 op); static const opcode_func s_opcode_table[65536 >> 3]; diff --git a/src/mame/drivers/atarisy2.cpp b/src/mame/drivers/atarisy2.cpp index 10641c5e4c8..ce0a7a775f0 100644 --- a/src/mame/drivers/atarisy2.cpp +++ b/src/mame/drivers/atarisy2.cpp @@ -144,24 +144,24 @@ void atarisy2_state::update_interrupts() { if (m_video_int_state) - m_maincpu->set_input_line(3, ASSERT_LINE); + m_maincpu->set_input_line(8, ASSERT_LINE); else - m_maincpu->set_input_line(3, CLEAR_LINE); + m_maincpu->set_input_line(8, CLEAR_LINE); if (m_scanline_int_state) + m_maincpu->set_input_line(4, ASSERT_LINE); + else + m_maincpu->set_input_line(4, CLEAR_LINE); + + if (m_p2portwr_state) m_maincpu->set_input_line(2, ASSERT_LINE); else m_maincpu->set_input_line(2, CLEAR_LINE); - if (m_p2portwr_state) + if (m_p2portrd_state) m_maincpu->set_input_line(1, ASSERT_LINE); else m_maincpu->set_input_line(1, CLEAR_LINE); - - if (m_p2portrd_state) - m_maincpu->set_input_line(0, ASSERT_LINE); - else - m_maincpu->set_input_line(0, CLEAR_LINE); } diff --git a/src/mame/drivers/galgame.cpp b/src/mame/drivers/galgame.cpp index 07c9b348eec..f8bb996747a 100644 --- a/src/mame/drivers/galgame.cpp +++ b/src/mame/drivers/galgame.cpp @@ -296,7 +296,7 @@ ADDRESS_MAP_END IRQ_CALLBACK_MEMBER(galaxygame_state::galaxygame_irq_callback) { - device.execute().set_input_line(0, CLEAR_LINE); + device.execute().set_input_line(1, CLEAR_LINE); return 0x40; } @@ -304,7 +304,7 @@ INTERRUPT_GEN_MEMBER(galaxygame_state::galaxygame_irq) { if ( m_clk & 0x40 ) { - device.execute().set_input_line(0, ASSERT_LINE); + device.execute().set_input_line(1, ASSERT_LINE); m_interrupt = 1; } } diff --git a/src/mame/drivers/vt240.cpp b/src/mame/drivers/vt240.cpp index a88e129e0cf..5706a76c7d7 100644 --- a/src/mame/drivers/vt240.cpp +++ b/src/mame/drivers/vt240.cpp @@ -97,10 +97,6 @@ public: DECLARE_READ16_MEMBER(mem_r); DECLARE_WRITE16_MEMBER(mem_w); - //UINT16 m_pcg_addr; - //UINT8 m_pcg_internal_addr; - //UINT8 *m_char_rom; - DECLARE_DRIVER_INIT(vt240); virtual void machine_reset() override; UPD7220_DISPLAY_PIXELS_MEMBER(hgdc_draw); @@ -121,8 +117,8 @@ WRITE_LINE_MEMBER(vt240_state::write_keyboard_clock) WRITE_LINE_MEMBER(vt240_state::i8085_rdy_w) { - //m_maincpu->set_input_line(T11_IRQ1, state ? ASSERT_LINE : CLEAR_LINE); - m_i8085_rdy = !state; + m_maincpu->set_input_line(3, state ? CLEAR_LINE : ASSERT_LINE); + m_i8085_rdy = state; } READ_LINE_MEMBER(vt240_state::i8085_sid_r) @@ -498,24 +494,8 @@ ROM_START( vt240 ) ROM_LOAD( "23-087j5.e182.e183.jed", 0x0000, 0x1000, NO_DUMP ) // PAL16L8ACN; "Logic Unit" Character Pattern Related ROM_END -/* Driver */ -DRIVER_INIT_MEMBER(vt240_state,vt240) -{ - UINT8 *ROM = memregion("charcpu")->base(); - - /* patch T11 check */ - ROM[0x09d] = 0x00; - ROM[0x09e] = 0x00; - ROM[0x09f] = 0x00; - - /* ROM checksum */ - ROM[0x15c] = 0x00; - ROM[0x15d] = 0x00; - ROM[0x15e] = 0x00; -} - /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ -COMP( 1983, vt240, 0, 0, vt240, 0, vt240_state, vt240, "Digital Equipment Corporation", "VT240", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +COMP( 1983, vt240, 0, 0, vt240, 0, driver_device, 0, "Digital Equipment Corporation", "VT240", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) //COMP( 1983, vt241, 0, 0, vt220, vt220, driver_device, 0, "Digital Equipment Corporation", "VT241", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) // NOTE: the only difference between VT240 and VT241 is the latter comes with a VR241 Color monitor, while the former comes with a mono display; the ROMs and operation are identical. -COMP( 1983, mc7105, 0, 0, mc7105, 0, vt240_state, vt240, "Elektronika", "MC7105", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +COMP( 1983, mc7105, 0, 0, mc7105, 0, driver_device, 0, "Elektronika", "MC7105", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) diff --git a/src/mame/machine/dec_lk201.cpp b/src/mame/machine/dec_lk201.cpp index 2164171dce0..353856f928c 100644 --- a/src/mame/machine/dec_lk201.cpp +++ b/src/mame/machine/dec_lk201.cpp @@ -3,8 +3,9 @@ /* DEC LK-201 keyboard Emulation by R. Belmont & M. Burke +with contributions by Cracyc and Karl-Ludwig Deisenhofer (2016) - This is the later "cost-reduced" 6805 version; there's also an 8048 version. +This is the later "cost-reduced" 6805 version with green LEDs; there's also an 8048 version. The LK-201 mechanical elements are described in US Patent 4,467,150 */ @@ -101,7 +102,6 @@ ________|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 C:D - Cursor down (B17) C:U - Cursor up (C17) C:R - Cursor right (B18) - C:L - Cursor left (B16) */ #include "emu.h" @@ -180,7 +180,12 @@ const device_type LK201 = &device_creator; ROM_START( lk201 ) ROM_REGION(0x2000, LK201_CPU_TAG, 0) + +// 23-001s9-00.bin is for the newer LK201 version (green LEDs, Motorola 6805) ROM_LOAD( "23-001s9-00.bin", 0x0000, 0x2000, CRC(be293c51) SHA1(a11ae004d2d6055d7279da3560c3e56610a19fdb) ) + +// 23-004M1 or 23-004M2 are in the older LK201 keyboard with red LEDs (8051) + ROM_END //------------------------------------------------- @@ -206,7 +211,7 @@ static MACHINE_CONFIG_FRAGMENT( lk201 ) MCFG_CPU_PROGRAM_MAP(lk201_map) MCFG_SPEAKER_STANDARD_MONO("mono") - MCFG_SOUND_ADD(LK201_SPK_TAG, BEEP, 3250) + MCFG_SOUND_ADD(LK201_SPK_TAG, BEEP, 2000) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) MACHINE_CONFIG_END @@ -496,6 +501,8 @@ void lk201_device::device_start() { m_count = timer_alloc(1); m_tx_handler.resolve_safe(); + + m_beeper = timer_alloc(2); } @@ -505,6 +512,14 @@ void lk201_device::device_start() void lk201_device::device_reset() { + m_beeper->adjust(attotime::never); + + m_speaker->set_state(0); + m_speaker->set_output_gain(0, 0); + + ddrs[0] = ddrs[1] = ddrs[2] = 0; + ports[0] = ports[1] = ports[2] = 0; + set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1); set_rate(4800); m_count->adjust(attotime::from_hz(1200), 0, attotime::from_hz(1200)); @@ -524,22 +539,35 @@ void lk201_device::device_reset() void lk201_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { - if(id == 1) + switch (id) { - if(m_timer.tcr & 0x40) + case 1: + m_timer.tsr |= TSR_OCFL; + + if ((m_timer.tcr & TCR_OCIE) && (m_timer.tsr & TSR_OCFL)) m_maincpu->set_input_line(M68HC05EG_INT_TIMER, ASSERT_LINE); - m_timer.tsr |= 0x40; - } - else + break; + + case 2: + m_speaker->set_output_gain(0, 0); + m_speaker->set_state(0); + break; + + default: device_serial_interface::device_timer(timer, id, param, ptr); } +} + void lk201_device::rcv_complete() { sci_status |= SCSR_RDRF; update_interrupts(); receive_register_extract(); -// printf("lk201 got %02x\n", get_received_char()); + + int data = get_received_char(); + m_kbd_state = data; +// printf("\nlk201 got %02x\n", m_kbd_state); } void lk201_device::tra_complete() @@ -567,7 +595,21 @@ void lk201_device::update_interrupts() READ8_MEMBER( lk201_device::timer_r ) { + static UINT16 count; + UINT8 ret = m_timer.regs[offset]; + + switch (offset) + { + case 8: // ACRH (high value is stored and reused when reading low) + count = (m_maincpu->total_cycles() / 4) & 0x0000ffff; + ret = count >> 8; + break; + case 9: // ACRL + ret = count & 0x00ff; + break; + } + if(m_timer.tsr) { m_timer.tsr = 0; @@ -578,7 +620,26 @@ READ8_MEMBER( lk201_device::timer_r ) WRITE8_MEMBER( lk201_device::timer_w ) { + static UINT16 count; + static int save_tsr; + m_timer.regs[offset] = data; + + switch (offset) + { + case 4: // OCRH + save_tsr = m_timer.tsr; // prevent crashes in between OCRH / OCRL loads + m_timer.tsr &= (255-TSR_OCFL); // OCFL flag tested for zero in TIMER routine + + count = m_timer.ocrh << 8; // store for later (when LOW is written). + break; + case 5 : // OCRL + count |= m_timer.ocrl; + m_timer.ocrh = count >> 8; + + m_timer.tsr = save_tsr; // restore flags + break; + } } READ8_MEMBER( lk201_device::ddr_r ) @@ -612,13 +673,13 @@ READ8_MEMBER( lk201_device::ports_r ) WRITE8_MEMBER( lk201_device::ports_w ) { UINT8 olddata = ports[offset]; - ports[offset] = data; + ports[offset] = data; // "port writes are independent of DDRC" send_port(space, offset, olddata & ddrs[offset]); +// printf("\nPORT %c write %02x (OLD = %02x) (DDR = %02x) (PC=%x)\n", 'A' + offset, data, olddata, ddrs[offset], m_maincpu->pc()); } void lk201_device::send_port(address_space &space, UINT8 offset, UINT8 olddata) { -// printf("PORT %c write %02x (DDR = %02x) (PC=%x)\n", 'A' + offset, data, ddrs[offset], m_maincpu->pc()); UINT8 porta = ports[0] & ddrs[0]; UINT8 portb = ports[1] & ddrs[1]; UINT8 portc = ports[2] & ddrs[2]; @@ -654,17 +715,60 @@ void lk201_device::send_port(address_space &space, UINT8 offset, UINT8 olddata) if (portc & 0x1) kbd_data = m_kbd16->read(); if (portc & 0x2) kbd_data = m_kbd17->read(); } + // Check for LED update strobe if (((portc & 0x80) == 0) && (olddata & 0x80)) { - // Lower nibble contains the LED values (1 = on, 0 = off) + if(ddrs[2] != 0x00) + { // Lower nibble contains the LED values (1 = on, 0 = off) machine().output().set_value("led_wait" , (led_data & 0x1) == 1); machine().output().set_value("led_compose", (led_data & 0x2) == 2); machine().output().set_value("led_lock" , (led_data & 0x4) == 4); machine().output().set_value("led_hold" , (led_data & 0x8) == 8); } - break; + if (led_data & 0xf0) + { + m_speaker->set_state(1); + // Beeps < 20 ms are clipped. A key click on a LK201 lasts 2 ms... + if(m_kbd_state == LK_CMD_BELL) + m_beeper->adjust(attotime::from_msec(125)); + else + m_beeper->adjust(attotime::from_msec(25)); // see note } + // Upper 4 bits of LED_DATA contain encoded volume info + switch (led_data & 0xf0) + { + case 0xf0: // 8 - (see TABLE 4 in 68HC05xx ROM) + m_speaker->set_output_gain(0, 100.0f); + break; + case 0xd0: // 7 + m_speaker->set_output_gain(0, (100 - (12 * 1)) / 100.0f); + break; + case 0xc0: // 6 + m_speaker->set_output_gain(0, (100 - (12 * 2)) / 100.0f); + break; + case 0x60: // 5 + m_speaker->set_output_gain(0, (100 - (12 * 3)) / 100.0f); + break; + case 0xb0: // 4 + m_speaker->set_output_gain(0, (100 - (12 * 4)) / 100.0f); + break; + case 0xa0: // 3 + m_speaker->set_output_gain(0, (100 - (12 * 5)) / 100.0f); + break; + case 0x30: // 2 + m_speaker->set_output_gain(0, (100 - (12 * 6)) / 100.0f); + break; + case 0x90: // 1 + m_speaker->set_output_gain(0, (100 - (12 * 7)) / 100.0f); + break; + default: + ; + } // switch (volume) + + } // if (update_strobe) + + } // outer switch } READ8_MEMBER( lk201_device::sci_r ) diff --git a/src/mame/machine/dec_lk201.h b/src/mame/machine/dec_lk201.h index 0871f1c3c4e..1df36577b7b 100644 --- a/src/mame/machine/dec_lk201.h +++ b/src/mame/machine/dec_lk201.h @@ -17,14 +17,19 @@ #define LK_CMD_DIS_KEYCLK 0x99 /* disable the keyclick */ #define LK_CMD_ENB_KEYCLK 0x1b /* enable the keyclick - 1st param: volume */ -//#define LK_CMD_DIS_CTLCLK 0xb9 /* disable the Ctrl keyclick */ -//#define LK_CMD_ENB_CTLCLK 0xbb /* enable the Ctrl keyclick */ +#define LK_CMD_DIS_CTLCLK 0xb9 /* disable the Ctrl keyclick */ +#define LK_CMD_ENB_CTLCLK 0xbb /* enable the Ctrl keyclick */ #define LK_CMD_SOUND_CLK 0x9f /* emit a keyclick - 1st param: volume */ #define LK_CMD_DIS_BELL 0xa1 /* disable the bell */ #define LK_CMD_ENB_BELL 0x23 /* enable the bell - 1st param: volume */ #define LK_CMD_BELL 0xa7 /* emit a bell - 1st param: volume */ -#define LK_CMD_POWER_UP 0xfd /* init power-up sequence */ +// TCR - Timer Compare Register +#define TCR_OCIE 0x40 // Bit 6 (output compare IRQ enable) +#define TCR_OLVL 0x01 // Bit 1 (output level) + +// TSR - Timer Status Register +#define TSR_OCFL 0x40 // TSR (68HC05 output compare flag) //************************************************************************** // INTERFACE CONFIGURATION MACROS @@ -45,16 +50,16 @@ public: // construction/destruction lk201_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - DECLARE_READ8_MEMBER( ddr_r ); - DECLARE_WRITE8_MEMBER( ddr_w ); - DECLARE_READ8_MEMBER( ports_r ); - DECLARE_WRITE8_MEMBER( ports_w ); - DECLARE_READ8_MEMBER( sci_r ); - DECLARE_WRITE8_MEMBER( sci_w ); - DECLARE_READ8_MEMBER( spi_r ); - DECLARE_WRITE8_MEMBER( spi_w ); - DECLARE_READ8_MEMBER( timer_r ); - DECLARE_WRITE8_MEMBER( timer_w ); + DECLARE_READ8_MEMBER(ddr_r); + DECLARE_WRITE8_MEMBER(ddr_w); + DECLARE_READ8_MEMBER(ports_r); + DECLARE_WRITE8_MEMBER(ports_w); + DECLARE_READ8_MEMBER(sci_r); + DECLARE_WRITE8_MEMBER(sci_w); + DECLARE_READ8_MEMBER(spi_r); + DECLARE_WRITE8_MEMBER(spi_w); + DECLARE_READ8_MEMBER(timer_r); + DECLARE_WRITE8_MEMBER(timer_w); template static devcb_base &set_tx_handler(device_t &device, _Object wr) { return downcast(device).m_tx_handler.set_callback(wr); } @@ -95,6 +100,7 @@ private: } m_timer; emu_timer *m_count; + emu_timer *m_beeper; UINT8 sci_ctl2; UINT8 sci_status; @@ -128,6 +134,8 @@ private: void send_port(address_space &space, UINT8 offset, UINT8 data); void update_interrupts(); + int m_kbd_state; + devcb_write_line m_tx_handler; };