From 35b59d7921f64cb7e5855a62c933d949fddc1dd3 Mon Sep 17 00:00:00 2001 From: Couriersud Date: Fri, 25 May 2012 23:47:28 +0000 Subject: [PATCH] Added cycle exact potentiometer and keyboard support to pokey device [Couriersud]. The keyboard changes may break some MESS drivers. Please have a look at atari.c and bartop52.c for an example how the new implementation works. --- src/emu/sound/pokey.c | 348 ++++++++++++++++++++---------------- src/emu/sound/pokey.h | 52 ++++-- src/mame/drivers/bartop52.c | 1 + src/mame/includes/atari.h | 4 +- src/mame/machine/atari.c | 159 +++++++--------- 5 files changed, 287 insertions(+), 277 deletions(-) diff --git a/src/emu/sound/pokey.c b/src/emu/sound/pokey.c index 366eba1bbcd..a9afc2d7b8e 100644 --- a/src/emu/sound/pokey.c +++ b/src/emu/sound/pokey.c @@ -13,6 +13,7 @@ * For more details read mame.txt that comes with MAME. * * 4.6: + * [1] http://ploguechipsounds.blogspot.de/2009/10/how-i-recorded-and-decoded-pokeys.html * - changed audio emulation to emulate borrow 3 clock delay and * proper channel reset. New frequency only becomes effective * after the counter hits 0. Emulation also treats counters @@ -71,7 +72,7 @@ #define POKEY_DEFAULT_GAIN (32767/11/4) -#define VERBOSE 0 +#define VERBOSE 1 #define VERBOSE_SOUND 0 #define VERBOSE_TIMER 0 #define VERBOSE_POLY 0 @@ -130,8 +131,8 @@ /* SKSTAT (R/D20F) */ #define SK_FRAME 0x80 /* serial framing error */ -#define SK_OVERRUN 0x40 /* serial overrun error */ -#define SK_KBERR 0x20 /* keyboard overrun error */ +#define SK_KBERR 0x40 /* keyboard overrun error - pokey documentation states *some bit as IRQST */ +#define SK_OVERRUN 0x20 /* serial overrun error - pokey documentation states *some bit as IRQST */ #define SK_SERIN 0x10 /* serial input high */ #define SK_SHIFT 0x08 /* shift key pressed */ #define SK_KEYBD 0x04 /* keyboard key pressed */ @@ -143,6 +144,8 @@ #define SK_FM 0x08 /* FM mode */ #define SK_PADDLE 0x04 /* fast paddle a/d conversion */ #define SK_RESET 0x03 /* reset serial/keyboard interface */ +#define SK_KEYSCAN 0x02 /* key scanning enabled ? */ +#define SK_DEBOUNCE 0x01 /* Debouncing ?*/ #define DIV_64 28 /* divisor for 1.78979 MHz clock to 63.9211 kHz */ #define DIV_15 114 /* divisor for 1.78979 MHz clock to 15.6999 kHz */ @@ -156,7 +159,7 @@ #define CLK_28 1 #define CLK_114 2 -static const int clock_divisors[3] = {1, 28, 114}; +static const int clock_divisors[3] = {1, DIV_64, DIV_15}; @@ -175,9 +178,7 @@ const device_type POKEYN = &device_creator; pokeyn_device::pokeyn_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, POKEYN, "POKEYN", tag, owner, clock), device_sound_interface(mconfig, *this), -#ifdef POKEY_EXEC_INTERFACE device_execute_interface(mconfig, *this), -#endif m_icount(0), m_stream(NULL) { @@ -215,14 +216,9 @@ void pokeyn_device::device_start() * (takes two scanlines) but the result is not as accurate. */ - m_ad_time_fast = (attotime::from_nsec(64000*2/228) * FREQ_17_EXACT) / clock(); - m_ad_time_slow = (attotime::from_nsec(64000 ) * FREQ_17_EXACT) / clock(); - /* initialize the poly counters */ poly_init_4_5(m_poly4, 4, 1, 0); poly_init_4_5(m_poly5, 5, 2, 1); - //poly_init(m_poly9, 9, 8, 1, 0x00180); - //poly_init(m_poly17, 17,16, 1, 0x1c000); /* initialize 9 / 17 arrays */ poly_init_9_17(m_poly9, 9); @@ -244,21 +240,21 @@ void pokeyn_device::device_start() for (i=0; i<8; i++) { - m_ptimer[i] = timer_alloc(2); m_pot_r[i].resolve(m_intf.pot_r[i], *this); } + m_allpot_r.resolve(m_intf.allpot_r, *this); m_serin_r.resolve(m_intf.serin_r, *this); m_serout_w.resolve(m_intf.serout_w, *this); m_interrupt_cb = m_intf.interrupt_cb; + m_kbd_r.resolve(m_intf.kbd_r, *this); m_stream = stream_alloc(0, 1, clock()); -#ifdef POKEY_EXEC_INTERFACE - m_write_timer = timer_alloc(10); /* timer for sync operation */ - timer_alloc(11); -#endif - + timer_alloc(SYNC_WRITE); /* timer for sync operation */ + timer_alloc(SYNC_NOOP); + timer_alloc(SYNC_POT); + timer_alloc(SYNC_SET_IRQST); for (i=0; ielapsed().as_double()))); - m_ALLPOT &= ~(1 << pot); /* set the enabled timer irq status bits */ - - } - else if (id == 3) + switch (id) { + case 3: /* serout_ready_cb */ if( m_IRQEN & IRQ_SEROR ) { @@ -349,9 +337,8 @@ void pokeyn_device::device_timer(emu_timer &timer, device_timer_id id, int param if( m_interrupt_cb ) (m_interrupt_cb)(this, IRQ_SEROR); } - } - else if (id == 4) - { + break; + case 4: /* serout_complete */ if( m_IRQEN & IRQ_SEROC ) { @@ -359,9 +346,8 @@ void pokeyn_device::device_timer(emu_timer &timer, device_timer_id id, int param if( m_interrupt_cb ) (m_interrupt_cb)(this, IRQ_SEROC); } - } - else if (id == 5) - { + break; + case 5: /* serin_ready */ if( m_IRQEN & IRQ_SERIN ) { @@ -371,22 +357,29 @@ void pokeyn_device::device_timer(emu_timer &timer, device_timer_id id, int param if( m_interrupt_cb ) (m_interrupt_cb)(this, IRQ_SERIN); } - } - else if (id == 10) - { - offs_t offset = (param >> 8) & 0xff; - UINT8 data = param & 0xff; - write_internal(offset, data); - } - else if (id == 11) - { + break; + case SYNC_WRITE: + { + offs_t offset = (param >> 8) & 0xff; + UINT8 data = param & 0xff; + write_internal(offset, data); + } + break; + case SYNC_NOOP: /* do nothing, caused by a forced resync */ - } - else + break; + case SYNC_POT: + logerror("x %02x \n", (param & 0x20)); + m_ALLPOT |= (param & 0xff); + break; + case SYNC_SET_IRQST: + m_IRQST |= (param & 0xff); + break; + default: assert_always(FALSE, "Unknown id in pokey_device::device_timer"); + } } -#ifdef POKEY_EXEC_INTERFACE void pokeyn_device::execute_run() { //bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0); @@ -412,8 +405,6 @@ void pokeyn_device::device_timer(emu_timer &timer, device_timer_id id, int param } while (m_icount > 0); } - //{ m_icount = 0; } //printf("execute: %d\n", m_icount); m_icount = 0; } -#endif //------------------------------------------------- @@ -421,6 +412,111 @@ void pokeyn_device::device_timer(emu_timer &timer, device_timer_id id, int param // clock cycle. //------------------------------------------------- +void pokeyn_device::step_keyboard() +{ + if (++m_kbd_cnt > 63) + m_kbd_cnt = 0; + if (!m_kbd_r.isnull()) { + UINT8 ret = m_kbd_r(m_kbd_cnt); + switch (m_kbd_cnt) + { + case POK_KEY_BREAK: + if (ret & 2) + { + /* check if the break IRQ is enabled */ + if( m_IRQEN & IRQ_BREAK ) + { + /* set break IRQ status and call back the interrupt handler */ + m_IRQST |= IRQ_BREAK; + if( m_interrupt_cb ) + (*m_interrupt_cb)(this, IRQ_BREAK); + } + } + break; + case POK_KEY_SHIFT: + m_kbd_latch = (m_kbd_latch & 0xbf) | ((ret & 2) << 5); + if( m_kbd_latch & 0x40 ) + m_SKSTAT |= SK_SHIFT; + else + m_SKSTAT &= ~SK_SHIFT; + /* FIXME: sync ? */ + break; + case POK_KEY_CTRL: + m_kbd_latch = (m_kbd_latch & 0x7f) | ((ret & 2) << 6); + break; + } + switch (m_kbd_state) + { + case 0: /* waiting for key */ + if (ret & 1) + { + m_kbd_latch = (m_kbd_latch & 0xc0) | m_kbd_cnt; + m_kbd_state++; + } + break; + case 1: /* waiting for key confirmation */ + if ((m_kbd_latch & 0x3f) == m_kbd_cnt) + { + if (ret & 1) + { + m_KBCODE = m_kbd_latch; + m_SKSTAT |= SK_KEYBD; + if( m_IRQEN & IRQ_KEYBD ) + { + /* last interrupt not acknowledged ? */ + if( m_IRQST & IRQ_KEYBD ) + m_SKSTAT |= SK_KBERR; + m_IRQST |= IRQ_KEYBD; + if( m_interrupt_cb ) + (*m_interrupt_cb)(this, IRQ_KEYBD); + } + m_kbd_state++; + } + else + m_kbd_state = 0; + } + break; + case 2: /* waiting for release */ + if ((m_kbd_latch & 0x3f) == m_kbd_cnt) + { + if ((ret & 1)==0) + m_kbd_state++; + else + m_SKSTAT |= SK_KEYBD; + } + break; + case 3: + if ((m_kbd_latch & 0x3f) == m_kbd_cnt) + { + if (ret & 1) + m_kbd_state = 2; + else + { + m_SKSTAT &= ~SK_KEYBD; + m_kbd_state = 0; + } + } + break; + } + } +} + +void pokeyn_device::step_pot() +{ + int pot; + UINT8 upd = 0; + m_pot_counter++; + for (pot = 0; pot < 8; pot++) + { + if ((m_POTx[pot] 0 ) { -#ifndef POKEY_EXEC_INTERFACE - m_output = step_one_clock(); -#endif /* store sum of output signals into the buffer */ *buffer++ = (m_output > 0x7fff) ? 0x7fff : m_output; @@ -573,33 +674,24 @@ UINT8 pokeyn_device::read(offs_t offset) { int data = 0, pot; - synchronize(11); /* force resync */ + synchronize(SYNC_NOOP); /* force resync */ + switch (offset & 15) { case POT0_C: case POT1_C: case POT2_C: case POT3_C: case POT4_C: case POT5_C: case POT6_C: case POT7_C: pot = offset & 7; - if( !m_pot_r[pot].isnull() ) + if( m_ALLPOT & (1 << pot) ) { - /* - * If the conversion is not yet finished (ptimer running), - * get the current value by the linear interpolation of - * the final value using the elapsed time. - */ - if( m_ALLPOT & (1 << pot) ) - { - data = m_ptimer[pot]->elapsed().attoseconds / ((m_SKCTL & SK_PADDLE) ? m_ad_time_fast : m_ad_time_slow).attoseconds; - LOG(("POKEY '%s' read POT%d (interpolated) $%02x\n", tag(), pot, data)); - } - else - { - data = m_POTx[pot]; - LOG(("POKEY '%s' read POT%d (final value) $%02x\n", tag(), pot, data)); - } + /* we have a value measured */ + data = m_POTx[pot]; + LOG(("POKEY '%s' read POT%d (final value) $%02x\n", tag(), pot, data)); } else - logerror("%s: warning - read '%s' POT%d\n", machine().describe_context(), tag(), pot); - //data = 0; //if (pot == 7) data = 1; + { + data = m_pot_counter; + LOG(("POKEY '%s' read POT%d (interpolated) $%02x\n", tag(), pot, data)); + } break; case ALLPOT_C: @@ -619,10 +711,9 @@ UINT8 pokeyn_device::read(offs_t offset) } else { - data = m_ALLPOT; + data = m_ALLPOT ^ 0xff; LOG(("POKEY '%s' ALLPOT internal $%02x\n", tag(), data)); } - //data = 127; break; case KBCODE_C: @@ -633,13 +724,13 @@ UINT8 pokeyn_device::read(offs_t offset) if( m_AUDCTL & POLY9 ) { data = m_poly9[m_p9] & 0xff; - synchronize(11); /* force resync */ + synchronize(SYNC_NOOP); /* force resync */ LOG_RAND(("POKEY '%s' rand9[$%05x]: $%02x\n", tag(), m_p9, data)); } else { data = (m_poly17[m_p17] >> 8) & 0xff; - synchronize(11); /* force resync */ + synchronize(SYNC_NOOP); /* force resync */ LOG_RAND(("POKEY '%s' rand17[$%05x]: $%02x\n", tag(), m_p17, data)); } break; @@ -680,13 +771,7 @@ UINT8 pokeyn_device::read(offs_t offset) void pokeyn_device::write(offs_t offset, UINT8 data) { -#ifdef POKEY_EXEC_INTERFACE - synchronize(10, (offset<<8) | data); -#else - m_stream->update(); - write_internal(offset, data); -#endif - + synchronize(SYNC_WRITE, (offset<<8) | data); } WRITE8_MEMBER( pokeyn_device::write ) @@ -850,109 +935,57 @@ void pokeyn_device::serin_ready(int after) timer_set(m_clock_period * after, 5, 0); } -void pokeyn_device::break_w(int shift) -{ - if( shift ) /* shift code ? */ - m_SKSTAT |= SK_SHIFT; - else - m_SKSTAT &= ~SK_SHIFT; - /* check if the break IRQ is enabled */ - if( m_IRQEN & IRQ_BREAK ) - { - /* set break IRQ status and call back the interrupt handler */ - m_IRQST |= IRQ_BREAK; - if( m_interrupt_cb ) - (*m_interrupt_cb)(this, IRQ_BREAK); - } -} - -void pokeyn_device::kbcode_w(int kbcode, int make) -{ - /* make code ? */ - if( make ) - { - m_KBCODE = kbcode; - m_SKSTAT |= SK_KEYBD; - if( kbcode & 0x40 ) /* shift code ? */ - m_SKSTAT |= SK_SHIFT; - else - m_SKSTAT &= ~SK_SHIFT; - - if( m_IRQEN & IRQ_KEYBD ) - { - /* last interrupt not acknowledged ? */ - if( m_IRQST & IRQ_KEYBD ) - m_SKSTAT |= SK_KBERR; - m_IRQST |= IRQ_KEYBD; - if( m_interrupt_cb ) - (*m_interrupt_cb)(this, IRQ_KEYBD); - } - } - else - { - m_KBCODE = kbcode; - m_SKSTAT &= ~SK_KEYBD; - } -} - - - //------------------------------------------------- // private stuff //------------------------------------------------- inline void pokeyn_device::process_channel(int ch) { - int toggle = 0; - - if( (m_channel[ch].m_AUDC & NOTPOLY5) || (m_poly5[m_p5] & 1) ) + if ((m_channel[ch].m_AUDC & NOTPOLY5) || (m_poly5[m_p5] & 1)) { - if( m_channel[ch].m_AUDC & PURE ) - toggle = 1; + if (m_channel[ch].m_AUDC & PURE) + m_channel[ch].m_output ^= 1; + else if (m_channel[ch].m_AUDC & POLY4) + m_channel[ch].m_output = (m_poly4[m_p4] & 1); + else if (m_AUDCTL & POLY9) + m_channel[ch].m_output = (m_poly9[m_p9] & 1); else - if( m_channel[ch].m_AUDC & POLY4 ) - toggle = m_channel[ch].m_output == !(m_poly4[m_p4] & 1); - else - if( m_AUDCTL & POLY9 ) - toggle = m_channel[ch].m_output == !(m_poly9[m_p9] & 1); - else - toggle = m_channel[ch].m_output == !(m_poly17[m_p17] & 1); - } - if( toggle ) - { - m_channel[ch].m_output ^= 1; + m_channel[ch].m_output = (m_poly17[m_p17] & 1); } } - - - void pokeyn_device::pokey_potgo(void) { int pot; LOG(("POKEY #%p pokey_potgo\n", this)); - m_ALLPOT = 0xff; + m_ALLPOT = 0x00; + m_pot_counter = 0; for( pot = 0; pot < 8; pot++ ) { - m_POTx[pot] = 0xff; + m_POTx[pot] = 228; if( !m_pot_r[pot].isnull() ) { int r = m_pot_r[pot](pot); LOG(("POKEY %s pot_r(%d) returned $%02x\n", tag(), pot, r)); - if( r != -1 ) + if (r >= 228) { - if (r > 228) - r = 228; - - /* final value */ - m_POTx[pot] = r; - m_ptimer[pot]->adjust(((m_SKCTL & SK_PADDLE) ? m_ad_time_fast : m_ad_time_slow) * r, pot); + r = 228; } + if (r == 0) + { + /* immediately set the ready - bit of m_ALLPOT + * In this case, most likely no capacitor is connected + */ + m_ALLPOT |= (1< pokey_device class pokeyn_device : public device_t, - public device_sound_interface -#ifdef POKEY_EXEC_INTERFACE - ,public device_execute_interface -#endif + public device_sound_interface, + public device_execute_interface, + public device_execute_state { public: + enum + { + POK_KEY_BREAK = 0x30, + POK_KEY_SHIFT = 0x20, + POK_KEY_CTRL = 0x00 + }; + enum { /* POKEY WRITE LOGICALS */ @@ -103,6 +110,14 @@ public: SKSTAT_C = 0x0F }; + enum /* sync-operations */ + { + SYNC_NOOP = 11, + SYNC_SET_IRQST = 12, + SYNC_POT = 13, + SYNC_WRITE = 14 + }; + // construction/destruction pokeyn_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); @@ -113,8 +128,6 @@ public: void write(offs_t offset, UINT8 data); void serin_ready(int after); - void break_w(int shift); - void kbcode_w(int kbcode, int make); protected: // device-level overrides @@ -127,9 +140,7 @@ protected: // device_sound_interface overrides virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); -#ifdef POKEY_EXEC_INTERFACE virtual void execute_run(); -#endif // configuration state pokey_interface m_intf; @@ -153,6 +164,7 @@ private: UINT32 m_volume; /* channel volume - derived */ UINT8 m_output; /* channel output signal (1 active, 0 inactive) */ UINT8 m_filter_sample; /* high-pass filter sample */ + UINT8 m_div2; /* division by 2 */ inline void sample(void) { m_filter_sample = m_output; } inline void reset_channel(void) { m_counter = m_AUDF ^ 0xff; } @@ -165,7 +177,8 @@ private: m_borrow_cnt = 3; if (m_parent->m_IRQEN & m_INTMask) { - m_parent->m_IRQST |= m_INTMask; + /* Exposed state has changed: This should only be updated after a resync ... */ + m_parent->synchronize(SYNC_SET_IRQST, m_INTMask); } } } @@ -184,6 +197,8 @@ private: static const int POKEY_CHANNELS = 4; UINT32 step_one_clock(); + void step_keyboard(); + void step_pot(); void poly_init_4_5(UINT32 *poly, int size, int xorbit, int invert); void poly_init_9_17(UINT32 *poly, int size); @@ -208,16 +223,12 @@ private: UINT32 m_p17; /* poly17 index */ UINT32 m_clockmult; /* clock multiplier */ - emu_timer *m_ptimer[8]; /* pot timers */ - -#ifdef POKEY_EXEC_INTERFACE - emu_timer *m_write_timer; /* timer for sync operation */ -#endif - devcb_resolved_read8 m_pot_r[8]; devcb_resolved_read8 m_allpot_r; devcb_resolved_read8 m_serin_r; devcb_resolved_write8 m_serout_w; + devcb_resolved_read8 m_kbd_r; + void (*m_interrupt_cb)(pokeyn_device *device, int mask); UINT8 m_POTx[8]; /* POTx (R/D200-D207) */ @@ -231,9 +242,12 @@ private: UINT8 m_SKSTAT; /* SKSTAT (R/D20F) */ UINT8 m_SKCTL; /* SKCTL (W/D20F) */ + UINT8 m_pot_counter; + UINT8 m_kbd_cnt; + UINT8 m_kbd_latch; + UINT8 m_kbd_state; + attotime m_clock_period; - attotime m_ad_time_fast; - attotime m_ad_time_slow; UINT32 m_poly4[0x0f]; UINT32 m_poly5[0x1f]; diff --git a/src/mame/drivers/bartop52.c b/src/mame/drivers/bartop52.c index 76ceaeaaa27..bbf22337757 100644 --- a/src/mame/drivers/bartop52.c +++ b/src/mame/drivers/bartop52.c @@ -114,6 +114,7 @@ static const pokey_interface atari_pokey_interface = DEVCB_NULL, DEVCB_NULL, atari_interrupt_cb, + DEVCB_HANDLER(atari_a5200_keypads) }; static MACHINE_CONFIG_START( a5200, bartop52_state ) diff --git a/src/mame/includes/atari.h b/src/mame/includes/atari.h index af682e843e1..27e32165b4c 100644 --- a/src/mame/includes/atari.h +++ b/src/mame/includes/atari.h @@ -33,8 +33,8 @@ MACHINE_START( atarixl ); void atari_interrupt_cb(pokeyn_device *device, int mask); -void a800_handle_keyboard(running_machine &machine); -void a5200_handle_keypads(running_machine &machine); +READ8_DEVICE_HANDLER(atari_a800_keyboard); +READ8_DEVICE_HANDLER(atari_a5200_keypads); /* video */ diff --git a/src/mame/machine/atari.c b/src/mame/machine/atari.c index 175763420ea..fa7d3580c86 100644 --- a/src/mame/machine/atari.c +++ b/src/mame/machine/atari.c @@ -16,9 +16,9 @@ #include "sound/dac.h" #include "video/gtia.h" -#define VERBOSE_POKEY 0 -#define VERBOSE_SERIAL 0 -#define VERBOSE_TIMERS 0 +#define VERBOSE_POKEY 1 +#define VERBOSE_SERIAL 1 +#define VERBOSE_TIMERS 1 static void a600xl_mmu(running_machine &machine, UINT8 new_mmu); @@ -155,62 +155,43 @@ void a600xl_mmu(running_machine &machine, UINT8 new_mmu) **************************************************************/ -static int atari_last; - -void a800_handle_keyboard(running_machine &machine) +READ8_DEVICE_HANDLER(atari_a800_keyboard) { - pokeyn_device *pokey = machine.device("pokey"); - int atari_code, count, ipt, i; + int ipt; static const char *const tag[] = { "keyboard_0", "keyboard_1", "keyboard_2", "keyboard_3", "keyboard_4", "keyboard_5", "keyboard_6", "keyboard_7" }; + UINT8 ret = 0x00; - /* check keyboard */ - for( i = 0; i < 8; i++ ) + /* decode special */ + switch (offset) { - ipt = machine.root_device().ioport(tag[i])->read_safe(0); - - if( ipt ) - { - count = 0; - while(ipt / 2) - { - ipt = ipt/2; - count++; - } - - atari_code = i*8 + count; - - /* SHIFT */ - if(machine.root_device().ioport("fake")->read_safe(0) & 0x01) - atari_code |= 0x40; - - /* CTRL */ - if(machine.root_device().ioport("fake")->read_safe(0) & 0x02) - atari_code |= 0x80; - - if( atari_code != AKEY_NONE ) - { - if( atari_code == atari_last ) - return; - atari_last = atari_code; - - if( (atari_code & 0x3f) == AKEY_BREAK ) - { - pokey->break_w(atari_code & 0x40); - return; - } - - pokey->kbcode_w(atari_code, 1); - return; - } - } - + case pokeyn_device::POK_KEY_BREAK: + /* special case ... */ + ret |= ((device->machine().root_device().ioport(tag[0])->read_safe(0) & 0x04) ? 0x02 : 0x00); + break; + case pokeyn_device::POK_KEY_CTRL: + /* CTRL */ + ret |= ((device->machine().root_device().ioport("fake")->read_safe(0) & 0x02) ? 0x02 : 0x00); + break; + case pokeyn_device::POK_KEY_SHIFT: + /* SHIFT */ + ret |= ((device->machine().root_device().ioport("fake")->read_safe(0) & 0x01) ? 0x02 : 0x00); + break; } - /* remove key pressed status bit from skstat */ - pokey->kbcode_w(AKEY_NONE, 0); - atari_last = AKEY_NONE; + + /* return on BREAK key now! */ + if (offset == AKEY_BREAK || offset == AKEY_NONE) + return ret; + + /* decode regular key */ + ipt = device->machine().root_device().ioport(tag[offset >> 3])->read_safe(0); + + if (ipt & (1 << (offset & 0x07))) + ret |= 0x01; + + return ret; } /************************************************************** @@ -242,60 +223,41 @@ void a800_handle_keyboard(running_machine &machine) **************************************************************/ -void a5200_handle_keypads(running_machine &machine) +READ8_DEVICE_HANDLER(atari_a5200_keypads) { - pokeyn_device *pokey = downcast(machine.device("pokey")); - int atari_code, count, ipt, i; + int ipt; static const char *const tag[] = { "keypad_0", "keypad_1", "keypad_2", "keypad_3" }; + UINT8 ret = 0x00; - /* check keypad */ - for( i = 0; i < 4; i++ ) + /* decode special */ + switch (offset) { - ipt = machine.root_device().ioport(tag[i])->read_safe(0); - - if( ipt ) - { - count = 0; - while(ipt / 2) - { - ipt = ipt/2; - count++; - } - - atari_code = i*4 + count; - - if( atari_code == atari_last ) - return; - atari_last = atari_code; - - if( atari_code == 0 ) - { - pokey->break_w(atari_code & 0x40); - return; - } - - pokey->kbcode_w((atari_code << 1) | 0x21, 1); - return; - } - + case pokeyn_device::POK_KEY_BREAK: + /* special case ... */ + ret |= ((device->machine().root_device().ioport(tag[0])->read_safe(0) & 0x01) ? 0x02 : 0x00); + break; + case pokeyn_device::POK_KEY_CTRL: + case pokeyn_device::POK_KEY_SHIFT: + break; } - /* check top button */ - if ((machine.root_device().ioport("djoy_b")->read() & 0x10) == 0) - { - if (atari_last == 0xfe) - return; - pokey->kbcode_w(0x61, 1); - //pokey_break_w(pokey, 0x40); - atari_last = 0xfe; - return; - } - else if (atari_last == 0xfe) - pokey->kbcode_w(0x21, 1); + /* decode regular key */ + /* if kr5 and kr0 not set just return */ + if ((offset & 0x21) != 0x21) + return ret; - /* remove key pressed status bit from skstat */ - pokey->kbcode_w(0xff, 0); - atari_last = 0xff; + offset = (offset >> 1) & 0x0f; + + /* return on BREAK key now! */ + if (offset == 0) + return ret; + + ipt = device->machine().root_device().ioport(tag[offset >> 2])->read_safe(0); + + if (ipt & (1 <<(offset & 0x03))) + ret |= 0x01; + + return ret; } @@ -310,7 +272,6 @@ static void pokey_reset(running_machine &machine) { pokeyn_device *pokey = downcast(machine.device("pokey")); pokey->write(15,0); - atari_last = 0xff; }