mirror of
https://github.com/holub/mame
synced 2025-04-24 01:11:11 +03:00
dec_lk201: keyclick [Bavarese]
tll: all irqs (nw)
This commit is contained in:
parent
92a1a8544b
commit
74efa92cda
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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<lk201_device>;
|
||||
|
||||
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 )
|
||||
|
@ -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<class _Object> static devcb_base &set_tx_handler(device_t &device, _Object wr) { return downcast<lk201_device &>(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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user