mirror of
https://github.com/holub/mame
synced 2025-04-20 15:32:45 +03:00
video/saa5240.cpp: Decode national character sets.
- Cursor rendered when enabled. - Implemented clear memory register. - Only acknowledge correct I2C device Id.
This commit is contained in:
parent
e7ed19e2da
commit
e45679e227
@ -2,17 +2,23 @@
|
||||
// copyright-holders:Nigel Barnes
|
||||
/*********************************************************************
|
||||
|
||||
Philips SAA5240 European Controlled Teletext Circuit
|
||||
Philips SAA5240 European Controlled Teletext Circuit (CCT)
|
||||
|
||||
TODO:
|
||||
- implement data acquisition.
|
||||
- output interlaced video.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "saa5240.h"
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define LOG_DATA (1U << 1)
|
||||
#define LOG_LINE (1U << 2)
|
||||
|
||||
#define VERBOSE (LOG_DATA)
|
||||
#define VERBOSE (0)
|
||||
#include "logmacro.h"
|
||||
|
||||
|
||||
@ -22,44 +28,22 @@ DEFINE_DEVICE_TYPE(SAA5243E, saa5243e_device, "saa5243e", "SAA5243E EURO CCT")
|
||||
//DEFINE_DEVICE_TYPE(SAA5243H, saa5243h_device, "saa5243h", "SAA5243H EURO CCT")
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// default address map
|
||||
//-------------------------------------------------
|
||||
|
||||
void saa5240_device::saa5240_vram(address_map &map)
|
||||
{
|
||||
if (!has_configured_map(0))
|
||||
map(0x0000, 0x1fff).ram();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// memory_space_config - return a description of
|
||||
// any address spaces owned by this device
|
||||
//-------------------------------------------------
|
||||
|
||||
device_memory_interface::space_config_vector saa5240_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector {
|
||||
std::make_pair(0, &m_space_config)
|
||||
};
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// ROM( saa5240 )
|
||||
//-------------------------------------------------
|
||||
|
||||
ROM_START( saa5240a )
|
||||
ROM_REGION16_BE( 0xc80, "chargen", ROMREGION_ERASE00 )
|
||||
ROM_START(saa5240a)
|
||||
ROM_REGION16_BE(0xc80, "chargen", ROMREGION_ERASE00)
|
||||
ROM_LOAD("saa5240a", 0x0280, 0x0a00, BAD_DUMP CRC(e205d1fc) SHA1(cb6872260c91f0665f8c7d691c9becc327e0ecc3)) // hand made from datasheet
|
||||
ROM_END
|
||||
|
||||
ROM_START( saa5240b )
|
||||
ROM_REGION16_BE( 0xc80, "chargen", ROMREGION_ERASE00 )
|
||||
ROM_START(saa5240b)
|
||||
ROM_REGION16_BE(0xc80, "chargen", ROMREGION_ERASE00)
|
||||
ROM_LOAD("saa5240b", 0x0280, 0x0a00, BAD_DUMP CRC(7b196f2c) SHA1(61d4460ed0956ff470cc1362ea6bb1f9abe4bc03)) // hand made from datasheet
|
||||
ROM_END
|
||||
|
||||
ROM_START( saa5243e )
|
||||
ROM_REGION16_BE( 0x1180, "chargen", ROMREGION_ERASE00 )
|
||||
ROM_START(saa5243e)
|
||||
ROM_REGION16_BE(0x1180, "chargen", ROMREGION_ERASE00)
|
||||
ROM_LOAD("saa5243e", 0x0280, 0x0f00, BAD_DUMP CRC(a74402e7) SHA1(48123c9bb0377e417a147f5a68088c1ed7bee12d)) // hand made from datasheet
|
||||
ROM_END
|
||||
|
||||
@ -70,26 +54,20 @@ ROM_END
|
||||
|
||||
const tiny_rom_entry *saa5240a_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME( saa5240a );
|
||||
return ROM_NAME(saa5240a);
|
||||
}
|
||||
|
||||
const tiny_rom_entry *saa5240b_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME( saa5240b );
|
||||
return ROM_NAME(saa5240b);
|
||||
}
|
||||
|
||||
const tiny_rom_entry *saa5243e_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME( saa5243e );
|
||||
return ROM_NAME(saa5243e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ALPHANUMERIC 0x01
|
||||
#define CONTIGUOUS 0x02
|
||||
#define SEPARATED 0x03
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
@ -100,9 +78,8 @@ const tiny_rom_entry *saa5243e_device::device_rom_region() const
|
||||
|
||||
saa5240_device::saa5240_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, device_memory_interface(mconfig, *this)
|
||||
, m_char_rom(*this, "chargen")
|
||||
, m_space_config("videoram", ENDIANNESS_LITTLE, 8, 13, 0, address_map_constructor(FUNC(saa5240a_device::saa5240_vram), this))
|
||||
, m_ram_size(0x2000)
|
||||
, m_slave_address(SAA5240_SLAVE_ADDRESS)
|
||||
, m_i2c_scl(0)
|
||||
, m_i2c_sdaw(0)
|
||||
@ -115,18 +92,18 @@ saa5240_device::saa5240_device(const machine_config &mconfig, device_type type,
|
||||
{
|
||||
}
|
||||
|
||||
saa5240a_device::saa5240a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
saa5240_device(mconfig, SAA5240A, tag, owner, clock)
|
||||
saa5240a_device::saa5240a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: saa5240_device(mconfig, SAA5240A, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
saa5240b_device::saa5240b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
saa5240_device(mconfig, SAA5240B, tag, owner, clock)
|
||||
saa5240b_device::saa5240b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: saa5240_device(mconfig, SAA5240B, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
saa5243e_device::saa5243e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
saa5240_device(mconfig, SAA5243E, tag, owner, clock)
|
||||
saa5243e_device::saa5243e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: saa5240_device(mconfig, SAA5243E, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
@ -137,9 +114,21 @@ saa5243e_device::saa5243e_device(const machine_config &mconfig, const char *tag,
|
||||
|
||||
void saa5240_device::device_start()
|
||||
{
|
||||
m_videoram = &space(0);
|
||||
m_ram = make_unique_clear<uint8_t[]>(m_ram_size);
|
||||
|
||||
// memory is cleared to 'space' on power-up
|
||||
std::memset(m_ram.get(), 0x20, m_ram_size);
|
||||
|
||||
// row 0 column 7 chapter 0 is alpha white
|
||||
m_ram[0x07] = 0x07;
|
||||
|
||||
// registers cleared on power-up, except R5 and R6
|
||||
std::fill(std::begin(m_register), std::end(m_register), 0x00);
|
||||
m_register[5] = 0x03;
|
||||
m_register[6] = 0x03;
|
||||
|
||||
// state saving
|
||||
save_pointer(NAME(m_ram), m_ram_size);
|
||||
save_item(NAME(m_i2c_scl));
|
||||
save_item(NAME(m_i2c_sdaw));
|
||||
save_item(NAME(m_i2c_sdar));
|
||||
@ -152,21 +141,6 @@ void saa5240_device::device_start()
|
||||
save_item(NAME(m_slave_address));
|
||||
}
|
||||
|
||||
void saa5240_device::device_reset()
|
||||
{
|
||||
// memmory is cleared to 'space' on power-up
|
||||
for (int i = 0; i < 0x1fff; i++)
|
||||
m_videoram->write_byte(i, 0x20);
|
||||
|
||||
// row 0 column 7 chapter 0 is alpha white
|
||||
m_videoram->write_byte(7, 0x07);
|
||||
|
||||
// reset registers
|
||||
std::fill(std::begin(m_register), std::end(m_register), 0x00);
|
||||
m_register[5] = 0x03;
|
||||
m_register[6] = 0x03;
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// READ/WRITE HANDLERS
|
||||
@ -196,78 +170,86 @@ void saa5240_device::write_scl(int state)
|
||||
{
|
||||
if (m_i2c_scl)
|
||||
{
|
||||
switch (m_i2c_state)
|
||||
{
|
||||
case STATE_DEVSEL:
|
||||
m_i2c_devsel = m_i2c_shift;
|
||||
|
||||
if ((m_i2c_devsel & 0xfe) != m_slave_address)
|
||||
{
|
||||
LOGMASKED(LOG_DATA, "devsel %02x: not this device\n", m_i2c_devsel);
|
||||
m_i2c_state = STATE_IDLE;
|
||||
}
|
||||
else if ((m_i2c_devsel & 1) == 0)
|
||||
{
|
||||
LOGMASKED(LOG_DATA, "devsel %02x: write\n", m_i2c_devsel);
|
||||
m_i2c_state = STATE_ADDRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_DATA, "devsel %02x: read\n", m_i2c_devsel);
|
||||
m_i2c_state = STATE_DATAOUT;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_ADDRESS:
|
||||
m_i2c_address = m_i2c_shift;
|
||||
LOGMASKED(LOG_DATA, "address %02x\n", m_i2c_shift);
|
||||
|
||||
m_i2c_state = STATE_DATAIN;
|
||||
break;
|
||||
|
||||
case STATE_DATAIN:
|
||||
m_register[m_i2c_address] = m_i2c_shift;
|
||||
LOGMASKED(LOG_DATA, "data[ %02x ] <- %02x\n", m_i2c_address, m_i2c_shift);
|
||||
|
||||
switch (m_i2c_address)
|
||||
{
|
||||
case 1: case 2: case 3: case 4: case 5: case 6:
|
||||
// auto-increment register
|
||||
m_i2c_address++;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
// active chapter - clear memory
|
||||
//if (BIT(m_register[8], 3))
|
||||
//{
|
||||
// for (int i = 0; i < 0x3ff; i++)
|
||||
// m_videoram->write_byte((m_register[8] & 0x07) * 0x400 + i, 0x20);
|
||||
//}
|
||||
[[fallthrough]];
|
||||
case 9: case 10:
|
||||
update_active_data();
|
||||
|
||||
// auto-increment register
|
||||
m_i2c_address++;
|
||||
break;
|
||||
case 11:
|
||||
// active data
|
||||
offs_t offset = (m_register[8] & 0x07) * 0x400 + (m_register[9] & 0x1f) * 40 + (m_register[10] & 0x3f);
|
||||
m_videoram->write_byte(offset, m_i2c_shift);
|
||||
|
||||
increment_active_data();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_i2c_bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_i2c_bits == 8)
|
||||
{
|
||||
m_i2c_sdar = 0;
|
||||
switch (m_i2c_state)
|
||||
{
|
||||
case STATE_DEVSEL:
|
||||
m_i2c_devsel = m_i2c_shift;
|
||||
|
||||
if ((m_i2c_devsel & 0xfe) != m_slave_address)
|
||||
{
|
||||
LOGMASKED(LOG_DATA, "devsel %02x: not this device\n", m_i2c_devsel);
|
||||
m_i2c_state = STATE_IDLE;
|
||||
}
|
||||
else if ((m_i2c_devsel & 1) == 0)
|
||||
{
|
||||
LOGMASKED(LOG_DATA, "devsel %02x: write\n", m_i2c_devsel);
|
||||
m_i2c_state = STATE_ADDRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_DATA, "devsel %02x: read\n", m_i2c_devsel);
|
||||
m_i2c_state = STATE_READSELACK;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_ADDRESS:
|
||||
m_i2c_address = m_i2c_shift;
|
||||
LOGMASKED(LOG_DATA, "address %02x\n", m_i2c_shift);
|
||||
|
||||
m_i2c_state = STATE_DATAIN;
|
||||
break;
|
||||
|
||||
case STATE_DATAIN:
|
||||
m_register[m_i2c_address] = m_i2c_shift;
|
||||
LOGMASKED(LOG_DATA, "data[ %02x ] <- %02x\n", m_i2c_address, m_i2c_shift);
|
||||
|
||||
switch (m_i2c_address)
|
||||
{
|
||||
case 1: // Mode
|
||||
case 2: // Page request address
|
||||
case 3: // Page request data
|
||||
case 4: // Display chapter
|
||||
case 5: // Display control (normal)
|
||||
case 6: // Display control (newsflash/subtitle)
|
||||
m_i2c_address++; // auto-increment register
|
||||
break;
|
||||
|
||||
case 7: // Display mode
|
||||
break;
|
||||
|
||||
case 8: // Active chapter
|
||||
if (BIT(m_register[8], 3))
|
||||
{
|
||||
// clear memory
|
||||
for (int i = 0; i < 0x400; i++)
|
||||
m_ram[ram_addr(m_register[8], 0, 0) + i] = 0x20;
|
||||
}
|
||||
[[fallthrough]];
|
||||
|
||||
case 9: // Active row
|
||||
case 10: // Active column
|
||||
update_active_data();
|
||||
m_i2c_address++; // auto-increment register
|
||||
break;
|
||||
|
||||
case 11: // Active data
|
||||
m_ram[ram_addr(m_register[8], m_register[9], m_register[10])] = m_i2c_shift;
|
||||
increment_active_data();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_i2c_state != STATE_IDLE)
|
||||
{
|
||||
m_i2c_sdar = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -278,10 +260,19 @@ void saa5240_device::write_scl(int state)
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READSELACK:
|
||||
m_i2c_bits = 0;
|
||||
m_i2c_state = STATE_DATAOUT;
|
||||
break;
|
||||
|
||||
case STATE_DATAOUT:
|
||||
if (m_i2c_bits < 8)
|
||||
{
|
||||
if (m_i2c_scl)
|
||||
{
|
||||
m_i2c_bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_i2c_bits == 0)
|
||||
{
|
||||
@ -291,8 +282,7 @@ void saa5240_device::write_scl(int state)
|
||||
if (m_i2c_address == 11)
|
||||
increment_active_data();
|
||||
|
||||
// FIXME: is this conditional?
|
||||
if (BIT(m_register[1], 6))
|
||||
if (!BIT(m_register[1], 6))
|
||||
{
|
||||
// 7 bits with parity checking
|
||||
m_i2c_shift &= 0x7f;
|
||||
@ -303,7 +293,6 @@ void saa5240_device::write_scl(int state)
|
||||
m_i2c_sdar = (m_i2c_shift >> 7) & 1;
|
||||
|
||||
m_i2c_shift = (m_i2c_shift << 1) & 0xff;
|
||||
m_i2c_bits++;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -316,18 +305,12 @@ void saa5240_device::write_scl(int state)
|
||||
m_i2c_state = STATE_IDLE;
|
||||
}
|
||||
|
||||
m_i2c_bits++;
|
||||
m_i2c_bits = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_i2c_bits == 8)
|
||||
{
|
||||
m_i2c_sdar = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_i2c_bits = 0;
|
||||
}
|
||||
|
||||
m_i2c_sdar = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -372,6 +355,12 @@ int saa5240_device::read_sda()
|
||||
}
|
||||
|
||||
|
||||
uint16_t saa5240_device::ram_addr(int chapter, int row, int column)
|
||||
{
|
||||
uint16_t addr = (chapter & 0x07) * 0x400 + (row & 0x1f) * 40 + (column & 0x3f);
|
||||
return addr & (m_ram_size - 1);
|
||||
}
|
||||
|
||||
void saa5240_device::increment_active_data()
|
||||
{
|
||||
// auto-increment column
|
||||
@ -388,8 +377,7 @@ void saa5240_device::increment_active_data()
|
||||
|
||||
void saa5240_device::update_active_data()
|
||||
{
|
||||
offs_t offset = (m_register[8] & 0x07) * 0x400 + (m_register[9] & 0x1f) * 40 + (m_register[10] & 0x3f);
|
||||
m_register[11] = m_videoram->read_byte(offset);
|
||||
m_register[11] = m_ram[ram_addr(m_register[8], m_register[9], m_register[10])];
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -400,17 +388,16 @@ int saa5240_device::calc_parity(uint8_t data)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
|
||||
while(data != 0)
|
||||
while (data != 0)
|
||||
{
|
||||
count++;
|
||||
data &= (data-1);
|
||||
data &= (data - 1);
|
||||
}
|
||||
|
||||
return (count ^ 1) & 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// process_control_character
|
||||
//-------------------------------------------------
|
||||
@ -565,16 +552,83 @@ uint16_t saa5240_device::get_gfx_data(uint8_t data, offs_t row, bool separated)
|
||||
|
||||
uint16_t saa5240_device::get_rom_data(uint8_t data, offs_t row)
|
||||
{
|
||||
uint16_t c;
|
||||
if (row < 0 || row >= 10)
|
||||
static const uint8_t nc_char_matrix[6][128] =
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
// SAA5240A - German / SAA5240B - Italian / SAA5243E - German
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
|
||||
},
|
||||
// SAA5240A - English / SAA5240B - German / SAA5243E - English
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x83, 0x84, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x80, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x81, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x88, 0x89, 0x8a, 0x7f
|
||||
},
|
||||
// SAA5240A - Swedish / SAA5240B - French / SAA5243E - Swedish
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x93, 0x94, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x90, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0x91, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x92, 0x98, 0x99, 0x9a, 0x7f
|
||||
},
|
||||
// SAA5243E - Italian
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0xa3, 0xa4, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0xa0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xa1, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0xa2, 0xa8, 0xa9, 0xaa, 0x7f
|
||||
},
|
||||
// SAA5243E - Spanish
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0xb3, 0xb4, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0xb0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xb1, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0xb2, 0xb8, 0xb9, 0xba, 0x7f
|
||||
},
|
||||
// SAA5243E - Swedish
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0xc3, 0xc4, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0xc0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xc1, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0xc2, 0xc8, 0xc9, 0xca, 0x7f
|
||||
}
|
||||
};
|
||||
|
||||
// decode national option characters
|
||||
if (!BIT(data, 7))
|
||||
data = nc_char_matrix[1][data]; // TODO: select character set from page header control bits
|
||||
else
|
||||
{
|
||||
c = m_char_rom[(data * 10) + row];
|
||||
}
|
||||
return c;
|
||||
data &= 0x7f;
|
||||
|
||||
return m_char_rom[(data * 10) + row];
|
||||
}
|
||||
|
||||
|
||||
@ -628,7 +682,7 @@ void saa5240_device::get_character_data(uint8_t data)
|
||||
m_held_char = 32;
|
||||
}
|
||||
|
||||
if (m_curr_chartype == ALPHANUMERIC || !BIT(data,5))
|
||||
if (m_curr_chartype == ALPHANUMERIC || !BIT(data, 5))
|
||||
m_char_data = get_rom_data(data, ra);
|
||||
else
|
||||
m_char_data = get_gfx_data(data, ra, (m_curr_chartype == SEPARATED));
|
||||
@ -643,9 +697,6 @@ void saa5240_device::vcs_w(int state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
m_ra++;
|
||||
m_ra %= 10;
|
||||
|
||||
if (!m_ra)
|
||||
{
|
||||
if (m_double_height_bottom_row)
|
||||
@ -706,33 +757,31 @@ int saa5240_device::get_rgb()
|
||||
|
||||
uint32_t saa5240_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
for (int y = 0; y < 25 * 10; y++)
|
||||
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
{
|
||||
int sy = y / 10;
|
||||
int x = 0;
|
||||
int x = screen.visible_area().left();
|
||||
|
||||
m_ra = y % 10;
|
||||
|
||||
vcs_w(1);
|
||||
vcs_w(0);
|
||||
|
||||
for (int sx = 0; sx < 40; sx++)
|
||||
{
|
||||
uint8_t code = m_videoram->read_byte((sy * 40) + sx) & 0x7f;
|
||||
get_character_data(code);
|
||||
// get display data
|
||||
get_character_data(m_ram[ram_addr(m_register[4], sy, sx)]);
|
||||
|
||||
for (int bit = 0; bit < 12; bit++)
|
||||
{
|
||||
f6_w(1);
|
||||
f6_w(0);
|
||||
|
||||
int color = get_rgb();
|
||||
|
||||
if (BIT(code, 7)) color ^= 0x07;
|
||||
|
||||
int r = BIT(color, 0) * 0xff;
|
||||
int g = BIT(color, 1) * 0xff;
|
||||
int b = BIT(color, 2) * 0xff;
|
||||
|
||||
bitmap.pix(y, x++) = rgb_t(r, g, b);
|
||||
// cursor on at active row/column
|
||||
if (BIT(m_register[7], 6) && (sy == m_register[9]) && (sx == m_register[10]))
|
||||
bitmap.pix(y, x++) = rgb_t::white();
|
||||
else
|
||||
bitmap.pix(y, x++) = rgb_t(pal1bit(BIT(get_rgb(), 0)), pal1bit(BIT(get_rgb(), 1)), pal1bit(BIT(get_rgb(), 2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,28 +38,20 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
#define SAA5240_SLAVE_ADDRESS ( 0x22 )
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> saa5240_device
|
||||
|
||||
class saa5240_device :
|
||||
public device_t,
|
||||
public device_memory_interface
|
||||
class saa5240_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
saa5240_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
void set_ram_size(uint16_t ram_size) { m_ram_size = ram_size; }
|
||||
|
||||
void write_scl(int state);
|
||||
void write_sda(int state);
|
||||
int read_sda();
|
||||
@ -73,18 +65,16 @@ public:
|
||||
protected:
|
||||
saa5240_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// device-level overrides
|
||||
// device_t overrides
|
||||
virtual void device_start() override ATTR_COLD;
|
||||
virtual void device_reset() override ATTR_COLD;
|
||||
|
||||
// optional information overrides
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
private:
|
||||
static constexpr uint8_t SAA5240_SLAVE_ADDRESS = 0x22;
|
||||
|
||||
required_region_ptr<uint16_t> m_char_rom;
|
||||
|
||||
const address_space_config m_space_config;
|
||||
address_space *m_videoram;
|
||||
std::unique_ptr<uint8_t[]> m_ram;
|
||||
uint16_t m_ram_size;
|
||||
|
||||
// internal state
|
||||
uint8_t m_register[12];
|
||||
@ -98,12 +88,11 @@ private:
|
||||
int m_i2c_devsel;
|
||||
int m_i2c_address;
|
||||
|
||||
uint16_t ram_addr(int chapter, int row, int column);
|
||||
void increment_active_data();
|
||||
void update_active_data();
|
||||
|
||||
enum { STATE_IDLE, STATE_DEVSEL, STATE_ADDRESS, STATE_DATAIN, STATE_DATAOUT };
|
||||
|
||||
void saa5240_vram(address_map &map) ATTR_COLD;
|
||||
enum { STATE_IDLE, STATE_DEVSEL, STATE_ADDRESS, STATE_DATAIN, STATE_DATAOUT, STATE_READSELACK };
|
||||
|
||||
enum
|
||||
{
|
||||
@ -147,6 +136,10 @@ private:
|
||||
uint16_t get_rom_data(uint8_t data, offs_t row);
|
||||
void get_character_data(uint8_t data);
|
||||
|
||||
static constexpr uint8_t ALPHANUMERIC = 0x01;
|
||||
static constexpr uint8_t CONTIGUOUS = 0x02;
|
||||
static constexpr uint8_t SEPARATED = 0x03;
|
||||
|
||||
uint8_t m_held_char;
|
||||
uint8_t m_next_chartype;
|
||||
uint8_t m_curr_chartype;
|
||||
|
@ -25,22 +25,22 @@
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "bus/centronics/ctronics.h"
|
||||
#include "bus/econet/econet.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "cpu/g65816/g65816.h"
|
||||
#include "machine/6522via.h"
|
||||
#include "machine/6850acia.h"
|
||||
#include "machine/clock.h"
|
||||
#include "machine/input_merger.h"
|
||||
#include "machine/mc6854.h"
|
||||
#include "machine/ram.h"
|
||||
#include "machine/nvram.h"
|
||||
#include "machine/pcf8573.h"
|
||||
#include "machine/ram.h"
|
||||
#include "machine/scn_pci.h"
|
||||
#include "sound/beep.h"
|
||||
#include "sound/pcd3311.h"
|
||||
#include "video/saa5240.h"
|
||||
#include "bus/econet/econet.h"
|
||||
#include "bus/centronics/ctronics.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
@ -110,6 +110,8 @@ private:
|
||||
void ram_w(offs_t offset, uint8_t data);
|
||||
uint8_t sheila_r(offs_t offset);
|
||||
void sheila_w(offs_t offset, uint8_t data);
|
||||
uint8_t via_pb_r();
|
||||
void via_pb_w(uint8_t data);
|
||||
|
||||
void accomm_palette(palette_device &palette) const;
|
||||
|
||||
@ -509,32 +511,31 @@ uint8_t accomm_state::ram_r(offs_t offset)
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (m_ram->size())
|
||||
{
|
||||
case 512 * 1024:
|
||||
data = m_ram->pointer()[offset & 0x7ffff];
|
||||
break;
|
||||
|
||||
case 1024 * 1024:
|
||||
data = m_ram->pointer()[offset & 0xfffff];
|
||||
break;
|
||||
}
|
||||
data = m_ram->pointer()[offset & m_ram->mask()];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void accomm_state::ram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
switch (m_ram->size())
|
||||
{
|
||||
case 512 * 1024:
|
||||
m_ram->pointer()[offset & 0x7ffff] = data;
|
||||
break;
|
||||
m_ram->pointer()[offset & m_ram->mask()] = data;
|
||||
}
|
||||
|
||||
case 1024 * 1024:
|
||||
m_ram->pointer()[offset & 0xfffff] = data;
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t accomm_state::via_pb_r()
|
||||
{
|
||||
return 0xfe | (m_rtc->sda_r() & m_cct->read_sda());
|
||||
}
|
||||
|
||||
void accomm_state::via_pb_w(uint8_t data)
|
||||
{
|
||||
data ^= 0xff;
|
||||
|
||||
m_rtc->sda_w(BIT(data, 1));
|
||||
m_rtc->scl_w(BIT(data, 2));
|
||||
|
||||
m_cct->write_sda(BIT(data, 1));
|
||||
m_cct->write_scl(BIT(data, 2));
|
||||
}
|
||||
|
||||
|
||||
@ -710,11 +711,6 @@ void accomm_state::main_map(address_map &map)
|
||||
map(0xff0000, 0xffffff).rom().region("maincpu", 0x010000); /* ROM bank 1 (ROM Slot 0) */
|
||||
}
|
||||
|
||||
void accomm_state::saa5240_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0x07ff);
|
||||
map(0x0000, 0x07ff).ram();
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(accomm_state::trigger_reset)
|
||||
{
|
||||
@ -926,17 +922,14 @@ void accomm_state::accomm(machine_config &config)
|
||||
|
||||
/* teletext */
|
||||
SAA5240A(config, m_cct, 6_MHz_XTAL);
|
||||
m_cct->set_addrmap(0, &accomm_state::saa5240_map);
|
||||
m_cct->set_ram_size(0x800);
|
||||
|
||||
/* via */
|
||||
MOS6522(config, m_via, 16_MHz_XTAL / 16);
|
||||
m_via->writepa_handler().set("cent_data_out", FUNC(output_latch_device::write));
|
||||
m_via->ca2_handler().set("centronics", FUNC(centronics_device::write_strobe));
|
||||
m_via->readpb_handler().set([this] () { return uint8_t(m_rtc->sda_r() & m_cct->read_sda()); });
|
||||
m_via->writepb_handler().set(m_rtc, FUNC(pcf8573_device::sda_w)).bit(1).invert();
|
||||
m_via->writepb_handler().append(m_rtc, FUNC(pcf8573_device::scl_w)).bit(2).invert();
|
||||
m_via->writepb_handler().append(m_cct, FUNC(saa5240a_device::write_sda)).bit(1).invert();
|
||||
m_via->writepb_handler().append(m_cct, FUNC(saa5240a_device::write_scl)).bit(2).invert();
|
||||
m_via->readpb_handler().set(FUNC(accomm_state::via_pb_r));
|
||||
m_via->writepb_handler().set(FUNC(accomm_state::via_pb_w));
|
||||
m_via->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
|
||||
|
||||
/* rs423 */
|
||||
@ -977,7 +970,7 @@ void accomm_state::accomm(machine_config &config)
|
||||
econet.clk_wr_callback().append(m_adlc, FUNC(mc6854_device::rxc_w));
|
||||
econet.data_wr_callback().set(m_adlc, FUNC(mc6854_device::set_rx));
|
||||
|
||||
ECONET_SLOT(config, "econet254", "econet", econet_devices).set_slot(254);
|
||||
ECONET_SLOT(config, "econet254", "econet", econet_devices);
|
||||
|
||||
/* printer */
|
||||
centronics_device ¢ronics(CENTRONICS(config, "centronics", centronics_devices, "printer"));
|
||||
@ -993,7 +986,7 @@ void accomm_state::accommi(machine_config &config)
|
||||
|
||||
/* teletext */
|
||||
SAA5240B(config.replace(), m_cct, 6_MHz_XTAL);
|
||||
m_cct->set_addrmap(0, &accomm_state::saa5240_map);
|
||||
m_cct->set_ram_size(0x800);
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
------------------
|
||||
22 SAA5240
|
||||
A2 PCF8582
|
||||
C0 ?
|
||||
C0 SAB3036
|
||||
|
||||
TODO:
|
||||
- implement keypad
|
||||
@ -84,7 +84,6 @@ private:
|
||||
void i2c_w(uint8_t data);
|
||||
|
||||
void mem_map(address_map &map) ATTR_COLD;
|
||||
void saa5240_map(address_map &map) ATTR_COLD;
|
||||
|
||||
required_device<i80186_cpu_device> m_maincpu;
|
||||
required_device<screen_device> m_screen;
|
||||
@ -109,7 +108,7 @@ void datacast_state::mem_map(address_map &map)
|
||||
map(0x00000, 0x7ffff).ram();
|
||||
map(0xc0000, 0xc0000).rw(FUNC(datacast_state::keypad_r), FUNC(datacast_state::keypad_w)).umask16(0x00ff);
|
||||
map(0xc0080, 0xc0080).lr8([]() { return 0xff; }, "dips"); // unknown purpose
|
||||
map(0xc0100, 0xc010f).noprw(); //.rw(m_saa5250, FUNC(saa5250_device::read), FUNC(saa5250_device::write)).umask16(0x00ff);
|
||||
map(0xc0100, 0xc010f).noprw(); //.rw(m_cidac, FUNC(saa5250_device::read), FUNC(saa5250_device::write)).umask16(0x00ff);
|
||||
map(0xc0180, 0xc0180).rw(FUNC(datacast_state::i2c_r), FUNC(datacast_state::i2c_w)).umask16(0x00ff);
|
||||
map(0xc0200, 0xc0203).rw(m_usart[0], FUNC(i8251_device::read), FUNC(i8251_device::write)).umask16(0x00ff);
|
||||
map(0xc0280, 0xc0280).w(m_dbrg, FUNC(com8116_device::stt_str_w));
|
||||
@ -117,12 +116,6 @@ void datacast_state::mem_map(address_map &map)
|
||||
map(0xf0000, 0xfffff).rom().region("rom", 0);
|
||||
}
|
||||
|
||||
void datacast_state::saa5240_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0x07ff);
|
||||
map(0x0000, 0x07ff).ram();
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START(datacast)
|
||||
PORT_START("X1")
|
||||
@ -158,7 +151,7 @@ INPUT_PORTS_END
|
||||
uint8_t datacast_state::keypad_r()
|
||||
{
|
||||
uint8_t data = (m_kb->read() << 0) | (m_kb->da_r() << 5);
|
||||
logerror("keypad_r: %02x\n", data);
|
||||
logerror("%s keypad_r: %02x\n", machine().describe_context(), data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -166,13 +159,13 @@ void datacast_state::keypad_w(uint8_t data)
|
||||
{
|
||||
m_key_col = data;
|
||||
|
||||
logerror("keypad_w: %02x\n", data);
|
||||
logerror("%s keypad_w: %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
|
||||
|
||||
uint8_t datacast_state::i2c_r()
|
||||
{
|
||||
return m_i2cmem->read_sda() & m_cct->read_sda();
|
||||
return m_i2cmem->read_sda() & m_cct->read_sda();
|
||||
}
|
||||
|
||||
void datacast_state::i2c_w(uint8_t data)
|
||||
@ -203,10 +196,10 @@ void datacast_state::datacast(machine_config &config)
|
||||
//SAA5231(config, m_saa5231, 13.875_MHz_XTAL);
|
||||
|
||||
SAA5240A(config, m_cct, 6_MHz_XTAL);
|
||||
m_cct->set_addrmap(0, &datacast_state::saa5240_map);
|
||||
m_cct->set_ram_size(0x800);
|
||||
|
||||
//SAA5250(config, m_saa5250, 0);
|
||||
//m_saa5250->set_addrmap(0, &datacast_state::saa5250_map); // 2K RAM
|
||||
//SAA5250(config, m_cidac, 0);
|
||||
//m_cidac->set_buffer_size(0x800);
|
||||
|
||||
I2C_PCF8582(config, m_i2cmem).set_e0(1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user