mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
misc/magicard.cpp: Added required devices and default NVRAM contents. (#9970)
* cpu/pic16c5x: Expose driven lines to I/O handlers in mask. * machine/ds1207.cpp: Added DS1207 Time Key device. * machine/msm6242.cpp: Fixed interrupt output pulse duration. * machine/scc66470.cpp: Added Philips SCC66470 Video and System controller device. Machines promoted to working ------------------------------- Puzzle Me! Lucky 7 (Impera) V04/91a Clones promoted to working ------------------------------- Magic Card Export 94 (V2.11a, set 3) Magic Card - Wien (Sicherheitsversion 1.2) unknown Poker 'TE06'
This commit is contained in:
parent
266b918349
commit
0a18e66463
@ -1179,6 +1179,18 @@ if (MACHINES["DS1205"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/ds1207.h,MACHINES["DS1207"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["DS1207"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/ds1207.cpp",
|
||||
MAME_DIR .. "src/devices/machine/ds1207.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/ds1302.h,MACHINES["DS1302"] = true
|
||||
@ -3105,6 +3117,17 @@ if (MACHINES["SAA1043"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/scc66470.h,MACHINES["SCC66470"] = true
|
||||
---------------------------------------------------
|
||||
if (MACHINES["SCC66470"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/scc66470.cpp",
|
||||
MAME_DIR .. "src/devices/machine/scc66470.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/scc68070.h,MACHINES["SCC68070"] = true
|
||||
|
@ -51,6 +51,8 @@
|
||||
* hap (12-Feb-2017) Ver 1.16 *
|
||||
* - Added basic support for the old GI PIC1650 and PIC1655. *
|
||||
* - Made RTCC(aka T0CKI) pin an inputline handler. *
|
||||
* pa (12-Jun-2022) Ver 1.17 *
|
||||
* - Port callback functions pass tristate value in mem_mask. *
|
||||
* *
|
||||
* *
|
||||
* **** Notes: **** *
|
||||
@ -449,7 +451,7 @@ void pic16c5x_device::STORE_REGFILE(offs_t addr, uint8_t data) /* Write to in
|
||||
}
|
||||
else if (m_picmodel != 0x1655) { /* A is input-only on 1655 */
|
||||
data &= 0x0f; /* 4-bit port (only lower 4 bits used) */
|
||||
m_write_a(PIC16C5x_PORTA, data & (uint8_t)(~m_TRISA), 0xff);
|
||||
m_write_a(PIC16C5x_PORTA, data & (uint8_t)(~m_TRISA) & 0x0f, (uint8_t)(~m_TRISA) & 0x0f);
|
||||
}
|
||||
PORTA = data;
|
||||
break;
|
||||
@ -458,7 +460,7 @@ void pic16c5x_device::STORE_REGFILE(offs_t addr, uint8_t data) /* Write to in
|
||||
m_write_b(PIC16C5x_PORTB, data, 0xff);
|
||||
}
|
||||
else {
|
||||
m_write_b(PIC16C5x_PORTB, data & (uint8_t)(~m_TRISB), 0xff);
|
||||
m_write_b(PIC16C5x_PORTB, data & (uint8_t)(~m_TRISB), (uint8_t)(~m_TRISB));
|
||||
}
|
||||
PORTB = data;
|
||||
break;
|
||||
@ -467,7 +469,7 @@ void pic16c5x_device::STORE_REGFILE(offs_t addr, uint8_t data) /* Write to in
|
||||
m_write_c(PIC16C5x_PORTC, data, 0xff);
|
||||
}
|
||||
else if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) {
|
||||
m_write_c(PIC16C5x_PORTC, data & (uint8_t)(~m_TRISC), 0xff);
|
||||
m_write_c(PIC16C5x_PORTC, data & (uint8_t)(~m_TRISC), (uint8_t)(~m_TRISC));
|
||||
}
|
||||
PORTC = data; /* also writes to RAM */
|
||||
break;
|
||||
@ -756,12 +758,12 @@ void pic16c5x_device::tris()
|
||||
switch(m_opcode.b.l & 0x7)
|
||||
{
|
||||
case 5: if (m_TRISA == m_W) break;
|
||||
else { m_TRISA = m_W | 0xf0; m_write_a(PIC16C5x_PORTA, PORTA & (uint8_t)(~m_TRISA) & 0x0f, 0xff); break; }
|
||||
else { m_TRISA = m_W | 0xf0; m_write_a(PIC16C5x_PORTA, PORTA & (uint8_t)(~m_TRISA) & 0x0f, (uint8_t)(~m_TRISA) & 0x0f); break; }
|
||||
case 6: if (m_TRISB == m_W) break;
|
||||
else { m_TRISB = m_W; m_write_b(PIC16C5x_PORTB, PORTB & (uint8_t)(~m_TRISB), 0xff); break; }
|
||||
else { m_TRISB = m_W; m_write_b(PIC16C5x_PORTB, PORTB & (uint8_t)(~m_TRISB), (uint8_t)(~m_TRISB)); break; }
|
||||
case 7: if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) {
|
||||
if (m_TRISC == m_W) break;
|
||||
else { m_TRISC = m_W; m_write_c(PIC16C5x_PORTC, PORTC & (uint8_t)(~m_TRISC), 0xff); break; }
|
||||
else { m_TRISC = m_W; m_write_c(PIC16C5x_PORTC, PORTC & (uint8_t)(~m_TRISC), (uint8_t)(~m_TRISC)); break; }
|
||||
}
|
||||
else {
|
||||
illegal(); break;
|
||||
|
646
src/devices/machine/ds1207.cpp
Normal file
646
src/devices/machine/ds1207.cpp
Normal file
@ -0,0 +1,646 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Paul-Arnold
|
||||
/*
|
||||
* ds1207.c
|
||||
*
|
||||
* Time Key
|
||||
*
|
||||
* Based on ds1204 by smf.
|
||||
*
|
||||
* File format is as follows:
|
||||
* 00-01 unique command pattern
|
||||
* 02-09 identification pattern
|
||||
* 0a-11 security match
|
||||
* 12-41 secure memory data
|
||||
* 42-43 days left
|
||||
* 44-4b start time (from time_t)
|
||||
* 4c control
|
||||
*
|
||||
* Control bits:
|
||||
* bit 0 - OSC ENABLED
|
||||
* bit 1 - OSC RUNNING
|
||||
* bit 2 - DAYS LOCKED
|
||||
* bit 3 - DAYS EXPIRED
|
||||
*
|
||||
* The unique command pattern can be user specific but a number of off the shelf devices exist.
|
||||
* For these devices the pattern should be as follows:
|
||||
* DS1207-G01 0x00 0xb0
|
||||
* DS1207-G02 0x04 0xb0
|
||||
* DS1207-G03 0x08 0xb0
|
||||
* DS1207-G04 0x0c 0xb0
|
||||
* DS1207-G05 0x10 0xb0
|
||||
*/
|
||||
#include "emu.h"
|
||||
#include "ds1207.h"
|
||||
|
||||
#define LOG_LINES (1U << 1)
|
||||
#define LOG_STATE (1U << 2)
|
||||
#define LOG_DATA (1U << 3)
|
||||
|
||||
//#define VERBOSE (LOG_LINES | LOG_STATE | LOG_DATA)
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__)
|
||||
#define LOGSTATE(...) LOGMASKED(LOG_STATE, __VA_ARGS__)
|
||||
#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__)
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(DS1207, ds1207_device, "ds1207", "DS1207 Time Key")
|
||||
|
||||
ds1207_device::ds1207_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, DS1207, tag, owner, clock),
|
||||
device_nvram_interface(mconfig, *this),
|
||||
device_rtc_interface(mconfig, *this),
|
||||
m_region(*this, DEVICE_SELF),
|
||||
m_rst(0),
|
||||
m_clk(0),
|
||||
m_dqw(0), m_dqr(0), m_state(0), m_bit(0)
|
||||
{
|
||||
}
|
||||
|
||||
void ds1207_device::device_reset()
|
||||
{
|
||||
adjust_days_left(); // compensate for time machine has been turned off
|
||||
}
|
||||
|
||||
void ds1207_device::device_start()
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
m_dqr = DQ_HIGH_IMPEDANCE;
|
||||
|
||||
std::fill_n(m_command, std::size(m_command), 0);
|
||||
std::fill_n(m_compare_register, std::size(m_compare_register), 0);
|
||||
m_last_update_time = 0;
|
||||
m_startup_time = 0;
|
||||
std::fill_n(m_day_clock, std::size(m_day_clock), 0);
|
||||
|
||||
save_item(NAME(m_rst));
|
||||
save_item(NAME(m_clk));
|
||||
save_item(NAME(m_dqw));
|
||||
save_item(NAME(m_dqr));
|
||||
save_item(NAME(m_state));
|
||||
save_item(NAME(m_bit));
|
||||
save_item(NAME(m_command));
|
||||
save_item(NAME(m_compare_register));
|
||||
save_item(NAME(m_unique_pattern));
|
||||
save_item(NAME(m_identification));
|
||||
save_item(NAME(m_security_match));
|
||||
save_item(NAME(m_secure_memory));
|
||||
save_item(NAME(m_day_clock));
|
||||
save_item(NAME(m_days_left));
|
||||
save_item(NAME(m_start_time));
|
||||
save_item(NAME(m_device_state));
|
||||
save_item(NAME(m_startup_time));
|
||||
save_item(NAME(m_last_update_time));
|
||||
}
|
||||
|
||||
void ds1207_device::nvram_default()
|
||||
{
|
||||
std::fill_n(m_unique_pattern, std::size(m_unique_pattern), 0);
|
||||
std::fill_n(m_identification, std::size(m_identification), 0);
|
||||
std::fill_n(m_security_match, std::size(m_security_match), 0);
|
||||
std::fill_n(m_secure_memory, std::size(m_secure_memory), 0);
|
||||
std::fill_n(m_days_left, std::size(m_days_left), 0);
|
||||
std::fill_n(m_start_time, std::size(m_start_time), 0);
|
||||
m_device_state = 0;
|
||||
|
||||
int expected_bytes = sizeof(m_unique_pattern) + sizeof(m_identification) + sizeof(m_security_match) + sizeof(m_secure_memory)
|
||||
+ sizeof(m_days_left) + sizeof(m_start_time) + sizeof(m_device_state);;
|
||||
|
||||
if(!m_region.found())
|
||||
{
|
||||
logerror("ds1207(%s) region not found\n", tag());
|
||||
}
|
||||
else if(m_region->bytes() != expected_bytes)
|
||||
{
|
||||
logerror("ds1207(%s) region length 0x%x expected 0x%x\n", tag(), m_region->bytes(), expected_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *region = m_region->base();
|
||||
|
||||
memcpy(m_unique_pattern, region, sizeof(m_unique_pattern));
|
||||
region += sizeof(m_unique_pattern);
|
||||
memcpy(m_identification, region, sizeof(m_identification));
|
||||
region += sizeof(m_identification);
|
||||
memcpy(m_security_match, region, sizeof(m_security_match));
|
||||
region += sizeof(m_security_match);
|
||||
memcpy(m_secure_memory, region, sizeof(m_secure_memory));
|
||||
region += sizeof(m_secure_memory);
|
||||
memcpy(m_days_left, region, sizeof(m_days_left));
|
||||
region += sizeof(m_days_left);
|
||||
memcpy(m_start_time, region, sizeof(m_start_time));
|
||||
region += sizeof(m_start_time);
|
||||
memcpy(&m_device_state, region, sizeof(m_device_state));
|
||||
region += sizeof(m_device_state);
|
||||
}
|
||||
}
|
||||
|
||||
bool ds1207_device::nvram_read(util::read_stream &file)
|
||||
{
|
||||
size_t actual;
|
||||
bool result = !file.read(m_unique_pattern, sizeof(m_unique_pattern), actual) && actual == sizeof(m_unique_pattern);
|
||||
result = result && !file.read(m_identification, sizeof(m_identification), actual) && actual == sizeof(m_identification);
|
||||
result = result && !file.read(m_security_match, sizeof(m_security_match), actual) && actual == sizeof(m_security_match);
|
||||
result = result && !file.read(m_secure_memory, sizeof(m_secure_memory), actual) && actual == sizeof(m_secure_memory);
|
||||
result = result && !file.read(m_days_left, sizeof(m_days_left), actual) && actual == sizeof(m_days_left);
|
||||
result = result && !file.read(m_start_time, sizeof(m_start_time), actual) && actual == sizeof(m_start_time);
|
||||
result = result && !file.read(&m_device_state, sizeof(m_device_state), actual) && actual == sizeof(m_device_state);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ds1207_device::nvram_write(util::write_stream &file)
|
||||
{
|
||||
size_t actual;
|
||||
bool result = !file.write(m_unique_pattern, sizeof(m_unique_pattern), actual) && actual == sizeof(m_unique_pattern);
|
||||
result = result && !file.write(m_identification, sizeof(m_identification), actual) && actual == sizeof(m_identification);
|
||||
result = result && !file.write(m_security_match, sizeof(m_security_match), actual) && actual == sizeof(m_security_match);
|
||||
result = result && !file.write(m_secure_memory, sizeof(m_secure_memory), actual) && actual == sizeof(m_secure_memory);
|
||||
result = result && !file.write(m_days_left, sizeof(m_days_left), actual) && actual == sizeof(m_days_left);
|
||||
result = result && !file.write(m_start_time, sizeof(m_start_time), actual) && actual == sizeof(m_start_time);
|
||||
result = result && !file.write(&m_device_state, sizeof(m_device_state), actual) && actual == sizeof(m_device_state);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ds1207_device::new_state(uint8_t state)
|
||||
{
|
||||
m_state = state;
|
||||
m_bit = 0;
|
||||
}
|
||||
|
||||
void ds1207_device::writebit(uint8_t *buffer)
|
||||
{
|
||||
if(m_clk)
|
||||
{
|
||||
uint16_t index = m_bit / 8;
|
||||
uint8_t mask = 1 << (m_bit % 8);
|
||||
|
||||
if(m_dqw)
|
||||
{
|
||||
buffer[ index ] |= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[ index ] &= ~mask;
|
||||
}
|
||||
|
||||
m_bit++;
|
||||
}
|
||||
}
|
||||
|
||||
void ds1207_device::readbit(uint8_t *buffer)
|
||||
{
|
||||
if(!m_clk)
|
||||
{
|
||||
uint16_t index = m_bit / 8;
|
||||
uint8_t mask = 1 << (m_bit % 8);
|
||||
|
||||
if(buffer[ index ] & mask)
|
||||
{
|
||||
m_dqr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dqr = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bit++;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(ds1207_device::write_rst)
|
||||
{
|
||||
const uint8_t this_state = state ? 1 : 0;
|
||||
if(m_rst != this_state)
|
||||
{
|
||||
m_rst = this_state;
|
||||
LOGLINES("%s: DS1270 rst=%d\n", machine().describe_context(), m_rst);
|
||||
|
||||
if(m_rst)
|
||||
{
|
||||
new_state(STATE_PROTOCOL);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(m_state)
|
||||
{
|
||||
case STATE_WRITE_IDENTIFICATION:
|
||||
LOGSTATE("%s: DS1270 reset during write identification (bit=%u)\n", machine().describe_context(), m_bit);
|
||||
break;
|
||||
|
||||
case STATE_WRITE_SECURITY_MATCH:
|
||||
LOGSTATE("%s: DS1270 reset during write security match (bit=%u)\n", machine().describe_context(), m_bit);
|
||||
break;
|
||||
|
||||
case STATE_WRITE_SECURE_MEMORY:
|
||||
LOGSTATE("%s: DS1270 reset during write secure memory (bit=%u)\n", machine().describe_context(), m_bit);
|
||||
break;
|
||||
}
|
||||
|
||||
new_state(STATE_STOP);
|
||||
m_dqr = DQ_HIGH_IMPEDANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(ds1207_device::write_clk)
|
||||
{
|
||||
const uint8_t this_state = state ? 1 : 0;
|
||||
if(m_clk != this_state)
|
||||
{
|
||||
m_clk = this_state;
|
||||
LOGLINES("%s: DS1270 clk=%d (bit=%u)\n", machine().describe_context(), m_clk, m_bit);
|
||||
|
||||
if(m_clk)
|
||||
{
|
||||
m_dqr = DQ_HIGH_IMPEDANCE;
|
||||
}
|
||||
|
||||
switch(m_state)
|
||||
{
|
||||
case STATE_PROTOCOL:
|
||||
writebit(m_command);
|
||||
|
||||
if(m_bit == 24)
|
||||
{
|
||||
LOGDATA("%s: DS1270 -> command %02x %02x %02x (%02x %02x)\n", machine().describe_context(),
|
||||
m_command[ 0 ], m_command[ 1 ], m_command[ 2 ], m_unique_pattern[ 0 ], m_unique_pattern[ 1 ]);
|
||||
|
||||
if(m_command[ 2 ] == m_unique_pattern[ 1 ] && (m_command[ 1 ] & ~3) == m_unique_pattern[ 0 ])
|
||||
{
|
||||
set_start_time();
|
||||
adjust_time_into_day();
|
||||
|
||||
if(m_command[ 0 ] == COMMAND_READ && (m_command[ 1 ] & 3) == CYCLE_NORMAL)
|
||||
{
|
||||
new_state(STATE_READ_IDENTIFICATION);
|
||||
}
|
||||
else if(m_command[ 0 ] == COMMAND_READ_DAY_CLOCK && (m_command[ 1 ] & 3) == CYCLE_PROGRAM)
|
||||
{
|
||||
new_state(STATE_READ_DAY_CLOCK);
|
||||
}
|
||||
else if(m_command[ 0 ] == COMMAND_READ_DAYS_REMAINING && (m_command[ 1 ] & 3) == CYCLE_PROGRAM)
|
||||
{
|
||||
new_state(STATE_READ_DAYS_REMAINING);
|
||||
}
|
||||
else if(!(m_device_state & DAYS_EXPIRED))
|
||||
{
|
||||
if(m_command[ 0 ] == COMMAND_WRITE && (m_command[ 1 ] & 3) == CYCLE_NORMAL)
|
||||
{
|
||||
new_state(STATE_READ_IDENTIFICATION);
|
||||
}
|
||||
else if((m_command[ 1 ] & 3) == CYCLE_PROGRAM)
|
||||
{
|
||||
if(m_command[ 0 ] == COMMAND_WRITE)
|
||||
{
|
||||
new_state(STATE_WRITE_IDENTIFICATION);
|
||||
}
|
||||
else if(m_command[ 0 ] == COMMAND_WRITE_DAYS_REMAINING)
|
||||
{
|
||||
if(!(m_device_state & DAYS_LOCKED))
|
||||
{
|
||||
new_state(STATE_WRITE_DAYS_REMAINING);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
}
|
||||
else if(m_command[ 0 ] == COMMAND_LOCK_DAYS_COUNT)
|
||||
{
|
||||
m_device_state |= DAYS_LOCKED;
|
||||
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
else if(m_command[ 0 ] == COMMAND_STOP_OSCILLATOR)
|
||||
{
|
||||
if(!(m_device_state & DAYS_LOCKED))
|
||||
{
|
||||
m_device_state &= ~(OSC_ENABLED | OSC_RUNNING);
|
||||
}
|
||||
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
else if(m_command[ 0 ] == COMMAND_ARM_OSCILLATOR)
|
||||
{
|
||||
m_device_state |= OSC_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ_IDENTIFICATION:
|
||||
readbit(m_identification);
|
||||
|
||||
if(m_bit == 64)
|
||||
{
|
||||
LOGDATA("%s: DS1270 <- identification %02x %02x %02x %02x %02x %02x %02x %02x\n", machine().describe_context(),
|
||||
m_identification[ 0 ], m_identification[ 1 ], m_identification[ 2 ], m_identification[ 3 ],
|
||||
m_identification[ 4 ], m_identification[ 5 ], m_identification[ 6 ], m_identification[ 7 ]);
|
||||
|
||||
new_state(STATE_WRITE_COMPARE_REGISTER);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WRITE_COMPARE_REGISTER:
|
||||
writebit(m_compare_register);
|
||||
|
||||
if(m_bit == 64)
|
||||
{
|
||||
LOGDATA("%s: DS1207 -> compare register %02x %02x %02x %02x %02x %02x %02x %02x (%02x %02x %02x %02x %02x %02x %02x %02x)\n", machine().describe_context(),
|
||||
m_compare_register[ 0 ], m_compare_register[ 1 ], m_compare_register[ 2 ], m_compare_register[ 3 ],
|
||||
m_compare_register[ 4 ], m_compare_register[ 5 ], m_compare_register[ 6 ], m_compare_register[ 7 ],
|
||||
m_security_match[ 0 ], m_security_match[ 1 ], m_security_match[ 2 ], m_security_match[ 3 ],
|
||||
m_security_match[ 4 ], m_security_match[ 5 ], m_security_match[ 6 ], m_security_match[ 7 ]);
|
||||
|
||||
if(memcmp(m_compare_register, m_security_match, sizeof(m_compare_register)) == 0)
|
||||
{
|
||||
if(m_command[ 0 ] == COMMAND_READ)
|
||||
{
|
||||
new_state(STATE_READ_SECURE_MEMORY);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state(STATE_WRITE_SECURE_MEMORY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state(STATE_OUTPUT_GARBLED_DATA);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ_SECURE_MEMORY:
|
||||
readbit(m_secure_memory);
|
||||
|
||||
if(m_bit == 384)
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WRITE_SECURE_MEMORY:
|
||||
writebit(m_secure_memory);
|
||||
|
||||
if(m_bit == 384)
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WRITE_IDENTIFICATION:
|
||||
writebit(m_identification);
|
||||
|
||||
if(m_bit == 64)
|
||||
{
|
||||
LOGDATA("%s: DS1207 -> identification %02x %02x %02x %02x %02x %02x %02x %02x\n", machine().describe_context(),
|
||||
m_identification[ 0 ], m_identification[ 1 ], m_identification[ 2 ], m_identification[ 3 ],
|
||||
m_identification[ 4 ], m_identification[ 5 ], m_identification[ 6 ], m_identification[ 7 ]);
|
||||
|
||||
new_state(STATE_WRITE_SECURITY_MATCH);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WRITE_SECURITY_MATCH:
|
||||
writebit(m_security_match);
|
||||
|
||||
if(m_bit == 64)
|
||||
{
|
||||
LOGDATA("%s: DS1207 >- security match %02x %02x %02x %02x %02x %02x %02x %02x\n", machine().describe_context(),
|
||||
m_security_match[ 0 ], m_security_match[ 1 ], m_security_match[ 2 ], m_security_match[ 3 ],
|
||||
m_security_match[ 4 ], m_security_match[ 5 ], m_security_match[ 6 ], m_security_match[ 7 ]);
|
||||
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_OUTPUT_GARBLED_DATA:
|
||||
if(!m_clk && m_command[ 0 ] == COMMAND_READ)
|
||||
{
|
||||
m_dqr = machine().rand() & 1;
|
||||
m_bit++;
|
||||
}
|
||||
else if(m_clk && m_command[ 0 ] == COMMAND_WRITE)
|
||||
{
|
||||
m_bit++;
|
||||
}
|
||||
|
||||
if(m_bit == 64)
|
||||
{
|
||||
if(m_command[ 0 ] == COMMAND_READ)
|
||||
{
|
||||
LOGDATA("%s: DS1207 <- random\n", machine().describe_context());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGDATA("%s: DS1207 -> ignore\n", machine().describe_context());
|
||||
}
|
||||
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ_DAY_CLOCK:
|
||||
readbit(m_day_clock);
|
||||
|
||||
if(m_bit == 20)
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ_DAYS_REMAINING:
|
||||
readbit(m_days_left);
|
||||
|
||||
if(m_bit == 9)
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WRITE_DAYS_REMAINING:
|
||||
writebit(m_days_left);
|
||||
|
||||
if(m_bit == 9)
|
||||
{
|
||||
new_state(STATE_STOP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(ds1207_device::write_dq)
|
||||
{
|
||||
const uint8_t this_state = state ? 1 : 0;
|
||||
if(m_dqw != this_state)
|
||||
{
|
||||
m_dqw = this_state;
|
||||
|
||||
LOGLINES("%s: DS1270 dqw=%u\n", machine().describe_context(), m_dqw);
|
||||
}
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(ds1207_device::read_dq)
|
||||
{
|
||||
if(m_dqr == DQ_HIGH_IMPEDANCE)
|
||||
{
|
||||
LOGLINES("%s: DS1270 dqr=high impedance\n", machine().describe_context());
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGLINES("%s: DS1270 dqr=%d (bit=%u)\n", machine().describe_context(), m_dqr, m_bit);
|
||||
return m_dqr;
|
||||
}
|
||||
|
||||
void ds1207_device::adjust_time_into_day()
|
||||
{
|
||||
if(!(m_device_state & DAYS_EXPIRED) && (m_device_state & OSC_ENABLED) && (m_device_state & OSC_RUNNING))
|
||||
{
|
||||
uint64_t day_clock = ((uint64_t)m_day_clock[ 0 ]) | (((uint64_t)m_day_clock[ 1 ]) << 8) | (((uint64_t)m_day_clock[ 2 ]) << 16);
|
||||
|
||||
const uint64_t cur_time = machine().time().as_ticks(32768) / 2700;
|
||||
const uint64_t diff_time = cur_time - m_last_update_time;
|
||||
m_last_update_time = cur_time;
|
||||
|
||||
day_clock += diff_time;
|
||||
|
||||
m_day_clock[ 0 ] = day_clock & 0xff;
|
||||
m_day_clock[ 1 ] = (day_clock >> 8) & 0xff;
|
||||
m_day_clock[ 2 ] = (day_clock >> 16) & 0xff;
|
||||
|
||||
if(day_clock >= 1048576)
|
||||
{
|
||||
adjust_days_left();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ds1207_device::adjust_days_left()
|
||||
{
|
||||
if(!(m_device_state & DAYS_EXPIRED) && (m_device_state & OSC_ENABLED) && (m_device_state & OSC_RUNNING))
|
||||
{
|
||||
const uint64_t current_time = m_startup_time + machine().time().as_ticks(1);
|
||||
|
||||
uint64_t start_time = 0;
|
||||
|
||||
for(int i = 0; i < 8 ; i++)
|
||||
{
|
||||
start_time <<= 8;
|
||||
start_time |= m_start_time[ 7 - i ];
|
||||
}
|
||||
|
||||
if(current_time > start_time)
|
||||
{
|
||||
uint64_t time_diff = current_time - start_time;
|
||||
|
||||
const uint16_t days_elapsed = time_diff / (24*60*60);
|
||||
|
||||
time_diff %= (24*60*60);// seconds into day
|
||||
|
||||
const uint32_t day_clock = (time_diff * 32768)/2700;// time into day
|
||||
|
||||
m_day_clock[ 0 ] = day_clock & 0xff;
|
||||
m_day_clock[ 1 ] = (day_clock >> 8) & 0xff;
|
||||
m_day_clock[ 2 ] = (day_clock >> 16) & 0xff;
|
||||
|
||||
if(days_elapsed > 0)
|
||||
{
|
||||
uint16_t days_left = m_days_left[ 0 ] | (m_days_left[ 1 ] << 8);
|
||||
|
||||
if(days_elapsed > days_left)
|
||||
{
|
||||
days_left = 0xffff;
|
||||
m_device_state |= DAYS_EXPIRED;
|
||||
}
|
||||
else
|
||||
{
|
||||
days_left -= days_elapsed;
|
||||
}
|
||||
|
||||
m_days_left[ 0 ] = days_left & 0xff;
|
||||
m_days_left[ 1 ] = (days_left >> 8) & 0x1;
|
||||
|
||||
start_time += days_elapsed * 24 * 60 * 60;
|
||||
|
||||
for(int i = 0; i < 8 ; i++)
|
||||
{
|
||||
m_start_time[ i ] = (start_time >> (i * 8)) & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ds1207_device::set_start_time()
|
||||
{
|
||||
if(!(m_device_state & DAYS_EXPIRED) && m_device_state & OSC_ENABLED && !(m_device_state & OSC_RUNNING))
|
||||
{
|
||||
const uint64_t current_time = m_startup_time + machine().time().as_ticks(1);
|
||||
|
||||
for(int i = 0; i < 8 ; i++)
|
||||
{
|
||||
m_start_time[ i ] = (current_time >> (i * 8)) & 0xff;
|
||||
}
|
||||
m_day_clock [ 0 ] = m_day_clock[ 1 ] = m_day_clock[ 2 ] = 0;
|
||||
|
||||
m_device_state |= OSC_RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
void ds1207_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
|
||||
{
|
||||
const int month_to_day_conversion[ 12 ] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
|
||||
|
||||
// put the seconds
|
||||
uint64_t m_startup_time = second;
|
||||
|
||||
// put the minutes
|
||||
m_startup_time += minute * 60;
|
||||
|
||||
// put the hours
|
||||
m_startup_time += hour * 60 * 60;
|
||||
|
||||
// put the days (note -1) */
|
||||
m_startup_time += (day - 1) * 60 * 60 * 24;
|
||||
|
||||
// take the months - despite popular beliefs, leap years aren't just evenly divisible by 4 */
|
||||
if(((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0)) && month > 2)
|
||||
{
|
||||
m_startup_time += (month_to_day_conversion[ month - 1 ] + 1) * 60 * 60 * 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_startup_time += (month_to_day_conversion[ month - 1 ]) * 60 * 60 * 24;
|
||||
}
|
||||
|
||||
// put the years
|
||||
int year_count = (year - 1969);
|
||||
|
||||
for(int i = 0; i < year_count - 1 ; i++)
|
||||
{
|
||||
m_startup_time += (((((i+1970) % 4) == 0) && (((i+1970) % 100) != 0)) || (((i+1970) % 400) == 0)) ? 60*60*24*366 : 60*60*24*365;
|
||||
}
|
||||
}
|
||||
|
122
src/devices/machine/ds1207.h
Normal file
122
src/devices/machine/ds1207.h
Normal file
@ -0,0 +1,122 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Paul-Arnold
|
||||
/*
|
||||
* ds1207.h
|
||||
*
|
||||
* Time Key
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MAME_MACHINE_DS1207_H
|
||||
#define MAME_MACHINE_DS1207_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dirtc.h"
|
||||
|
||||
class ds1207_device : public device_t, public device_nvram_interface, public device_rtc_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
ds1207_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(write_rst);
|
||||
DECLARE_WRITE_LINE_MEMBER(write_clk);
|
||||
DECLARE_WRITE_LINE_MEMBER(write_dq);
|
||||
DECLARE_READ_LINE_MEMBER(read_dq);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_nvram_interface overrides
|
||||
virtual void nvram_default() override;
|
||||
virtual bool nvram_read(util::read_stream &file) override;
|
||||
virtual bool nvram_write(util::write_stream &file) override;
|
||||
|
||||
// device_rtc_interface overrides
|
||||
virtual bool rtc_feature_y2k() const override { return true; }
|
||||
virtual bool rtc_feature_leap_year() const override { return true; }
|
||||
virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override;
|
||||
|
||||
private:
|
||||
void new_state(uint8_t state);
|
||||
void writebit(uint8_t *buffer);
|
||||
void readbit(uint8_t *buffer);
|
||||
void set_start_time();
|
||||
void adjust_days_left();
|
||||
void adjust_time_into_day();
|
||||
|
||||
enum state_t
|
||||
{
|
||||
STATE_STOP,
|
||||
STATE_PROTOCOL,
|
||||
STATE_READ_IDENTIFICATION,
|
||||
STATE_WRITE_IDENTIFICATION,
|
||||
STATE_WRITE_COMPARE_REGISTER,
|
||||
STATE_WRITE_SECURITY_MATCH,
|
||||
STATE_READ_SECURE_MEMORY,
|
||||
STATE_WRITE_SECURE_MEMORY,
|
||||
STATE_OUTPUT_GARBLED_DATA,
|
||||
STATE_READ_DAY_CLOCK,
|
||||
STATE_READ_DAYS_REMAINING,
|
||||
STATE_WRITE_DAYS_REMAINING
|
||||
};
|
||||
|
||||
enum command_t
|
||||
{
|
||||
COMMAND_READ = 0x62,
|
||||
COMMAND_WRITE = 0x9d,
|
||||
COMMAND_READ_DAY_CLOCK = 0xf1,
|
||||
COMMAND_WRITE_DAYS_REMAINING = 0xf2,
|
||||
COMMAND_READ_DAYS_REMAINING = 0xf3,
|
||||
COMMAND_STOP_OSCILLATOR = 0xf4,
|
||||
COMMAND_ARM_OSCILLATOR = 0xf5,
|
||||
COMMAND_LOCK_DAYS_COUNT = 0xf6
|
||||
};
|
||||
|
||||
enum cycle_t
|
||||
{
|
||||
CYCLE_NORMAL = 1,
|
||||
CYCLE_PROGRAM = 2,
|
||||
CYCLE_MASK = 3
|
||||
};
|
||||
|
||||
enum device_state_t
|
||||
{
|
||||
OSC_ENABLED = 1,
|
||||
OSC_RUNNING = 2,
|
||||
DAYS_LOCKED = 4,
|
||||
DAYS_EXPIRED = 8
|
||||
};
|
||||
|
||||
static const int8_t DQ_HIGH_IMPEDANCE = -1;
|
||||
|
||||
optional_memory_region m_region;
|
||||
|
||||
uint8_t m_rst;
|
||||
uint8_t m_clk;
|
||||
uint8_t m_dqw;
|
||||
int8_t m_dqr;
|
||||
uint8_t m_state;
|
||||
uint16_t m_bit;
|
||||
uint64_t m_startup_time;
|
||||
uint64_t m_last_update_time;
|
||||
uint8_t m_command[3];
|
||||
uint8_t m_day_clock[3];
|
||||
uint8_t m_compare_register[8];
|
||||
uint8_t m_unique_pattern[2];
|
||||
uint8_t m_identification[8];
|
||||
uint8_t m_security_match[8];
|
||||
uint8_t m_secure_memory[48];
|
||||
uint8_t m_days_left[2];
|
||||
uint8_t m_start_time[8];
|
||||
uint8_t m_device_state;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(DS1207, ds1207_device)
|
||||
|
||||
#endif // MAME_MACHINE_DS1207_H
|
@ -53,7 +53,6 @@ enum
|
||||
MSM6242_REG_CF
|
||||
};
|
||||
|
||||
#define TIMER_RTC_CALLBACK 1
|
||||
|
||||
|
||||
|
||||
@ -102,6 +101,8 @@ void msm6242_device::device_start()
|
||||
// let's call the timer callback every tick
|
||||
m_timer = timer_alloc(FUNC(msm6242_device::rtc_timer_callback), this);
|
||||
m_timer->adjust(attotime::zero);
|
||||
m_timer_irq_clear = timer_alloc(FUNC(msm6242_device::rtc_irq_pulse_timer_callback), this);
|
||||
m_timer_irq_clear->adjust(attotime::zero);
|
||||
|
||||
// set up registers
|
||||
m_tick = 0;
|
||||
@ -176,6 +177,14 @@ void msm6242_device::set_irq(bool active)
|
||||
|
||||
if (!m_out_int_handler.isnull())
|
||||
m_out_int_handler(active ? ASSERT_LINE : CLEAR_LINE);
|
||||
|
||||
if (active)
|
||||
{
|
||||
if (!BIT(m_reg[1], 1)) // irq is pulsed
|
||||
{
|
||||
m_timer_irq_clear->adjust(attotime::from_nsec(7812500));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -262,7 +271,7 @@ void msm6242_device::update_rtc_registers()
|
||||
return;
|
||||
|
||||
// ticks
|
||||
if ((m_tick % 200) != int((delta + m_tick) % 0x200))
|
||||
if ((m_tick / 0x200) != int((delta + m_tick) / 0x200))
|
||||
irq(IRQ_64THSECOND);
|
||||
delta = bump(RTC_TICKS, delta, 0, 0x8000);
|
||||
if (delta == 0)
|
||||
@ -369,6 +378,17 @@ TIMER_CALLBACK_MEMBER(msm6242_device::rtc_timer_callback)
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// rtc_irq_pulse_timer_callback
|
||||
//-------------------------------------------------
|
||||
|
||||
TIMER_CALLBACK_MEMBER(msm6242_device::rtc_irq_pulse_timer_callback)
|
||||
{
|
||||
set_irq(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// get_clock_nibble
|
||||
//-------------------------------------------------
|
||||
@ -519,6 +539,7 @@ void msm6242_device::write(offs_t offset, u8 data)
|
||||
{
|
||||
LOGIRQENABLE("%s: MSM6242 acknowledging irq\n", machine().describe_context());
|
||||
set_irq(false);
|
||||
m_timer_irq_clear->adjust(attotime::zero);
|
||||
}
|
||||
m_reg[0] = (data & 0x09) | (m_reg[0] & 0x06);
|
||||
break;
|
||||
@ -528,7 +549,7 @@ void msm6242_device::write(offs_t offset, u8 data)
|
||||
// --x- STD
|
||||
// ---x MASK
|
||||
m_reg[1] = data & 0x0f;
|
||||
if((data & 3) == 0) // MASK & STD = 0
|
||||
if((data & 1) == 0) // MASK = 0
|
||||
{
|
||||
m_irq_flag = 1;
|
||||
m_irq_type = (data & 0xc) >> 2;
|
||||
|
@ -83,10 +83,12 @@ private:
|
||||
// incidentals
|
||||
devcb_write_line m_out_int_handler;
|
||||
emu_timer * m_timer;
|
||||
emu_timer * m_timer_irq_clear;
|
||||
u64 m_last_update_time; // last update time, in clock cycles
|
||||
|
||||
// methods
|
||||
TIMER_CALLBACK_MEMBER(rtc_timer_callback);
|
||||
TIMER_CALLBACK_MEMBER(rtc_irq_pulse_timer_callback);
|
||||
u64 current_time();
|
||||
void set_irq(bool active);
|
||||
void irq(u8 irq_type);
|
||||
|
901
src/devices/machine/scc66470.cpp
Normal file
901
src/devices/machine/scc66470.cpp
Normal file
@ -0,0 +1,901 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Paul Arnold
|
||||
/***************************************************************************
|
||||
Philips SCC66470 Video and System controller.
|
||||
|
||||
This does not render the image to the display. It is up to the user
|
||||
to provide their own screen_update function. Pixel (palette offset) data
|
||||
can be obtained by calling line( line number ) for each line.
|
||||
Some boards have multiple video sources, the source being displayed being
|
||||
selected based on pixel value...is there a nice way of doing this other
|
||||
than leaving it to the board driver ?
|
||||
|
||||
Todo:
|
||||
Add support for mosaic and RLE screens.
|
||||
Add remaining pixac operations. Only BCOLOUR1/BCOLOUR2 are supported.
|
||||
Add interlaced support.
|
||||
Add bep ?
|
||||
Verify number of cycles for each access.
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "scc66470.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define CSR_REG (m_csr)
|
||||
#define DCR_REG (m_dcr)
|
||||
#define DCR2_REG (m_dcr2)
|
||||
|
||||
#define DCR_DE 15
|
||||
#define DCR_CF1 14
|
||||
#define DCR_CF2 13
|
||||
#define DCR_FD 12
|
||||
#define DCR_SM 11
|
||||
#define DCR_SS 10
|
||||
#define DCR_LS 9
|
||||
#define DCR_CM 8
|
||||
#define DCR_FG 7
|
||||
#define DCR_DF 6
|
||||
#define DCR_IC 5
|
||||
#define DCR_DC 4
|
||||
|
||||
#define CSR_DI1 15
|
||||
#define CSR_DI2 14
|
||||
#define CSR_EW 10
|
||||
#define CSR_DD1 9
|
||||
#define CSR_DD2 8
|
||||
#define CSR_DM1 7
|
||||
#define CSR_DM2 6
|
||||
#define CSR_TD 5
|
||||
#define CSR_CG 4
|
||||
#define CSR_DD 3
|
||||
#define CSR_ED 2
|
||||
#define CSR_ST 1
|
||||
#define CSR_BE 0
|
||||
|
||||
#define DCR2_OM1 14
|
||||
#define DCR2_OM2 13
|
||||
#define DCR2_ID 12
|
||||
#define DCR2_MF1 11
|
||||
#define DCR2_MF2 10
|
||||
#define DCR2_FT1 9
|
||||
#define DCR2_FT2 8
|
||||
|
||||
#define CSR_R_DA 0x80
|
||||
#define CSR_R_PA 0x20
|
||||
#define CSR_R_IT2 0x04
|
||||
#define CSR_R_IT1 0x02
|
||||
|
||||
#define SCC_INS_STOP ( 0 << 12 )
|
||||
#define SCC_INS_NOP ( 1 << 12 )
|
||||
#define SCC_INS_LOAD_DCP ( 2 << 12 )
|
||||
#define SCC_INS_LOAD_DCP_STOP ( 3 << 12 )
|
||||
#define SCC_INS_LOAD_VSR ( 4 << 12 )
|
||||
#define SCC_INS_LOAD_VSR_STOP ( 5 << 12 )
|
||||
#define SCC_INS_INTERRUPT ( 6 << 12 )
|
||||
#define SCC_INS_LOAD_BORDER ( 14 << 11 )
|
||||
#define SCC_INS_LOAD_BORDER_DSP ( 15 << 11 )
|
||||
#define SCC_INS_BEP_CONTROL ( 1 << 15 )
|
||||
|
||||
#define PIXAC_4N 15
|
||||
#define PIXAC_COL 14
|
||||
#define PIXAC_EXC 13
|
||||
#define PIXAC_CPY 12
|
||||
#define PIXAC_CMP 11
|
||||
#define PIXAC_RTL 10
|
||||
#define PIXAC_SHK 9
|
||||
#define PIXAC_ZOM 8
|
||||
#define PIXAC_INV 3
|
||||
#define PIXAC_BIT 2
|
||||
#define PIXAC_TT 1
|
||||
#define PIXAC_NI 0
|
||||
|
||||
struct horizontal_settings
|
||||
{
|
||||
uint32_t pixels;
|
||||
uint32_t border;
|
||||
};
|
||||
|
||||
static const horizontal_settings h_table[] =
|
||||
{
|
||||
//cf1 cf2 ss st
|
||||
{ 512, 64 }, // 0 0 0 0
|
||||
{ 512, 64 }, // 0 0 0 1
|
||||
{ 512, 0 }, // 0 0 1 0
|
||||
{ 512, 0 }, // 0 0 1 1
|
||||
|
||||
{ 640, 128 }, // 0 1 0 0
|
||||
{ 640, 128 }, // 0 1 0 1
|
||||
{ 640, 0 }, // 0 1 1 0
|
||||
{ 640, 0 }, // 0 1 1 1
|
||||
|
||||
{ 720, 80 }, // 1 0 0 0
|
||||
{ 720, 80 }, // 1 0 0 1
|
||||
|
||||
{ 720, 0 }, // 1 0 1 0
|
||||
{ 720, 0 }, // 1 0 1 1
|
||||
|
||||
{ 768, 128 }, // 1 1 0 0
|
||||
{ 720, 80 }, // 1 1 0 1
|
||||
|
||||
{ 768, 0 }, // 1 1 1 0
|
||||
|
||||
{ 768, 48 }, // 1 1 1 1
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(SCC66470, scc66470_device, "scc66470", "Philips SCC66470")
|
||||
|
||||
//-------------------------------------------------
|
||||
// scc66470_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
scc66470_device::scc66470_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, SCC66470, tag, owner, clock),
|
||||
device_memory_interface(mconfig, *this),
|
||||
device_video_interface(mconfig, *this),
|
||||
m_irqcallback(*this),
|
||||
m_space_config("videoram", ENDIANNESS_BIG, 16, 21, 0, address_map_constructor(FUNC(scc66470_device::scc66470_vram), this))
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void scc66470_device::device_start()
|
||||
{
|
||||
m_irqcallback.resolve_safe();
|
||||
|
||||
m_ica_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(scc66470_device::process_ica), this));
|
||||
|
||||
m_dca_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(scc66470_device::process_dca), this));
|
||||
|
||||
save_item(NAME(m_csr));
|
||||
save_item(NAME(m_dcr));
|
||||
save_item(NAME(m_vsr));
|
||||
save_item(NAME(m_bcr));
|
||||
save_item(NAME(m_dcr2));
|
||||
save_item(NAME(m_dcp));
|
||||
save_item(NAME(m_swm));
|
||||
save_item(NAME(m_stm));
|
||||
save_item(NAME(m_reg_a));
|
||||
save_item(NAME(m_reg_b));
|
||||
save_item(NAME(m_pcr));
|
||||
save_item(NAME(m_mask));
|
||||
save_item(NAME(m_shift));
|
||||
save_item(NAME(m_index));
|
||||
save_item(NAME(m_fc));
|
||||
save_item(NAME(m_bc));
|
||||
save_item(NAME(m_tc));
|
||||
save_item(NAME(m_csr_r));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void scc66470_device::device_reset()
|
||||
{
|
||||
m_working_dcp = 0;
|
||||
|
||||
m_csr = 0;
|
||||
m_dcr = 0;
|
||||
m_vsr = 0;
|
||||
m_bcr = 0;
|
||||
m_dcr2 = 0;
|
||||
m_dcp = 0;
|
||||
m_swm = 0;
|
||||
m_stm = 0;
|
||||
m_reg_a = 0;
|
||||
m_reg_b = 0;
|
||||
m_pcr = 0;
|
||||
m_mask = 0;
|
||||
m_shift = 0;
|
||||
m_index = 0;
|
||||
m_fc = 0;
|
||||
m_bc = 0;
|
||||
m_tc = 0;
|
||||
m_csr_r = 0;
|
||||
|
||||
m_ica_timer->adjust(screen().time_until_pos(0, 0));
|
||||
m_dca_timer->adjust(screen().time_until_pos(32, 784));
|
||||
}
|
||||
|
||||
// default address map
|
||||
void scc66470_device::scc66470_vram(address_map &map)
|
||||
{
|
||||
if(!has_configured_map(0))
|
||||
{
|
||||
map(0x00000000, 0x0017ffff).ram();
|
||||
}
|
||||
}
|
||||
|
||||
device_memory_interface::space_config_vector scc66470_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector {
|
||||
std::make_pair(0, &m_space_config)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void scc66470_device::set_vectors(uint16_t *src)
|
||||
{
|
||||
for(int i = 0 ; i < 4 ; i++)
|
||||
{
|
||||
dram_w(i, *src++, 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scc66470_device::dram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
space().write_word(offset<<1, data, mem_mask);
|
||||
}
|
||||
|
||||
uint16_t scc66470_device::dram_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
return space().read_word(offset<<1, mem_mask);
|
||||
}
|
||||
|
||||
inline uint8_t scc66470_device::dram_byte_r(offs_t offset)
|
||||
{
|
||||
return space().read_byte(offset);
|
||||
}
|
||||
|
||||
void scc66470_device::csr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_csr);
|
||||
}
|
||||
|
||||
void scc66470_device::dcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_dcr);
|
||||
}
|
||||
|
||||
void scc66470_device::vsr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_vsr);
|
||||
}
|
||||
|
||||
void scc66470_device::bcr_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_bcr = data;
|
||||
}
|
||||
|
||||
void scc66470_device::dcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_dcr2);
|
||||
}
|
||||
|
||||
void scc66470_device::dcp_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_dcp);
|
||||
}
|
||||
|
||||
void scc66470_device::swm_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_swm = data | data << 8;
|
||||
}
|
||||
|
||||
void scc66470_device::stm_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_stm = data;
|
||||
}
|
||||
|
||||
void scc66470_device::reg_a_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_reg_a);
|
||||
}
|
||||
|
||||
void scc66470_device::reg_b_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_reg_b);
|
||||
perform_pixac_op();
|
||||
}
|
||||
|
||||
void scc66470_device::pcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_pcr);
|
||||
|
||||
if(!BIT(m_pcr, PIXAC_COL) || !BIT(m_pcr, PIXAC_4N) || !BIT(m_pcr, PIXAC_BIT))
|
||||
{
|
||||
logerror("unsuppported pixac %x\n", m_pcr);
|
||||
}
|
||||
}
|
||||
|
||||
void scc66470_device::mask_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_mask = data;
|
||||
}
|
||||
|
||||
void scc66470_device::shift_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_shift = data;
|
||||
}
|
||||
|
||||
void scc66470_device::index_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_index = data;
|
||||
}
|
||||
|
||||
void scc66470_device::fc_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_fc = data;
|
||||
}
|
||||
|
||||
void scc66470_device::bc_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_bc = data;
|
||||
}
|
||||
|
||||
void scc66470_device::tc_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_tc = data;
|
||||
}
|
||||
|
||||
uint8_t scc66470_device::csr_r(offs_t offset)
|
||||
{
|
||||
uint8_t val = m_csr_r;
|
||||
|
||||
if(!machine().side_effects_disabled())
|
||||
{
|
||||
m_csr_r &= ~(CSR_R_IT1 | CSR_R_IT2);
|
||||
|
||||
if(!m_irqcallback.isnull())
|
||||
{
|
||||
m_irqcallback(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
int scanline = screen().vpos();
|
||||
|
||||
if(scanline >= total_height() - height())
|
||||
{
|
||||
val |= CSR_R_DA;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
uint16_t scc66470_device::reg_b_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
return m_reg_b & mem_mask;
|
||||
}
|
||||
|
||||
int scc66470_device::dram_dtack_cycles()
|
||||
{
|
||||
const int slot_cycle = (int)(machine().time().as_ticks(clock()) & 0xf);
|
||||
|
||||
if(slot_cycle == 9)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else if(slot_cycle < 9)
|
||||
{
|
||||
return 2 + 9 - slot_cycle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 2 + 9 + 16 - slot_cycle;
|
||||
}
|
||||
}
|
||||
|
||||
void scc66470_device::map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x17ffff).rw(FUNC(scc66470_device::dram_r), FUNC(scc66470_device::dram_w));
|
||||
map(0x1fffe0, 0x1fffe1).w(FUNC(scc66470_device::csr_w));
|
||||
map(0x1fffe1, 0x1fffe1).r(FUNC(scc66470_device::csr_r));
|
||||
map(0x1fffe2, 0x1fffe3).w(FUNC(scc66470_device::dcr_w));
|
||||
map(0x1fffe4, 0x1fffe5).w(FUNC(scc66470_device::vsr_w));
|
||||
map(0x1fffe7, 0x1fffe7).w(FUNC(scc66470_device::bcr_w));
|
||||
map(0x1fffe8, 0x1fffe9).w(FUNC(scc66470_device::dcr2_w));
|
||||
map(0x1fffea, 0x1fffeb).w(FUNC(scc66470_device::dcp_w));
|
||||
map(0x1fffec, 0x1fffec).w(FUNC(scc66470_device::swm_w));
|
||||
map(0x1fffef, 0x1fffef).w(FUNC(scc66470_device::stm_w));
|
||||
map(0x1ffff0, 0x1ffff1).w(FUNC(scc66470_device::reg_a_w));
|
||||
map(0x1ffff2, 0x1ffff3).rw(FUNC(scc66470_device::reg_b_r), FUNC(scc66470_device::reg_b_w));
|
||||
map(0x1ffff4, 0x1ffff5).w(FUNC(scc66470_device::pcr_w));
|
||||
map(0x1ffff7, 0x1ffff7).w(FUNC(scc66470_device::mask_w));
|
||||
map(0x1ffff8, 0x1ffff8).w(FUNC(scc66470_device::shift_w));
|
||||
map(0x1ffffb, 0x1ffffb).w(FUNC(scc66470_device::index_w));
|
||||
map(0x1ffffc, 0x1ffffc).w(FUNC(scc66470_device::fc_w));
|
||||
map(0x1ffffd, 0x1ffffd).w(FUNC(scc66470_device::bc_w));
|
||||
map(0x1ffffe, 0x1ffffe).w(FUNC(scc66470_device::tc_w));
|
||||
}
|
||||
|
||||
int scc66470_device::pixac_trigger()
|
||||
{
|
||||
if(BIT(m_pcr, PIXAC_COL))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if(BIT(m_pcr, PIXAC_CPY) && !BIT(m_pcr, PIXAC_TT))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void scc66470_device::perform_pixac_op()
|
||||
{
|
||||
if(BIT(m_pcr, PIXAC_COL) && BIT(m_pcr, PIXAC_BIT))
|
||||
{
|
||||
if(BIT(m_pcr, PIXAC_4N))
|
||||
{
|
||||
uint16_t result = m_reg_b;
|
||||
m_index &= 0xf;
|
||||
|
||||
if(BIT(m_reg_a, 15 - m_index))
|
||||
{
|
||||
result = (result & 0xff) | m_fc << 8;
|
||||
}
|
||||
else if(!BIT(m_pcr, PIXAC_TT))
|
||||
{
|
||||
result = (result & 0xff) | m_bc << 8;
|
||||
}
|
||||
|
||||
m_index++;
|
||||
|
||||
m_index &= 0xf;
|
||||
|
||||
if(BIT(m_reg_a, 15 - m_index))
|
||||
{
|
||||
result = (result & 0xff00) | m_fc;
|
||||
}
|
||||
else if(!BIT(m_pcr, PIXAC_TT))
|
||||
{
|
||||
result = (result & 0xff00) | m_bc;
|
||||
}
|
||||
|
||||
m_index++;
|
||||
|
||||
m_reg_b = (m_reg_b & ~m_swm) | (result & m_swm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint16_t scc66470_device::ipa_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
if(offset < 0x180000 / 2)
|
||||
{
|
||||
if(pixac_trigger())
|
||||
{
|
||||
reg_b_w(0, dram_r(offset, 0xffff), 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void scc66470_device::ipa_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
if(offset < 0x180000 / 2)
|
||||
{
|
||||
if(pixac_trigger())
|
||||
{
|
||||
dram_w(offset, m_reg_b, 0xffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool scc66470_device::display_enabled()
|
||||
{
|
||||
if(BIT(DCR_REG, DCR_DE))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void scc66470_device::set_vsr(uint32_t vsr)
|
||||
{
|
||||
m_dcr = (m_dcr & 0xfff0) | ((vsr >> 16) & 0x0f);
|
||||
m_vsr = vsr;
|
||||
}
|
||||
|
||||
uint32_t scc66470_device::get_vsr()
|
||||
{
|
||||
return ((m_dcr & 0xf) << 16) | m_vsr;
|
||||
}
|
||||
|
||||
uint32_t scc66470_device::get_dcp()
|
||||
{
|
||||
return ((m_dcr2 & 0x0f) << 16) | m_dcp;
|
||||
}
|
||||
|
||||
void scc66470_device::set_dcp(uint32_t dcp)
|
||||
{
|
||||
m_dcr2 = (m_dcr2 & 0xfff0) | (dcp & 0x0f);
|
||||
m_dcp = dcp;
|
||||
}
|
||||
|
||||
void scc66470_device::line(int line, uint8_t *line_buffer, unsigned line_buffer_size)
|
||||
{
|
||||
if(line_buffer_size == width())
|
||||
{
|
||||
if(display_enabled() && line >= (total_height() - height()))
|
||||
{
|
||||
uint8_t bc = m_bcr;
|
||||
|
||||
if(BIT(DCR_REG, DCR_CM)) //4 bits/pixel
|
||||
{
|
||||
bc = bc >> 4;
|
||||
}
|
||||
|
||||
line -= total_height() - height();
|
||||
|
||||
if(line < border_height() || line >= (height() - border_height()))
|
||||
{
|
||||
std::fill_n(line_buffer, width(), bc);
|
||||
|
||||
if(line == height() - 1)
|
||||
{
|
||||
set_vsr(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned vsr = get_vsr() & 0xfffff;
|
||||
|
||||
if(vsr)
|
||||
{
|
||||
line_buffer = std::fill_n(line_buffer, border_width(), bc);
|
||||
|
||||
if(BIT(DCR_REG, DCR_CM)) //4 bits/pixel
|
||||
{
|
||||
if(!BIT(DCR2_REG, DCR2_FT1))
|
||||
{
|
||||
for(int i = 0 ; i < width() - (border_width() * 2) ; i += 2)
|
||||
{
|
||||
uint8_t pixels = dram_byte_r(vsr++);
|
||||
*line_buffer++ = (pixels >> 4) & 0x0f;
|
||||
*line_buffer++ = (pixels) & 0x0f;
|
||||
vsr &= 0xfffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!BIT(DCR2_REG, DCR2_FT1))
|
||||
{
|
||||
for(int i = 0 ; i < width() - (border_width() * 2) ; i += 2)
|
||||
{
|
||||
const uint8_t pixel = dram_byte_r(vsr++);
|
||||
*line_buffer++ = pixel;
|
||||
*line_buffer++ = pixel;
|
||||
vsr &= 0xfffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::fill_n(line_buffer, border_width(), bc);
|
||||
|
||||
if(BIT(DCR_REG, DCR_LS))
|
||||
{
|
||||
vsr = get_vsr() + 512;
|
||||
|
||||
if(BIT(DCR_REG, DCR_IC))
|
||||
{
|
||||
m_working_dcp = vsr - 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_working_dcp = vsr - 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!BIT(DCR2_REG, DCR2_ID))
|
||||
{
|
||||
if(BIT(DCR_REG, DCR_DC))
|
||||
{
|
||||
m_working_dcp = vsr;
|
||||
|
||||
if(BIT(DCR_REG, DCR_IC))
|
||||
{
|
||||
vsr += 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
vsr += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_vsr(vsr);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fill_n(line_buffer, line_buffer_size, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fill_n(line_buffer, line_buffer_size, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fill_n(line_buffer, line_buffer_size, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(scc66470_device::process_ica)
|
||||
{
|
||||
uint32_t ctrl = 0x400 / 2;
|
||||
|
||||
if((BIT(DCR_REG, DCR_IC) || BIT(DCR_REG, DCR_DC)) && dram_r(ctrl, 0xffff) != 0)
|
||||
{
|
||||
bool stop = false;
|
||||
while(!stop)
|
||||
{
|
||||
uint16_t cmd = dram_r(ctrl++, 0xffff);
|
||||
uint16_t data = dram_r(ctrl++, 0xffff);
|
||||
|
||||
ctrl &= 0xffffe;
|
||||
|
||||
switch(cmd & 0xff00)
|
||||
{
|
||||
case SCC_INS_STOP:
|
||||
set_vsr((ctrl - 2) * 2);
|
||||
stop = true;
|
||||
break;
|
||||
|
||||
case SCC_INS_NOP:
|
||||
break;
|
||||
|
||||
case SCC_INS_LOAD_DCP:
|
||||
set_dcp(((cmd & 0xf) << 16) | (data & 0xfc));
|
||||
break;
|
||||
|
||||
case SCC_INS_LOAD_DCP_STOP:
|
||||
set_dcp(((cmd & 0xf) << 16) | (data & 0xfc));
|
||||
stop = true;
|
||||
break;
|
||||
|
||||
case SCC_INS_LOAD_VSR:
|
||||
ctrl = (((cmd & 0xf) << 16) | data) / 2;
|
||||
ctrl &= 0xffffe;
|
||||
break;
|
||||
|
||||
case SCC_INS_LOAD_VSR_STOP:
|
||||
ctrl = ((cmd & 0xf) << 16) | data;
|
||||
ctrl &= 0xffffe;
|
||||
set_vsr(ctrl);
|
||||
stop = true;
|
||||
break;
|
||||
|
||||
case SCC_INS_INTERRUPT:
|
||||
m_csr_r |= CSR_R_IT1;
|
||||
|
||||
if(!BIT(CSR_REG, CSR_DI1))
|
||||
{
|
||||
if(!m_irqcallback.isnull())
|
||||
{
|
||||
m_irqcallback(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if((cmd & 0xf800) == SCC_INS_LOAD_BORDER)
|
||||
{
|
||||
m_bcr = cmd & 0xff;
|
||||
}
|
||||
else if((cmd & 0xf800) == SCC_INS_LOAD_BORDER_DSP)
|
||||
{
|
||||
m_bcr = cmd & 0xff;
|
||||
m_dcr2 = (m_dcr2 & 0x90ff) | (data & 0x6f) << 8;
|
||||
m_dcr = (m_dcr & 0xfaff) | (data & 0x0500);
|
||||
}
|
||||
else if(cmd & SCC_INS_BEP_CONTROL)
|
||||
{
|
||||
//need to implement ?
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("Unknown ica/dca instruction %x %x %x\n",cmd,data,ctrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_working_dcp = 0;
|
||||
|
||||
if(BIT(DCR_REG, DCR_DC) && BIT(DCR2_REG, DCR2_ID))
|
||||
{
|
||||
m_working_dcp = get_dcp();
|
||||
}
|
||||
|
||||
m_ica_timer->adjust(screen().time_until_pos(0, 0));
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(scc66470_device::process_dca)
|
||||
{
|
||||
uint32_t ctrl = (m_working_dcp / 2) & 0xffffe;
|
||||
|
||||
if(BIT(DCR_REG, DCR_DC) && ctrl)
|
||||
{
|
||||
bool stop = false;
|
||||
bool new_dcp = false;
|
||||
uint32_t count;
|
||||
|
||||
if(!BIT(DCR_REG, DCR_IC))
|
||||
{
|
||||
count = 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 64;
|
||||
}
|
||||
|
||||
while(!stop && count)
|
||||
{
|
||||
uint16_t cmd = dram_r(ctrl++, 0xffff);
|
||||
uint16_t data = dram_r(ctrl++, 0xffff);
|
||||
|
||||
ctrl &= 0xffffe;
|
||||
|
||||
count -= 4;
|
||||
|
||||
switch(cmd & 0xff00)
|
||||
{
|
||||
case SCC_INS_STOP:
|
||||
stop = true;
|
||||
break;
|
||||
|
||||
case SCC_INS_NOP:
|
||||
break;
|
||||
|
||||
case SCC_INS_LOAD_DCP:
|
||||
m_working_dcp = ((cmd & 0xf) << 16) | (data & 0xfc);
|
||||
set_dcp(m_working_dcp);
|
||||
ctrl = m_working_dcp / 2;
|
||||
ctrl &= 0xffffe;
|
||||
break;
|
||||
|
||||
case SCC_INS_LOAD_DCP_STOP:
|
||||
m_working_dcp = ((cmd & 0xf) << 16) | (data & 0xfc);
|
||||
set_dcp(m_working_dcp);
|
||||
stop = true;
|
||||
new_dcp = true;
|
||||
break;
|
||||
|
||||
case SCC_INS_LOAD_VSR:
|
||||
set_vsr(((cmd & 0xf) << 16) | data);
|
||||
break;
|
||||
|
||||
case SCC_INS_LOAD_VSR_STOP:
|
||||
set_vsr(((cmd & 0xf) << 16) | data);
|
||||
stop = true;
|
||||
break;
|
||||
|
||||
case SCC_INS_INTERRUPT:
|
||||
m_csr_r |= CSR_R_IT1;
|
||||
|
||||
if(!BIT(CSR_REG, CSR_DI1))
|
||||
{
|
||||
if(!m_irqcallback.isnull())
|
||||
{
|
||||
m_irqcallback(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if((cmd & 0xf800) == SCC_INS_LOAD_BORDER)
|
||||
{
|
||||
m_bcr = cmd & 0xff;
|
||||
}
|
||||
else if((cmd & 0xf800) == SCC_INS_LOAD_BORDER_DSP)
|
||||
{
|
||||
m_bcr = cmd & 0xff;
|
||||
m_dcr2 = (m_dcr2 & 0x90ff) | (data & 0x6f) << 8;
|
||||
m_dcr = (m_dcr & 0xfaff) | (data & 0x0500);
|
||||
}
|
||||
else if(cmd & SCC_INS_BEP_CONTROL)
|
||||
{
|
||||
//need to implement ?
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("Unknown ica instruction %x %x %x\n",cmd,data,ctrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctrl *= 2;
|
||||
|
||||
if(!new_dcp)
|
||||
{
|
||||
ctrl += count;
|
||||
}
|
||||
|
||||
if(BIT(DCR_REG, DCR_DC) && BIT(DCR2_REG, DCR2_ID))
|
||||
{
|
||||
m_working_dcp = ctrl;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_working_dcp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int scanline = screen().vpos();
|
||||
|
||||
if(scanline == total_height() - border_height() - 1)
|
||||
{
|
||||
m_csr_r ^= CSR_R_PA;
|
||||
|
||||
m_dca_timer->adjust(screen().time_until_pos(total_height() - height() + border_height(), 784));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dca_timer->adjust(screen().time_until_pos(scanline + 1, 784));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned scc66470_device::border_width()
|
||||
{
|
||||
const unsigned hoffset = (BIT(DCR_REG, DCR_CF1) << 3) | (BIT(DCR_REG, DCR_CF2) << 2) | (BIT(DCR_REG, DCR_SS) << 1) | BIT(CSR_REG, CSR_ST);
|
||||
return h_table[ hoffset ].border / 2;
|
||||
}
|
||||
|
||||
int scc66470_device::border_height()
|
||||
{
|
||||
int height = 0;
|
||||
|
||||
if(!BIT(DCR_REG, DCR_FD) && BIT(CSR_REG, CSR_ST))
|
||||
{
|
||||
height = 20;
|
||||
}
|
||||
|
||||
if(!BIT(DCR_REG, DCR_SS))
|
||||
{
|
||||
height += 15;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
unsigned scc66470_device::width()
|
||||
{
|
||||
const unsigned hoffset = (BIT(DCR_REG, DCR_CF1) << 3) | (BIT(DCR_REG, DCR_CF2) << 2) | (BIT(DCR_REG, DCR_SS) << 1) | BIT(CSR_REG, CSR_ST);
|
||||
return h_table[ hoffset ].pixels;
|
||||
}
|
||||
|
||||
unsigned scc66470_device::height()
|
||||
{
|
||||
if(BIT(DCR_REG, DCR_FD))
|
||||
{
|
||||
return 240;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 280;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned scc66470_device::total_height()
|
||||
{
|
||||
if(BIT(DCR_REG, DCR_FD))
|
||||
{
|
||||
return 262;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 312;
|
||||
}
|
||||
}
|
115
src/devices/machine/scc66470.h
Normal file
115
src/devices/machine/scc66470.h
Normal file
@ -0,0 +1,115 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Paul Arnold
|
||||
/***************************************************************************
|
||||
|
||||
scc66470.h
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_VIDEO_SCC66470_H
|
||||
#define MAME_VIDEO_SCC66470_H
|
||||
|
||||
#pragma once
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
|
||||
// ======================> scc66470_device
|
||||
|
||||
class scc66470_device : public device_t, public device_memory_interface, public device_video_interface
|
||||
{
|
||||
public:
|
||||
auto irq()
|
||||
{
|
||||
return m_irqcallback.bind();
|
||||
}
|
||||
|
||||
// construction/destruction
|
||||
scc66470_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
uint16_t ipa_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void ipa_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
bool display_enabled();
|
||||
void line(int line, uint8_t *line_buffer, unsigned line_buffer_size);
|
||||
unsigned width();
|
||||
unsigned height();
|
||||
unsigned total_height();
|
||||
int dram_dtack_cycles();
|
||||
void dram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t dram_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void map(address_map &map);
|
||||
void set_vectors(uint16_t *src);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
devcb_write_line m_irqcallback;
|
||||
|
||||
uint32_t m_working_dcp;
|
||||
|
||||
uint16_t m_csr;
|
||||
uint16_t m_dcr;
|
||||
uint16_t m_vsr;
|
||||
uint8_t m_bcr;
|
||||
uint16_t m_dcr2;
|
||||
uint16_t m_dcp;
|
||||
uint16_t m_swm;
|
||||
uint8_t m_stm;
|
||||
uint16_t m_reg_a;
|
||||
uint16_t m_reg_b;
|
||||
uint16_t m_pcr;
|
||||
uint8_t m_mask;
|
||||
uint8_t m_shift;
|
||||
uint8_t m_index;
|
||||
uint8_t m_fc;
|
||||
uint8_t m_bc;
|
||||
uint8_t m_tc;
|
||||
uint8_t m_csr_r;
|
||||
|
||||
private:
|
||||
void scc66470_vram(address_map &map);
|
||||
void set_vsr(uint32_t vsr);
|
||||
void set_dcp(uint32_t dcp);
|
||||
uint32_t get_vsr();
|
||||
uint32_t get_dcp();
|
||||
unsigned border_width();
|
||||
int border_height();
|
||||
void csr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void dcr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void vsr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void bcr_w(offs_t offset, uint8_t data);
|
||||
void dcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void dcp_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void swm_w(offs_t offset, uint8_t data);
|
||||
void stm_w(offs_t offset, uint8_t data);
|
||||
void reg_a_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void reg_b_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void pcr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void mask_w(offs_t offset, uint8_t data);
|
||||
void shift_w(offs_t offset, uint8_t data);
|
||||
void index_w(offs_t offset, uint8_t data);
|
||||
void fc_w(offs_t offset, uint8_t data);
|
||||
void bc_w(offs_t offset, uint8_t data);
|
||||
void tc_w(offs_t offset, uint8_t data);
|
||||
uint8_t csr_r(offs_t offset);
|
||||
uint16_t reg_b_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
int pixac_trigger();
|
||||
void perform_pixac_op();
|
||||
inline uint8_t dram_byte_r(offs_t offset);
|
||||
|
||||
TIMER_CALLBACK_MEMBER(process_ica);
|
||||
TIMER_CALLBACK_MEMBER(process_dca);
|
||||
emu_timer *m_ica_timer;
|
||||
emu_timer *m_dca_timer;
|
||||
|
||||
const address_space_config m_space_config;
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(SCC66470, scc66470_device)
|
||||
|
||||
#endif // MAME_VIDEO_SCC66470_H
|
@ -13,11 +13,12 @@
|
||||
|
||||
STATUS:
|
||||
|
||||
- Skeleton. Just enough for the CD-i to run.
|
||||
- Skeleton. Just enough for the CD-i and Magicard to run.
|
||||
|
||||
TODO:
|
||||
|
||||
- Proper handling of the 68070's internal devices (UART, DMA, Timers, etc.)
|
||||
- I2C could do with re-visiting.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
@ -41,6 +42,165 @@ TODO:
|
||||
|
||||
#define ENABLE_UART_PRINTING (0)
|
||||
|
||||
//**************************************************************************
|
||||
// Register defines
|
||||
//**************************************************************************
|
||||
enum isr_bits
|
||||
{
|
||||
ISR_MST = 0x80, // Master
|
||||
ISR_TRX = 0x40, // Transmitter
|
||||
ISR_BB = 0x20, // Busy
|
||||
ISR_PIN = 0x10, // No Pending Interrupt
|
||||
ISR_AL = 0x08, // Arbitration Lost
|
||||
ISR_AAS = 0x04, // Addressed As Slave
|
||||
ISR_AD0 = 0x02, // Address Zero
|
||||
ISR_LRB = 0x01, // Last Received Bit
|
||||
ISR_SSR_MASK = (ISR_MST | ISR_TRX | ISR_BB),// Mask for detecting start/stop/restart
|
||||
ISR_START = (ISR_MST | ISR_TRX | ISR_BB),// Start bit request
|
||||
ISR_STOP = (ISR_MST | ISR_TRX) // Stop bit request
|
||||
};
|
||||
|
||||
enum umr_bits
|
||||
{
|
||||
UMR_OM = 0xc0,
|
||||
UMR_OM_NORMAL = 0x00,
|
||||
UMR_OM_ECHO = 0x40,
|
||||
UMR_OM_LOOPBACK = 0x80,
|
||||
UMR_OM_RLOOP = 0xc0,
|
||||
UMR_TXC = 0x10,
|
||||
UMR_PC = 0x08,
|
||||
UMR_P = 0x04,
|
||||
UMR_SB = 0x02,
|
||||
UMR_CL = 0x01
|
||||
};
|
||||
|
||||
enum usr_bits
|
||||
{
|
||||
USR_RB = 0x80,
|
||||
USR_FE = 0x40,
|
||||
USR_PE = 0x20,
|
||||
USR_OE = 0x10,
|
||||
USR_TXEMT = 0x08,
|
||||
USR_TXRDY = 0x04,
|
||||
USR_RXRDY = 0x01
|
||||
};
|
||||
|
||||
enum tsr_bits
|
||||
{
|
||||
TSR_OV0 = 0x80,
|
||||
TSR_MA1 = 0x40,
|
||||
TSR_CAP1 = 0x20,
|
||||
TSR_OV1 = 0x10,
|
||||
TSR_MA2 = 0x08,
|
||||
TSR_CAP2 = 0x04,
|
||||
TSR_OV2 = 0x02
|
||||
};
|
||||
|
||||
enum tcr_bits
|
||||
{
|
||||
TCR_E1 = 0xc0,
|
||||
TCR_E1_NONE = 0x00,
|
||||
TCR_E1_RISING = 0x40,
|
||||
TCR_E1_FALLING = 0x80,
|
||||
TCR_E1_BOTH = 0xc0,
|
||||
TCR_M1 = 0x30,
|
||||
TCR_M1_NONE = 0x00,
|
||||
TCR_M1_MATCH = 0x10,
|
||||
TCR_M1_CAPTURE = 0x20,
|
||||
TCR_M1_COUNT = 0x30,
|
||||
TCR_E2 = 0x0c,
|
||||
TCR_E2_NONE = 0x00,
|
||||
TCR_E2_RISING = 0x04,
|
||||
TCR_E2_FALLING = 0x08,
|
||||
TCR_E2_BOTH = 0x0c,
|
||||
TCR_M2 = 0x03,
|
||||
TCR_M2_NONE = 0x00,
|
||||
TCR_M2_MATCH = 0x01,
|
||||
TCR_M2_CAPTURE = 0x02,
|
||||
TCR_M2_COUNT = 0x03
|
||||
};
|
||||
|
||||
enum csr_bits
|
||||
{
|
||||
CSR_COC = 0x80,
|
||||
CSR_NDT = 0x20,
|
||||
CSR_ERR = 0x10,
|
||||
CSR_CA = 0x08
|
||||
};
|
||||
|
||||
enum cer_bits
|
||||
{
|
||||
CER_EC = 0x1f,
|
||||
CER_NONE = 0x00,
|
||||
CER_TIMING = 0x02,
|
||||
CER_BUSERR_MEM = 0x09,
|
||||
CER_BUSERR_DEV = 0x0a,
|
||||
CER_SOFT_ABORT = 0x11
|
||||
};
|
||||
|
||||
enum dcr1_bits
|
||||
{
|
||||
DCR1_ERM = 0x80,
|
||||
DCR1_DT = 0x30
|
||||
};
|
||||
|
||||
enum dcr2_bits
|
||||
{
|
||||
DCR2_ERM = 0x80,
|
||||
DCR2_DT = 0x30,
|
||||
DCR2_DS = 0x08
|
||||
};
|
||||
|
||||
|
||||
enum scr2_bits
|
||||
{
|
||||
SCR2_MAC = 0x0c,
|
||||
SCR2_MAC_NONE = 0x00,
|
||||
SCR2_MAC_INC = 0x04,
|
||||
SCR2_DAC = 0x03,
|
||||
SCR2_DAC_NONE = 0x00,
|
||||
SCR2_DAC_INC = 0x01
|
||||
};
|
||||
|
||||
enum ccr_bits
|
||||
{
|
||||
CCR_SO = 0x80,
|
||||
CCR_SA = 0x10,
|
||||
CCR_INE = 0x08,
|
||||
CCR_IPL = 0x07
|
||||
};
|
||||
|
||||
enum icr_bits
|
||||
{
|
||||
ICR_SEL = 0x40,
|
||||
ICR_ESO = 0x08,
|
||||
ICR_ACK = 0x04
|
||||
};
|
||||
|
||||
enum i2c_states
|
||||
{
|
||||
I2C_IDLE = 0,
|
||||
I2C_TX_IN_PROGRESS,
|
||||
I2C_RX_IN_PROGRESS,
|
||||
I2C_RX_COMPLETE,
|
||||
I2C_GET_ACK,
|
||||
I2C_SEND_ACK,
|
||||
I2C_SEND_ACK_AND_RX,
|
||||
I2C_SEND_ACK_AND_STOP,
|
||||
I2C_SEND_STOP,
|
||||
I2C_CHANGED_TO_RX,
|
||||
I2C_SEND_RESTART
|
||||
};
|
||||
|
||||
enum i2c_clock_states
|
||||
{
|
||||
I2C_SCL_IDLE = 0,
|
||||
I2C_SCL_SET_0,
|
||||
I2C_SCL_SET_1,
|
||||
I2C_SCL_WAIT_1,
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(SCC68070, scc68070_device, "scc68070", "Philips SCC68070")
|
||||
|
||||
@ -86,6 +246,9 @@ scc68070_device::scc68070_device(const machine_config &mconfig, const char *tag,
|
||||
, m_iack7_callback(*this)
|
||||
, m_uart_tx_callback(*this)
|
||||
, m_uart_rtsn_callback(*this)
|
||||
, m_i2c_scl_callback(*this)
|
||||
, m_i2c_sdaw_callback(*this)
|
||||
, m_i2c_sdar_callback(*this)
|
||||
, m_ipl(0)
|
||||
, m_in2_line(CLEAR_LINE)
|
||||
, m_in4_line(CLEAR_LINE)
|
||||
@ -113,6 +276,9 @@ void scc68070_device::device_resolve_objects()
|
||||
m_iack7_callback.resolve_safe(autovector(7));
|
||||
m_uart_tx_callback.resolve_safe();
|
||||
m_uart_rtsn_callback.resolve_safe();
|
||||
m_i2c_scl_callback.resolve_safe();
|
||||
m_i2c_sdaw_callback.resolve_safe();
|
||||
m_i2c_sdar_callback.resolve_safe(0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -146,6 +312,16 @@ void scc68070_device::device_start()
|
||||
save_item(NAME(m_i2c.status_register));
|
||||
save_item(NAME(m_i2c.control_register));
|
||||
save_item(NAME(m_i2c.clock_control_register));
|
||||
save_item(NAME(m_i2c.scl_out_state));
|
||||
save_item(NAME(m_i2c.scl_in_state));
|
||||
save_item(NAME(m_i2c.sda_out_state));
|
||||
save_item(NAME(m_i2c.sda_in_state));
|
||||
save_item(NAME(m_i2c.state));
|
||||
save_item(NAME(m_i2c.counter));
|
||||
save_item(NAME(m_i2c.clock_change_state));
|
||||
save_item(NAME(m_i2c.clocks));
|
||||
save_item(NAME(m_i2c.first_byte));
|
||||
save_item(NAME(m_i2c.ack_or_nak_sent));
|
||||
|
||||
save_item(NAME(m_uart.mode_register));
|
||||
save_item(NAME(m_uart.status_register));
|
||||
@ -191,6 +367,9 @@ void scc68070_device::device_start()
|
||||
|
||||
m_uart.tx_timer = timer_alloc(FUNC(scc68070_device::tx_callback), this);
|
||||
m_uart.tx_timer->adjust(attotime::never);
|
||||
|
||||
m_i2c.timer = timer_alloc(FUNC(scc68070_device::i2c_callback), this);
|
||||
m_i2c.timer->adjust(attotime::never);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -212,9 +391,15 @@ void scc68070_device::device_reset()
|
||||
|
||||
m_i2c.data_register = 0;
|
||||
m_i2c.address_register = 0;
|
||||
m_i2c.status_register = 0;
|
||||
m_i2c.status_register = ISR_PIN;
|
||||
m_i2c.control_register = 0;
|
||||
m_i2c.clock_control_register = 0;
|
||||
m_i2c.scl_out_state = true;
|
||||
m_i2c.scl_in_state = true;
|
||||
m_i2c.sda_out_state = true;
|
||||
m_i2c.state = I2C_IDLE;
|
||||
m_i2c.clock_change_state = I2C_SCL_IDLE;
|
||||
m_i2c.clocks = 0;
|
||||
|
||||
m_uart.mode_register = 0;
|
||||
m_uart.status_register = USR_TXRDY;
|
||||
@ -260,7 +445,7 @@ void scc68070_device::device_reset()
|
||||
|
||||
m_uart.rx_timer->adjust(attotime::never);
|
||||
m_uart.tx_timer->adjust(attotime::never);
|
||||
m_timers.timer0_timer->adjust(attotime::never);
|
||||
set_timer_callback(0);
|
||||
}
|
||||
|
||||
void scc68070_device::m68k_reset_peripherals()
|
||||
@ -274,9 +459,15 @@ void scc68070_device::m68k_reset_peripherals()
|
||||
m_uart_rx_int = false;
|
||||
m_uart_tx_int = false;
|
||||
|
||||
m_i2c.status_register = 0;
|
||||
m_i2c.status_register = ISR_PIN;
|
||||
m_i2c.control_register = 0;
|
||||
m_i2c.clock_control_register = 0;
|
||||
m_i2c.scl_out_state = true;
|
||||
m_i2c.scl_in_state = true;
|
||||
m_i2c.sda_out_state = true;
|
||||
m_i2c.state = I2C_IDLE;
|
||||
m_i2c.clock_change_state = I2C_SCL_IDLE;
|
||||
m_i2c.clocks = 0;
|
||||
m_uart.command_register = 0;
|
||||
m_uart.receive_pointer = -1;
|
||||
m_uart.transmit_pointer = -1;
|
||||
@ -291,6 +482,7 @@ void scc68070_device::m68k_reset_peripherals()
|
||||
m_uart.rx_timer->adjust(attotime::never);
|
||||
m_uart.tx_timer->adjust(attotime::never);
|
||||
m_timers.timer0_timer->adjust(attotime::never);
|
||||
m_i2c.timer->adjust(attotime::never);
|
||||
|
||||
update_ipl();
|
||||
}
|
||||
@ -370,7 +562,7 @@ WRITE_LINE_MEMBER(scc68070_device::int2_w)
|
||||
update_ipl();
|
||||
}
|
||||
|
||||
m_int1_line = state;
|
||||
m_int2_line = state;
|
||||
}
|
||||
}
|
||||
|
||||
@ -558,13 +750,41 @@ TIMER_CALLBACK_MEMBER(scc68070_device::tx_callback)
|
||||
uint8_t scc68070_device::lir_r()
|
||||
{
|
||||
// LIR priority level: 80001001
|
||||
return m_lir;
|
||||
return m_lir & 0x77;
|
||||
}
|
||||
|
||||
void scc68070_device::lir_w(uint8_t data)
|
||||
{
|
||||
LOGMASKED(LOG_IRQS, "%s: LIR Write: %02x\n", machine().describe_context(), data);
|
||||
m_lir = data;
|
||||
|
||||
switch (data & 0x88)
|
||||
{
|
||||
case 0x08:
|
||||
if (m_lir & 0x08)
|
||||
{
|
||||
m_lir &= 0xf7;
|
||||
update_ipl();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
if (data & 0x80)
|
||||
{
|
||||
m_lir &= 0x7f;
|
||||
update_ipl();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x88:
|
||||
if (data & 0x88)
|
||||
{
|
||||
m_lir &= 0x77;
|
||||
update_ipl();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_lir = (m_lir & 0x88) | (data & 0x77);
|
||||
}
|
||||
|
||||
uint8_t scc68070_device::picr1_r()
|
||||
@ -654,6 +874,35 @@ uint8_t scc68070_device::idr_r()
|
||||
// I2C data register: 80002001
|
||||
if (!machine().side_effects_disabled())
|
||||
LOGMASKED(LOG_I2C, "%s: I2C Data Register Read: %02x\n", machine().describe_context(), m_i2c.data_register);
|
||||
|
||||
m_i2c.counter = 0;
|
||||
m_i2c.status_register |= ISR_PIN;
|
||||
m_i2c_int = false;
|
||||
update_ipl();
|
||||
|
||||
if (m_i2c.state != I2C_RX_COMPLETE)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.sda_out_state = (m_i2c.control_register & ICR_ACK) ? false : true;
|
||||
m_i2c_sdaw_callback(m_i2c.sda_out_state);
|
||||
|
||||
if (m_i2c.control_register & ICR_ACK)
|
||||
{
|
||||
m_i2c.state = I2C_SEND_ACK_AND_RX;
|
||||
m_i2c.clocks = 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.state = I2C_SEND_ACK;
|
||||
m_i2c.clocks = 1;
|
||||
}
|
||||
m_i2c.ack_or_nak_sent = true;
|
||||
m_i2c.clock_change_state = I2C_SCL_SET_1;
|
||||
set_i2c_timer();
|
||||
|
||||
}
|
||||
return m_i2c.data_register;
|
||||
}
|
||||
|
||||
@ -661,6 +910,18 @@ void scc68070_device::idr_w(uint8_t data)
|
||||
{
|
||||
LOGMASKED(LOG_I2C, "%s: I2C Data Register Write: %02x\n", machine().describe_context(), data);
|
||||
m_i2c.data_register = data;
|
||||
if (m_i2c.status_register & ISR_MST && m_i2c.status_register & ISR_TRX && m_i2c.status_register & ISR_BB)
|
||||
{
|
||||
m_i2c.status_register |= ISR_PIN;
|
||||
m_i2c_int = false;
|
||||
update_ipl();
|
||||
m_i2c.counter = 0;
|
||||
m_i2c.state = I2C_TX_IN_PROGRESS;
|
||||
m_i2c.clocks = 9;
|
||||
i2c_process_falling_scl();
|
||||
m_i2c.clock_change_state = I2C_SCL_SET_1;
|
||||
set_i2c_timer();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t scc68070_device::iar_r()
|
||||
@ -682,13 +943,154 @@ uint8_t scc68070_device::isr_r()
|
||||
// I2C status register: 80002005
|
||||
if (!machine().side_effects_disabled())
|
||||
LOGMASKED(LOG_I2C, "%s: I2C Status Register Read: %02x\n", machine().describe_context(), m_i2c.status_register);
|
||||
return m_i2c.status_register & 0xef; // hack for magicard
|
||||
return m_i2c.status_register;
|
||||
}
|
||||
|
||||
void scc68070_device::isr_w(uint8_t data)
|
||||
{
|
||||
LOGMASKED(LOG_I2C, "%s: I2C Status Register Write: %02x\n", machine().describe_context(), data);
|
||||
m_i2c.status_register = data;
|
||||
if (data & ISR_MST)
|
||||
{
|
||||
if ((data & ISR_SSR_MASK) == ISR_START)
|
||||
{
|
||||
if ((m_i2c.status_register & ISR_SSR_MASK) == ISR_STOP || (m_i2c.status_register & ISR_SSR_MASK) == 0)
|
||||
{
|
||||
if (m_i2c_sdar_callback() && m_i2c.state == I2C_IDLE)
|
||||
{
|
||||
m_i2c.status_register = data;
|
||||
if (data & ISR_PIN)
|
||||
{
|
||||
m_i2c_int = false;
|
||||
update_ipl();
|
||||
}
|
||||
m_i2c.sda_out_state = false;
|
||||
m_i2c_sdaw_callback(false);
|
||||
m_i2c.clock_change_state = I2C_SCL_SET_0;
|
||||
m_i2c.clocks = 10;
|
||||
m_i2c.state = I2C_TX_IN_PROGRESS;
|
||||
m_i2c.first_byte = true;
|
||||
m_i2c.ack_or_nak_sent = false;
|
||||
set_i2c_timer();
|
||||
m_i2c.counter = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.status_register |= ISR_AL;
|
||||
m_i2c.status_register &= ~ISR_PIN;
|
||||
m_i2c_int = true;
|
||||
update_ipl();
|
||||
}
|
||||
}
|
||||
else if ((m_i2c.status_register & ISR_SSR_MASK) == ISR_MST)
|
||||
{
|
||||
m_i2c.status_register = data;
|
||||
if (data & ISR_PIN)
|
||||
{
|
||||
m_i2c_int = false;
|
||||
update_ipl();
|
||||
}
|
||||
m_i2c.sda_out_state = true;
|
||||
m_i2c_sdaw_callback(true);
|
||||
m_i2c.clock_change_state = I2C_SCL_SET_1;
|
||||
m_i2c.clocks = 10;
|
||||
m_i2c.state = I2C_SEND_RESTART;
|
||||
m_i2c.first_byte = true;
|
||||
m_i2c.ack_or_nak_sent = false;
|
||||
set_i2c_timer();
|
||||
m_i2c.counter = 0;
|
||||
}
|
||||
}
|
||||
else if ((data & ISR_SSR_MASK) == ISR_STOP && m_i2c.status_register & ISR_BB)
|
||||
{
|
||||
// we should send STOP here, however, unkte06 in magicard appears to expect
|
||||
// NAK followed by STOP when in read mode.
|
||||
|
||||
if (data & ISR_PIN)
|
||||
{
|
||||
m_i2c_int = false;
|
||||
update_ipl();
|
||||
}
|
||||
|
||||
if (m_i2c.ack_or_nak_sent || (m_i2c.status_register & ISR_TRX))
|
||||
{
|
||||
m_i2c.state = I2C_SEND_STOP;
|
||||
m_i2c.sda_out_state = false;
|
||||
m_i2c_sdaw_callback(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.ack_or_nak_sent = true;
|
||||
m_i2c.sda_out_state = (m_i2c.control_register&ICR_ACK) ? false : true;
|
||||
m_i2c_sdaw_callback(m_i2c.sda_out_state);
|
||||
m_i2c.state = I2C_SEND_ACK_AND_STOP;
|
||||
m_i2c.clocks = 2;
|
||||
}
|
||||
m_i2c.status_register = data | ISR_BB;
|
||||
m_i2c.clock_change_state = I2C_SCL_SET_1;
|
||||
set_i2c_timer();
|
||||
}
|
||||
else if ((data & ISR_SSR_MASK) == ISR_MST)
|
||||
{
|
||||
m_i2c.status_register = data;
|
||||
if (data & ISR_PIN)
|
||||
{
|
||||
m_i2c_int = false;
|
||||
update_ipl();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data & ISR_PIN && !(m_i2c.status_register & ISR_PIN))
|
||||
{
|
||||
if (m_i2c.state == I2C_CHANGED_TO_RX)
|
||||
{
|
||||
m_i2c.state = I2C_RX_IN_PROGRESS;
|
||||
m_i2c.clock_change_state = I2C_SCL_SET_1;
|
||||
m_i2c.status_register = data;
|
||||
m_i2c_int = false;
|
||||
update_ipl();
|
||||
m_i2c.counter = 0;
|
||||
m_i2c.clocks = 8;
|
||||
set_i2c_timer();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.ack_or_nak_sent = true;
|
||||
m_i2c.sda_out_state = (m_i2c.control_register&ICR_ACK) ? false : true;
|
||||
m_i2c_sdaw_callback(m_i2c.sda_out_state);
|
||||
m_i2c.status_register = data;
|
||||
m_i2c_int = false;
|
||||
update_ipl();
|
||||
m_i2c.state = I2C_SEND_ACK;
|
||||
m_i2c.clock_change_state = I2C_SCL_SET_1;
|
||||
m_i2c.clocks = 1;
|
||||
set_i2c_timer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.status_register = data;
|
||||
if (data & ISR_PIN)
|
||||
{
|
||||
m_i2c_int = false;
|
||||
update_ipl();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.status_register = data;
|
||||
m_i2c_int = false;
|
||||
update_ipl();
|
||||
m_i2c.timer->adjust(attotime::never);
|
||||
m_i2c_scl_callback(1);
|
||||
m_i2c_sdaw_callback(1);
|
||||
m_i2c.scl_out_state = true;
|
||||
m_i2c.scl_in_state = true;
|
||||
m_i2c.sda_out_state = true;
|
||||
m_i2c.state = I2C_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t scc68070_device::icr_r()
|
||||
@ -703,6 +1105,17 @@ void scc68070_device::icr_w(uint8_t data)
|
||||
{
|
||||
LOGMASKED(LOG_I2C, "%s: I2C Control Register Write: %02x\n", machine().describe_context(), data);
|
||||
m_i2c.control_register = data;
|
||||
|
||||
if (!(data & ICR_ESO))
|
||||
{
|
||||
m_i2c.timer->adjust(attotime::never);
|
||||
m_i2c_scl_callback(1);
|
||||
m_i2c_sdaw_callback(1);
|
||||
m_i2c.scl_out_state = true;
|
||||
m_i2c.scl_in_state = true;
|
||||
m_i2c.sda_out_state = true;
|
||||
m_i2c.state = I2C_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t scc68070_device::iccr_r()
|
||||
@ -719,6 +1132,200 @@ void scc68070_device::iccr_w(uint8_t data)
|
||||
m_i2c.clock_control_register = data & 0x1f;
|
||||
}
|
||||
|
||||
|
||||
void scc68070_device::i2c_process_falling_scl()
|
||||
{
|
||||
switch (m_i2c.state)
|
||||
{
|
||||
case I2C_TX_IN_PROGRESS:
|
||||
if (m_i2c.counter<8)
|
||||
{
|
||||
m_i2c.sda_out_state = BIT(m_i2c.data_register, 7 - m_i2c.counter);
|
||||
m_i2c_sdaw_callback(m_i2c.sda_out_state);
|
||||
m_i2c.counter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.sda_out_state = true;
|
||||
m_i2c_sdaw_callback(true);
|
||||
m_i2c.state = I2C_GET_ACK;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_GET_ACK:
|
||||
m_i2c.status_register &= ~ISR_PIN;
|
||||
m_i2c_int = true;
|
||||
update_ipl();
|
||||
m_i2c.state = I2C_IDLE;
|
||||
if (m_i2c.first_byte)
|
||||
{
|
||||
m_i2c.first_byte = false;
|
||||
if (BIT(m_i2c.data_register, 0))
|
||||
{
|
||||
m_i2c.status_register &= ~ISR_TRX;
|
||||
if (!(m_i2c.status_register & ISR_LRB))
|
||||
{
|
||||
m_i2c.state = I2C_CHANGED_TO_RX;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_RX_IN_PROGRESS:
|
||||
if (m_i2c.counter >= 8)
|
||||
{
|
||||
m_i2c.status_register &= ~ISR_PIN;
|
||||
m_i2c_int = true;
|
||||
update_ipl();
|
||||
m_i2c.state = I2C_RX_COMPLETE;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SEND_ACK_AND_RX:
|
||||
m_i2c.sda_out_state = true;
|
||||
m_i2c_sdaw_callback(true);
|
||||
m_i2c.state = I2C_RX_IN_PROGRESS;
|
||||
m_i2c.counter = 0;
|
||||
break;
|
||||
|
||||
case I2C_SEND_ACK_AND_STOP:
|
||||
m_i2c.sda_out_state = false;
|
||||
m_i2c_sdaw_callback(false);
|
||||
m_i2c.state = I2C_SEND_STOP;
|
||||
break;
|
||||
|
||||
case I2C_SEND_ACK:
|
||||
m_i2c.state = I2C_IDLE;
|
||||
m_i2c.status_register &= ~ISR_PIN;
|
||||
m_i2c_int = true;
|
||||
update_ipl();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void scc68070_device::i2c_process_rising_scl()
|
||||
{
|
||||
switch (m_i2c.state)
|
||||
{
|
||||
case I2C_GET_ACK:
|
||||
if (m_i2c_sdar_callback())
|
||||
{
|
||||
m_i2c.status_register |= ISR_LRB;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.status_register &= ~ISR_LRB;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SEND_STOP:
|
||||
case I2C_SEND_RESTART:
|
||||
m_i2c.timer->adjust(attotime::from_nsec(5000));
|
||||
break;
|
||||
|
||||
case I2C_RX_IN_PROGRESS:
|
||||
if (m_i2c.counter < 8)
|
||||
{
|
||||
m_i2c.data_register <<= 1;
|
||||
m_i2c.data_register |= m_i2c_sdar_callback();
|
||||
m_i2c.counter++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(scc68070_device::write_scl)
|
||||
{
|
||||
if (m_i2c.status_register & ISR_MST)
|
||||
{
|
||||
if (m_i2c.scl_in_state != state && state)
|
||||
{
|
||||
i2c_process_rising_scl();
|
||||
i2c_next_state();
|
||||
}
|
||||
}
|
||||
m_i2c.scl_in_state = state;
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(scc68070_device::i2c_callback)
|
||||
{
|
||||
i2c_next_state();
|
||||
}
|
||||
|
||||
void scc68070_device::i2c_next_state()
|
||||
{
|
||||
switch (m_i2c.clock_change_state)
|
||||
{
|
||||
case I2C_SCL_SET_0:
|
||||
if (m_i2c.state == I2C_SEND_STOP)
|
||||
{
|
||||
if (!m_i2c.sda_out_state)
|
||||
{
|
||||
m_i2c.sda_out_state = true;
|
||||
m_i2c_sdaw_callback(true);
|
||||
set_i2c_timer();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.state = I2C_IDLE;
|
||||
m_i2c.status_register &= ~(ISR_PIN | ISR_BB);
|
||||
m_i2c_int = true;
|
||||
update_ipl();
|
||||
m_i2c.clock_change_state = I2C_SCL_IDLE;
|
||||
}
|
||||
}
|
||||
else if (m_i2c.state == I2C_SEND_RESTART)
|
||||
{
|
||||
m_i2c.sda_out_state = false;
|
||||
m_i2c_sdaw_callback(false);
|
||||
set_i2c_timer();
|
||||
m_i2c.clock_change_state = I2C_SCL_SET_0;
|
||||
m_i2c.state = I2C_TX_IN_PROGRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c.scl_out_state = false;
|
||||
m_i2c_scl_callback(false);
|
||||
if (m_i2c.clocks)
|
||||
{
|
||||
m_i2c.clocks--;
|
||||
}
|
||||
if (m_i2c.clocks == 0)
|
||||
{
|
||||
m_i2c.clock_change_state = I2C_SCL_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
set_i2c_timer();
|
||||
m_i2c.clock_change_state = I2C_SCL_SET_1;
|
||||
}
|
||||
i2c_process_falling_scl();
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SCL_SET_1:
|
||||
m_i2c.clock_change_state = I2C_SCL_WAIT_1;
|
||||
m_i2c.scl_out_state = true;
|
||||
m_i2c_scl_callback(true);
|
||||
break;
|
||||
|
||||
case I2C_SCL_WAIT_1:
|
||||
set_i2c_timer();
|
||||
m_i2c.clock_change_state = I2C_SCL_SET_0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void scc68070_device::set_i2c_timer()
|
||||
{
|
||||
// divider offset 0 entry is illegal
|
||||
static constexpr int divider[]={ 1, 78, 90, 102, 126, 150, 174, 198,
|
||||
246, 294, 342, 390, 486, 582, 678, 774,
|
||||
996, 1158, 1350, 1542, 1926, 2310, 2694, 3078,
|
||||
3846, 4614, 5382, 6150, 7686, 9222, 10758, 12294 };
|
||||
m_i2c.timer->adjust(cycles_to_attotime(divider[m_i2c.clock_control_register]));
|
||||
}
|
||||
|
||||
uint8_t scc68070_device::umr_r()
|
||||
{
|
||||
// UART mode register: 80002011
|
||||
@ -870,7 +1477,8 @@ uint16_t scc68070_device::timer_r(offs_t offset, uint16_t mem_mask)
|
||||
case 0x4/2:
|
||||
if (!machine().side_effects_disabled())
|
||||
LOGMASKED(LOG_TIMERS, "%s: Timer 0 Read: %04x & %04x\n", machine().describe_context(), m_timers.timer0, mem_mask);
|
||||
return m_timers.timer0;
|
||||
return 0x10000 - (attotime_to_cycles(m_timers.timer0_timer->remaining()) / 96);
|
||||
|
||||
case 0x6/2:
|
||||
if (!machine().side_effects_disabled())
|
||||
LOGMASKED(LOG_TIMERS, "%s: Timer 1 Read: %04x & %04x\n", machine().describe_context(), m_timers.timer1, mem_mask);
|
||||
@ -908,6 +1516,7 @@ void scc68070_device::timer_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
case 0x2/2:
|
||||
LOGMASKED(LOG_TIMERS, "%s: Timer Reload Register Write: %04x & %04x\n", machine().describe_context(), data, mem_mask);
|
||||
COMBINE_DATA(&m_timers.reload_register);
|
||||
set_timer_callback(0);
|
||||
break;
|
||||
case 0x4/2:
|
||||
LOGMASKED(LOG_TIMERS, "%s: Timer 0 Write: %04x & %04x\n", machine().describe_context(), data, mem_mask);
|
||||
|
@ -28,105 +28,18 @@ TODO:
|
||||
|
||||
#include "cpu/m68000/m68000.h"
|
||||
|
||||
|
||||
#define ISR_MST 0x80 // Master
|
||||
#define ISR_TRX 0x40 // Transmitter
|
||||
#define ISR_BB 0x20 // Busy
|
||||
#define ISR_PIN 0x10 // No Pending Interrupt
|
||||
#define ISR_AL 0x08 // Arbitration Lost
|
||||
#define ISR_AAS 0x04 // Addressed As Slave
|
||||
#define ISR_AD0 0x02 // Address Zero
|
||||
#define ISR_LRB 0x01 // Last Received Bit
|
||||
|
||||
#define UMR_OM 0xc0
|
||||
#define UMR_OM_NORMAL 0x00
|
||||
#define UMR_OM_ECHO 0x40
|
||||
#define UMR_OM_LOOPBACK 0x80
|
||||
#define UMR_OM_RLOOP 0xc0
|
||||
#define UMR_TXC 0x10
|
||||
#define UMR_PC 0x08
|
||||
#define UMR_P 0x04
|
||||
#define UMR_SB 0x02
|
||||
#define UMR_CL 0x01
|
||||
|
||||
#define USR_RB 0x80
|
||||
#define USR_FE 0x40
|
||||
#define USR_PE 0x20
|
||||
#define USR_OE 0x10
|
||||
#define USR_TXEMT 0x08
|
||||
#define USR_TXRDY 0x04
|
||||
#define USR_RXRDY 0x01
|
||||
|
||||
#define TSR_OV0 0x80
|
||||
#define TSR_MA1 0x40
|
||||
#define TSR_CAP1 0x20
|
||||
#define TSR_OV1 0x10
|
||||
#define TSR_MA2 0x08
|
||||
#define TSR_CAP2 0x04
|
||||
#define TSR_OV2 0x02
|
||||
|
||||
#define TCR_E1 0xc0
|
||||
#define TCR_E1_NONE 0x00
|
||||
#define TCR_E1_RISING 0x40
|
||||
#define TCR_E1_FALLING 0x80
|
||||
#define TCR_E1_BOTH 0xc0
|
||||
#define TCR_M1 0x30
|
||||
#define TCR_M1_NONE 0x00
|
||||
#define TCR_M1_MATCH 0x10
|
||||
#define TCR_M1_CAPTURE 0x20
|
||||
#define TCR_M1_COUNT 0x30
|
||||
#define TCR_E2 0x0c
|
||||
#define TCR_E2_NONE 0x00
|
||||
#define TCR_E2_RISING 0x04
|
||||
#define TCR_E2_FALLING 0x08
|
||||
#define TCR_E2_BOTH 0x0c
|
||||
#define TCR_M2 0x03
|
||||
#define TCR_M2_NONE 0x00
|
||||
#define TCR_M2_MATCH 0x01
|
||||
#define TCR_M2_CAPTURE 0x02
|
||||
#define TCR_M2_COUNT 0x03
|
||||
|
||||
#define CSR_COC 0x80
|
||||
#define CSR_NDT 0x20
|
||||
#define CSR_ERR 0x10
|
||||
#define CSR_CA 0x08
|
||||
|
||||
#define CER_EC 0x1f
|
||||
#define CER_NONE 0x00
|
||||
#define CER_TIMING 0x02
|
||||
#define CER_BUSERR_MEM 0x09
|
||||
#define CER_BUSERR_DEV 0x0a
|
||||
#define CER_SOFT_ABORT 0x11
|
||||
|
||||
#define DCR1_ERM 0x80
|
||||
#define DCR1_DT 0x30
|
||||
|
||||
#define DCR2_ERM 0x80
|
||||
#define DCR2_DT 0x30
|
||||
#define DCR2_DS 0x08
|
||||
|
||||
#define OCR_D 0x80
|
||||
#define OCR_D_M2D 0x00
|
||||
#define OCR_D_D2M 0x80
|
||||
#define OCR_OS 0x30
|
||||
#define OCR_OS_BYTE 0x00
|
||||
#define OCR_OS_WORD 0x10
|
||||
|
||||
#define SCR2_MAC 0x0c
|
||||
#define SCR2_MAC_NONE 0x00
|
||||
#define SCR2_MAC_INC 0x04
|
||||
#define SCR2_DAC 0x03
|
||||
#define SCR2_DAC_NONE 0x00
|
||||
#define SCR2_DAC_INC 0x01
|
||||
|
||||
#define CCR_SO 0x80
|
||||
#define CCR_SA 0x10
|
||||
#define CCR_INE 0x08
|
||||
#define CCR_IPL 0x07
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
enum scc68070_ocr_bits
|
||||
{
|
||||
SCC68070_OCR_D = 0x80,
|
||||
SCC68070_OCR_D_M2D = 0x00,
|
||||
SCC68070_OCR_D_D2M = 0x80,
|
||||
SCC68070_OCR_OS = 0x30,
|
||||
SCC68070_OCR_OS_BYTE = 0x00,
|
||||
SCC68070_OCR_OS_WORD = 0x10
|
||||
};
|
||||
|
||||
// ======================> scc68070_device
|
||||
|
||||
@ -141,6 +54,9 @@ public:
|
||||
auto iack7_callback() { return m_iack7_callback.bind(); }
|
||||
auto uart_tx_callback() { return m_uart_tx_callback.bind(); }
|
||||
auto uart_rtsn_callback() { return m_uart_rtsn_callback.bind(); }
|
||||
auto i2c_scl_w() { return m_i2c_scl_callback.bind(); }
|
||||
auto i2c_sda_w() { return m_i2c_sdaw_callback.bind(); }
|
||||
auto i2c_sda_r() { return m_i2c_sdar_callback.bind(); }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(in2_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(in4_w);
|
||||
@ -149,9 +65,12 @@ public:
|
||||
DECLARE_WRITE_LINE_MEMBER(int1_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(int2_w);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(write_scl);
|
||||
|
||||
TIMER_CALLBACK_MEMBER(timer0_callback);
|
||||
TIMER_CALLBACK_MEMBER(rx_callback);
|
||||
TIMER_CALLBACK_MEMBER(tx_callback);
|
||||
TIMER_CALLBACK_MEMBER(i2c_callback);
|
||||
|
||||
// external callbacks
|
||||
void uart_rx(uint8_t data);
|
||||
@ -170,6 +89,17 @@ public:
|
||||
uint8_t control_register;
|
||||
uint8_t reserved;
|
||||
uint8_t clock_control_register;
|
||||
emu_timer* timer;
|
||||
bool scl_out_state;
|
||||
bool scl_in_state;
|
||||
bool sda_out_state;
|
||||
bool sda_in_state;
|
||||
uint8_t clock_change_state;
|
||||
uint8_t clocks;
|
||||
uint8_t state;
|
||||
uint8_t counter;
|
||||
bool first_byte;
|
||||
bool ack_or_nak_sent;
|
||||
};
|
||||
|
||||
struct uart_regs_t
|
||||
@ -298,6 +228,10 @@ private:
|
||||
void icr_w(uint8_t data);
|
||||
uint8_t iccr_r();
|
||||
void iccr_w(uint8_t data);
|
||||
void set_i2c_timer();
|
||||
void i2c_process_falling_scl();
|
||||
void i2c_process_rising_scl();
|
||||
void i2c_next_state();
|
||||
|
||||
// UART interface
|
||||
uint8_t umr_r();
|
||||
@ -336,6 +270,9 @@ private:
|
||||
devcb_read8 m_iack7_callback;
|
||||
devcb_write8 m_uart_tx_callback;
|
||||
devcb_write_line m_uart_rtsn_callback;
|
||||
devcb_write_line m_i2c_scl_callback;
|
||||
devcb_write_line m_i2c_sdaw_callback;
|
||||
devcb_read8 m_i2c_sdar_callback;
|
||||
|
||||
// internal state
|
||||
uint8_t m_ipl;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1313,10 +1313,10 @@ void cdicdic_device::regs_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
uint16_t *ram = (uint16_t *)m_ram.get();
|
||||
LOGMASKED(LOG_WRITES, "%s: cdic_w: DMA Control Register = %04x & %04x\n", machine().describe_context(), data, mem_mask);
|
||||
LOGMASKED(LOG_WRITES, "%s: Memory address counter: %08x\n", machine().describe_context(), m_scc->dma().channel[0].memory_address_counter);
|
||||
LOGMASKED(LOG_WRITES, "%s: Doing copy, transferring %04x bytes %s\n", machine().describe_context(), count * 2, (m_scc->dma().channel[0].operation_control & OCR_D) ? "to main RAM" : "to device RAM");
|
||||
LOGMASKED(LOG_WRITES, "%s: Doing copy, transferring %04x bytes %s\n", machine().describe_context(), count * 2, (m_scc->dma().channel[0].operation_control & SCC68070_OCR_D) ? "to main RAM" : "to device RAM");
|
||||
for (uint32_t index = start / 2; index < (start / 2 + count); index++)
|
||||
{
|
||||
if (m_scc->dma().channel[0].operation_control & OCR_D)
|
||||
if (m_scc->dma().channel[0].operation_control & SCC68070_OCR_D)
|
||||
{
|
||||
m_memory_space->write_word(index * 2, ram[device_index++]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user