summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/e0c6200/e0c6s46.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/e0c6200/e0c6s46.c')
-rw-r--r--src/emu/cpu/e0c6200/e0c6s46.c102
1 files changed, 51 insertions, 51 deletions
diff --git a/src/emu/cpu/e0c6200/e0c6s46.c b/src/emu/cpu/e0c6200/e0c6s46.c
index 55a0127db7b..be131a1e5dc 100644
--- a/src/emu/cpu/e0c6200/e0c6s46.c
+++ b/src/emu/cpu/e0c6200/e0c6s46.c
@@ -4,7 +4,7 @@
Seiko Epson E0C6S46 MCU
QFP5-128pin, see manual for pinout
-
+
TODO:
- OSC3
- K input interrupts
@@ -64,7 +64,7 @@ e0c6s46_device::e0c6s46_device(const machine_config &mconfig, const char *tag, d
void e0c6s46_device::device_start()
{
e0c6200_cpu_device::device_start();
-
+
// find ports
m_write_r0.resolve_safe();
m_write_r1.resolve_safe();
@@ -88,7 +88,7 @@ void e0c6s46_device::device_start()
m_prgtimer_handle->adjust(attotime::never);
m_buzzer_handle = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(e0c6s46_device::buzzer_cb), this));
m_buzzer_handle->adjust(attotime::never);
-
+
// zerofill
memset(m_port_r, 0x0, sizeof(m_port_r));
m_r_dir = 0;
@@ -97,7 +97,7 @@ void e0c6s46_device::device_start()
m_p_pullup = 0;
memset(m_port_k, 0xf, sizeof(m_port_k));
m_dfk0 = 0xf;
-
+
memset(m_irqflag, 0, sizeof(m_irqflag));
memset(m_irqmask, 0, sizeof(m_irqmask));
m_osc = 0;
@@ -114,7 +114,7 @@ void e0c6s46_device::device_start()
m_swl_slice = 0;
m_swl_count = 0;
m_swh_count = 0;
-
+
m_prgtimer_select = 0;
m_prgtimer_on = 0;
m_prgtimer_src_pulse = 0;
@@ -130,7 +130,7 @@ void e0c6s46_device::device_start()
m_bz_1shot_running = false;
m_bz_1shot_count = 0;
m_bz_pulse = 0;
-
+
// register for savestates
save_item(NAME(m_port_r));
save_item(NAME(m_r_dir));
@@ -139,7 +139,7 @@ void e0c6s46_device::device_start()
save_item(NAME(m_p_pullup));
save_item(NAME(m_port_k));
save_item(NAME(m_dfk0));
-
+
save_item(NAME(m_irqflag));
save_item(NAME(m_irqmask));
save_item(NAME(m_osc));
@@ -187,7 +187,7 @@ void e0c6s46_device::device_reset()
// reset interrupts
memset(m_irqflag, 0, sizeof(m_irqflag));
memset(m_irqmask, 0, sizeof(m_irqmask));
-
+
// reset other i/o
m_data->write_byte(0xf41, 0xf);
m_data->write_byte(0xf54, 0xf);
@@ -205,7 +205,7 @@ void e0c6s46_device::device_reset()
m_data->write_byte(0xf7b, 0x0);
m_data->write_byte(0xf7d, 0x0);
m_data->write_byte(0xf7e, 0x0);
-
+
// reset ports
for (int i = 0; i < 5; i++)
write_r(i, m_port_r[i]);
@@ -224,7 +224,7 @@ void e0c6s46_device::execute_one()
// E0C6S46 has no support for SLP opcode
if (m_op == 0xff9)
return;
-
+
e0c6200_cpu_device::execute_one();
}
@@ -255,7 +255,7 @@ bool e0c6s46_device::check_interrupt()
m_irq_vector = 2*pri + 2;
int reg = priorder[pri];
m_irq_id = reg;
-
+
switch (reg)
{
// other: mask vs flag
@@ -265,7 +265,7 @@ bool e0c6s46_device::check_interrupt()
break;
}
}
-
+
return false;
}
@@ -278,7 +278,7 @@ void e0c6s46_device::execute_set_input(int line, int state)
state = (state) ? 1 : 0;
int port = line >> 2 & 1;
UINT8 bit = 1 << (line & 3);
-
+
m_port_k[port] = (m_port_k[port] & ~bit) | (state ? bit : 0);
}
@@ -299,14 +299,14 @@ void e0c6s46_device::write_r(UINT8 port, UINT8 data)
UINT8 out = data;
if (port < 4 && !(m_r_dir >> port & 1))
out = 0xf;
-
+
switch (port)
{
case 0: m_write_r0(port, out, 0xff); break;
case 1: m_write_r1(port, out, 0xff); break;
case 2: m_write_r2(port, out, 0xff); break;
case 3: m_write_r3(port, out, 0xff); break; // TODO: R33 PTCLK/_SRDY
-
+
// R4x: special output
case 4:
// d3: buzzer on: direct output or 1-shot output
@@ -336,7 +336,7 @@ void e0c6s46_device::write_p(UINT8 port, UINT8 data)
{
data &= 0xf;
m_port_p[port] = data;
-
+
// don't output if port direction is set to input
if (!(m_p_dir >> port & 1))
return;
@@ -355,7 +355,7 @@ UINT8 e0c6s46_device::read_p(UINT8 port)
// return written value if port direction is set to output
if (m_p_dir >> port & 1)
return m_port_p[port];
-
+
switch (port)
{
case 0: return m_read_p0(port, 0xff);
@@ -363,7 +363,7 @@ UINT8 e0c6s46_device::read_p(UINT8 port)
case 2: return m_read_p2(port, 0xff);
case 3: return m_read_p3(port, 0xff);
}
-
+
return 0;
}
@@ -412,7 +412,7 @@ void e0c6s46_device::clock_watchdog()
void e0c6s46_device::clock_clktimer()
{
m_clktimer_count++;
-
+
// irq on falling edge of 32, 8, 2, 1hz
UINT8 flag = 0;
if ((m_clktimer_count & 0x07) == 0)
@@ -427,7 +427,7 @@ void e0c6s46_device::clock_clktimer()
m_irqflag[IRQREG_CLKTIMER] |= flag;
if (m_irqflag[IRQREG_CLKTIMER] & m_irqmask[IRQREG_CLKTIMER])
m_possible_irq = true;
-
+
// 1hz falling edge also clocks the watchdog timer
if (m_clktimer_count == 0)
clock_watchdog();
@@ -439,14 +439,14 @@ void e0c6s46_device::clock_clktimer()
void e0c6s46_device::clock_stopwatch()
{
m_swl_slice++;
-
+
// 1 slice is 3 ticks(256hz) on even and 2 ticks on uneven counts,
// but from count 1 to 2 it's 3 ticks, 6 out of 100 times, to make
// exactly 26/256hz * 6 + 25/256hz * 4 = 1 second
int swl_next = 3 - (m_swl_count & 1);
if (m_swl_count == 1 && !(m_swh_count >> 1 & 1))
swl_next = 3;
-
+
if (m_swl_slice == swl_next)
{
m_swl_slice = 0;
@@ -477,7 +477,7 @@ void e0c6s46_device::clock_prgtimer()
m_irqflag[IRQREG_PRGTIMER] |= 1;
if (m_irqflag[IRQREG_PRGTIMER] & m_irqmask[IRQREG_PRGTIMER])
m_possible_irq = true;
-
+
// note: a reload of 0 indicates a 256-counter
m_prgtimer_count = m_prgtimer_reload;
}
@@ -489,7 +489,7 @@ bool e0c6s46_device::prgtimer_reset_prescaler()
UINT8 sel = m_prgtimer_select & 7;
if (sel >= 2)
m_prgtimer_handle->adjust(attotime::from_ticks(2 << (sel ^ 7), unscaled_clock()));
-
+
return (sel >= 2);
}
@@ -501,7 +501,7 @@ TIMER_CALLBACK_MEMBER(e0c6s46_device::prgtimer_cb)
m_prgtimer_src_pulse ^= 1;
m_prgtimer_cur_pulse = m_prgtimer_src_pulse | (m_prgtimer_on ^ 1);
-
+
// clock prgtimer on falling edge of pulse+on
if (m_prgtimer_cur_pulse == 0)
clock_prgtimer();
@@ -515,17 +515,17 @@ void e0c6s46_device::schedule_buzzer()
// only schedule next buzzer timeout if it's on
if (m_bz_43_on != 0 && !m_bz_1shot_running)
return;
-
+
// pulse width differs per frequency selection
int mul = (m_bz_freq & 4) ? 1 : 2;
int high = (m_bz_freq & 2) ? 12 : 8;
int low = 16 + (m_bz_freq << 2 & 0xc);
-
+
// pulse width envelope if it's on
if (m_bz_envelope & 1)
high -= m_bz_duty_ratio;
low -= high;
-
+
m_buzzer_handle->adjust(attotime::from_ticks(m_bz_pulse ? high : low, mul * unscaled_clock()));
}
@@ -548,14 +548,14 @@ void e0c6s46_device::reset_buzzer()
void e0c6s46_device::clock_bz_1shot()
{
m_bz_1shot_running = true;
-
+
// reload counter the 1st time
if (m_bz_1shot_count == 0)
{
reset_buzzer();
m_bz_1shot_count = (m_bz_freq & 8) ? 16 : 8;
}
-
+
// stop ringing when counter reaches 0
else if (--m_bz_1shot_count == 0)
{
@@ -586,7 +586,7 @@ UINT32 e0c6s46_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap
pixel = 1;
else
lcd_on = true;
-
+
// draw pixels
for (int offset = 0; offset < 0x50; offset++)
{
@@ -594,11 +594,11 @@ UINT32 e0c6s46_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap
{
if (lcd_on)
pixel = vram[offset] >> c & 1;
-
+
// 16 COM(common) pins, 40 SEG(segment) pins
int seg = offset / 2;
int com = bank * 8 + (offset & 1) * 4 + c;
-
+
if (m_pixel_update_handler != NULL)
m_pixel_update_handler(*this, bitmap, cliprect, m_lcd_contrast, seg, com, pixel);
else if (cliprect.contains(seg, com))
@@ -631,7 +631,7 @@ READ8_MEMBER(e0c6s46_device::io_r)
}
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15:
return m_irqmask[offset-0x10];
-
+
// K input ports
case 0x40: case 0x42:
return m_port_k[offset >> 1 & 1];
@@ -643,7 +643,7 @@ READ8_MEMBER(e0c6s46_device::io_r)
return m_port_r[offset & 7];
case 0x7b:
return m_r_dir;
-
+
// P I/O ports
case 0x60: case 0x61: case 0x62: case 0x63:
return read_p(offset & 3);
@@ -651,11 +651,11 @@ READ8_MEMBER(e0c6s46_device::io_r)
return m_p_dir;
case 0x7e:
return m_p_pullup;
-
+
// clock-timer (lo, hi)
case 0x20: case 0x21:
return m_clktimer_count >> (4 * (offset & 1)) & 0xf;
-
+
// stopwatch timer
case 0x22:
return m_swl_count;
@@ -663,7 +663,7 @@ READ8_MEMBER(e0c6s46_device::io_r)
return m_swh_count;
case 0x77:
return m_stopwatch_on;
-
+
// programmable timer
case 0x24: case 0x25:
return m_prgtimer_count >> (4 * (offset & 1)) & 0xf;
@@ -673,34 +673,34 @@ READ8_MEMBER(e0c6s46_device::io_r)
return m_prgtimer_on;
case 0x79:
return m_prgtimer_select;
-
+
// buzzer
case 0x74:
return m_bz_freq;
case 0x75:
// d3: 1-shot buzzer is on
return m_bz_1shot_on | m_bz_envelope;
-
+
// OSC circuit
case 0x70:
return m_osc;
-
+
// LCD driver
case 0x71:
return m_lcd_control;
case 0x72:
return m_lcd_contrast;
-
+
// SVD circuit (supply voltage detection)
case 0x73:
// d3: criteria voltage* is 0: <=, 1: > source voltage (Vdd-Vss)
// *0,1,2,3: -2.2V, -2.5V, -3.1V, -4.2V, 1 when off
return m_svd | ((m_svd & 4 && m_svd != 7) ? 0 : 8);
-
+
// write-only registers
case 0x76:
break;
-
+
default:
if (!space.debugger_access())
logerror("%s unknown io_r from $0F%02X at $%04X\n", tag(), offset, m_prev_pc);
@@ -722,13 +722,13 @@ WRITE8_MEMBER(e0c6s46_device::io_w)
m_possible_irq = true;
break;
}
-
+
// K input ports
case 0x41:
// d0-d3: K0x irq on 0: rising edge, 1: falling edge
m_dfk0 = data;
break;
-
+
// R output ports
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54:
write_r(offset & 7, data);
@@ -744,7 +744,7 @@ WRITE8_MEMBER(e0c6s46_device::io_w)
write_r(i, m_port_r[i]);
}
break;
-
+
// P I/O ports
case 0x60: case 0x61: case 0x62: case 0x63:
write_p(offset & 3, data);
@@ -764,7 +764,7 @@ WRITE8_MEMBER(e0c6s46_device::io_w)
// d0-d3: Px* pull up resistor on/off
m_p_pullup = data;
break;
-
+
// OSC circuit
case 0x70:
// d0,d1: CPU operating voltage
@@ -793,7 +793,7 @@ WRITE8_MEMBER(e0c6s46_device::io_w)
// d2: on
m_svd = data & 7;
break;
-
+
// clock-timer
case 0x76:
// d0: reset watchdog
@@ -804,7 +804,7 @@ WRITE8_MEMBER(e0c6s46_device::io_w)
if (data & 2)
m_clktimer_count = 0;
break;
-
+
// stopwatch timer
case 0x77:
// d0: run/stop counter
@@ -878,7 +878,7 @@ WRITE8_MEMBER(e0c6s46_device::io_w)
m_bz_envelope = data & 3;
m_bz_1shot_on |= data & 8;
break;
-
+
// read-only registers
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05:
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: