smc1102: added timer

This commit is contained in:
hap 2023-04-20 19:28:57 +02:00
parent dd1fe09ce3
commit 49166bd5c8
5 changed files with 70 additions and 13 deletions

View File

@ -19,10 +19,8 @@ SMC1112 die notes (SMC1102 is assumed to be the same):
- no output PLA
TODO:
- each opcode is 4 cycles instead of 6
- LCD refresh timing is unknown
- add (micro)instructions PLA if it turns out it can be customized
- add timer
- add halt opcode
*/
@ -72,6 +70,11 @@ void smc1102_cpu_device::device_start()
m_selin = 0;
m_k_line = false;
m_div = 0;
m_timer = 0;
m_timeout = false;
m_tmset = 0;
memset(m_stack, 0, sizeof(m_stack));
m_sp = 0;
m_pb_stack = 0;
@ -87,6 +90,11 @@ void smc1102_cpu_device::device_start()
save_item(NAME(m_selin));
save_item(NAME(m_k_line));
save_item(NAME(m_div));
save_item(NAME(m_timer));
save_item(NAME(m_timeout));
save_item(NAME(m_tmset));
save_item(NAME(m_stack));
save_item(NAME(m_sp));
save_item(NAME(m_pb_stack));
@ -102,6 +110,7 @@ void smc1102_cpu_device::device_reset()
m_inten = false;
m_selin = 0;
m_timeout = false;
// changed/added fixed instructions (mostly handled in op_extra)
m_fixed_decode[0x0a] = F_EXTRA;
@ -186,11 +195,12 @@ void smc1102_cpu_device::read_opcode()
}
// check interrupts (blocked after INTEN)
if (m_inten && m_opcode != 0x74)
if (m_opcode != 0x74)
{
bool taken = (m_selin & 2) ? false : m_k_line;
const bool taken = (m_selin & 2) ? m_timeout : m_k_line;
m_timeout = false;
if (taken)
if (m_inten && taken)
{
interrupt();
return;
@ -223,6 +233,46 @@ void smc1102_cpu_device::interrupt()
m_inten = false;
}
void smc1102_cpu_device::execute_run()
{
while (m_icount > 0)
{
m_icount--;
// decrement timer
m_div = (m_div + 1) & 0x1fff;
const u16 tmask = (m_selin & 1) ? 0x1ff : 0x1fff;
if ((m_div & tmask) == 0)
{
m_timer = (m_timer - 1) & 0xf;
if (m_timer == 0)
{
m_timer = m_tmset;
m_timeout = true;
}
}
// 4 cycles per opcode instead of 6
switch (m_subcycle)
{
case 2:
execute_one(2);
execute_one(3);
break;
case 3:
execute_one(4);
execute_one(5);
break;
default:
execute_one(m_subcycle);
break;
}
m_subcycle = (m_subcycle + 1) & 3;
}
}
// opcode deviations
void smc1102_cpu_device::op_call()
@ -283,6 +333,7 @@ void smc1102_cpu_device::op_selin()
void smc1102_cpu_device::op_tmset()
{
// TMSET: transfer A to timer latch
m_tmset = m_a;
}
void smc1102_cpu_device::op_halt()

View File

@ -62,6 +62,7 @@ protected:
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
virtual u32 decode_micro(offs_t offset) override;
virtual void execute_run() override;
virtual void read_opcode() override;
void interrupt();
@ -92,6 +93,11 @@ protected:
u8 m_selin;
bool m_k_line;
u16 m_div;
u8 m_timer;
bool m_timeout;
u8 m_tmset;
// stack
u16 m_stack[4];
u8 m_sp;

View File

@ -598,9 +598,9 @@ void tms1k_base_device::op_tpc()
// execute
//-------------------------------------------------
void tms1k_base_device::execute_one()
void tms1k_base_device::execute_one(int subcycle)
{
switch (m_subcycle)
switch (subcycle)
{
case 0:
// fetch: rom address 1/2
@ -735,8 +735,6 @@ void tms1k_base_device::execute_one()
// execute: br/call 1/2
break;
}
m_subcycle = (m_subcycle + 1) % 6;
}
void tms1k_base_device::execute_run()
@ -744,6 +742,8 @@ void tms1k_base_device::execute_run()
while (m_icount > 0)
{
m_icount--;
execute_one();
execute_one(m_subcycle);
m_subcycle = (m_subcycle + 1) % 6;
}
}

View File

@ -62,7 +62,7 @@ protected:
virtual u32 execute_min_cycles() const noexcept override { return 1; }
virtual u32 execute_max_cycles() const noexcept override { return 1; }
virtual void execute_run() override;
virtual void execute_one();
virtual void execute_one(int subcycle);
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;

View File

@ -26,8 +26,8 @@ license:CC0-1.0
</element>
<element name="lamp" defstate="0">
<disk state="1"><color red="1.0" green="1.0" blue="1.0" /></disk>
<disk state="0"><color red="0.25" green="0.25" blue="0.25" /></disk>
<disk state="1"><color red="1.0" green="0.97" blue="0.9" /></disk>
<disk state="0"><color red="0.3" green="0.3" blue="0.3" /></disk>
</element>
<element name="hl" defstate="0">