New working systems

-------------------
Liberty Electronics Freedom 200 [Bitsavers]

- Rename freedom220.cpp to freedom200.cpp
- Add support for font selection
- Improve double-width support
- Support 'invisible' attribute
- Reduce NVRAM size
This commit is contained in:
Dirk Best 2023-04-20 13:29:20 +02:00
parent d798958d5c
commit a4732500a5
2 changed files with 90 additions and 34 deletions

View File

@ -2,8 +2,10 @@
// copyright-holders: Dirk Best // copyright-holders: Dirk Best
/**************************************************************************** /****************************************************************************
Liberty Electronics Freedom 220 Video Display Terminal Liberty Electronics Freedom 200 Video Display Terminal
Serial terminal
Liberty Electronics Freedom 220 Video Display Terminal
VT220 compatible serial terminal VT220 compatible serial terminal
Hardware: Hardware:
@ -26,10 +28,10 @@
- Expansion slot - Expansion slot
TODO: TODO:
- Font selection
- Light/dark background - Light/dark background
- Soft scroll - Soft scroll
- Pixel clock, characters should be 9 pixels? - Pixel clock, characters should be 9 pixels?
- I/O write to 0xc0
Notes: Notes:
- On first boot you will get an "error 8" - this is because - On first boot you will get an "error 8" - this is because
@ -60,10 +62,10 @@ namespace {
// TYPE DEFINITIONS // TYPE DEFINITIONS
//************************************************************************** //**************************************************************************
class freedom220_state : public driver_device class freedom200_state : public driver_device
{ {
public: public:
freedom220_state(const machine_config &mconfig, device_type type, const char *tag) : freedom200_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag), driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
m_avdc(*this, "avdc"), m_avdc(*this, "avdc"),
@ -74,11 +76,10 @@ public:
m_translate(*this, "translate"), m_translate(*this, "translate"),
m_charram(*this, "charram%u", 0U), m_charram(*this, "charram%u", 0U),
m_attrram(*this, "attrram%u", 0U), m_attrram(*this, "attrram%u", 0U),
m_video_ctrl(0x00), m_video_ctrl(0x00)
m_dw_active(false)
{ } { }
void freedom220(machine_config &config); void freedom200(machine_config &config);
protected: protected:
virtual void machine_start() override; virtual void machine_start() override;
@ -96,7 +97,14 @@ private:
required_shared_ptr_array<uint8_t, 2> m_attrram; required_shared_ptr_array<uint8_t, 2> m_attrram;
uint8_t m_video_ctrl; uint8_t m_video_ctrl;
// double width support
bool m_dw_active; bool m_dw_active;
uint8_t m_dw_char;
uint8_t m_dw_attr;
bool m_dw_ul;
bool m_dw_blink;
bool m_dw_cursor;
void mem_map(address_map &map); void mem_map(address_map &map);
void io_map(address_map &map); void io_map(address_map &map);
@ -113,17 +121,18 @@ private:
// ADDRESS MAPS // ADDRESS MAPS
//************************************************************************** //**************************************************************************
void freedom220_state::mem_map(address_map &map) void freedom200_state::mem_map(address_map &map)
{ {
map(0x0000, 0x5fff).rom(); map(0x0000, 0x5fff).rom();
map(0x8000, 0x87ff).ram().share(m_charram[0]); map(0x8000, 0x87ff).ram().share(m_charram[0]);
map(0x8800, 0x8fff).ram().share(m_attrram[0]); map(0x8800, 0x8fff).ram().share(m_attrram[0]);
map(0x9000, 0x97ff).ram().share(m_charram[1]); map(0x9000, 0x97ff).ram().share(m_charram[1]);
map(0x9800, 0x9fff).ram().share(m_attrram[1]); map(0x9800, 0x9fff).ram().share(m_attrram[1]);
map(0xa000, 0xafff).ram().share("nvram"); // actual NVRAM possibly only 0x800 in size map(0xa000, 0xa7ff).ram().share("nvram");
map(0xa800, 0xafff).ram().share("workram");
} }
void freedom220_state::io_map(address_map &map) void freedom200_state::io_map(address_map &map)
{ {
map.global_mask(0xff); map.global_mask(0xff);
map(0x00, 0x07).rw(m_avdc, FUNC(scn2674_device::read), FUNC(scn2674_device::write)); map(0x00, 0x07).rw(m_avdc, FUNC(scn2674_device::read), FUNC(scn2674_device::write));
@ -131,7 +140,8 @@ void freedom220_state::io_map(address_map &map)
map(0x40, 0x41).rw(m_usart[0], FUNC(i8251_device::read), FUNC(i8251_device::write)); map(0x40, 0x41).rw(m_usart[0], FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x60, 0x61).rw(m_usart[1], FUNC(i8251_device::read), FUNC(i8251_device::write)); map(0x60, 0x61).rw(m_usart[1], FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0x80, 0x81).rw(m_usart[2], FUNC(i8251_device::read), FUNC(i8251_device::write)); map(0x80, 0x81).rw(m_usart[2], FUNC(i8251_device::read), FUNC(i8251_device::write));
map(0xa0, 0xa0).w(FUNC(freedom220_state::video_ctrl_w)); map(0xa0, 0xa0).w(FUNC(freedom200_state::video_ctrl_w));
// c0 - used by free200 only
} }
@ -139,53 +149,76 @@ void freedom220_state::io_map(address_map &map)
// VIDEO EMULATION // VIDEO EMULATION
//************************************************************************** //**************************************************************************
void freedom220_state::char_map(address_map &map) void freedom200_state::char_map(address_map &map)
{ {
map(0x0000, 0x07ff).ram().share(m_charram[0]); map(0x0000, 0x07ff).ram().share(m_charram[0]);
map(0x1000, 0x17ff).ram().share(m_charram[1]); map(0x1000, 0x17ff).ram().share(m_charram[1]);
map(0x2000, 0x2fff).ram().share("nvram"); map(0x2000, 0x27ff).ram().share("nvram");
map(0x2800, 0x2fff).ram().share("workram");
} }
void freedom220_state::attr_map(address_map &map) void freedom200_state::attr_map(address_map &map)
{ {
map(0x0000, 0x07ff).ram().share(m_attrram[0]); map(0x0000, 0x07ff).ram().share(m_attrram[0]);
map(0x1000, 0x17ff).ram().share(m_attrram[1]); map(0x1000, 0x17ff).ram().share(m_attrram[1]);
map(0x2000, 0x2fff).ram().share("nvram"); map(0x2000, 0x27ff).ram().share("workram");
map(0x2800, 0x2fff).ram().share("workram");
} }
void freedom220_state::avdc_intr_w(int state) void freedom200_state::avdc_intr_w(int state)
{ {
if (state) if (state)
m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
} }
void freedom220_state::video_ctrl_w(uint8_t data) void freedom200_state::video_ctrl_w(uint8_t data)
{ {
// 7------- unknown // 7------- unknown
// -6------ unknown // -6------ unknown
// --5----- unknown // --5----- unknown
// ---432-- font select // ---432-- translation table bit 210
// ------1- normal/reverse video // ------1- normal/reverse video
// -------0 unknown // -------0 translation table bit 3
logerror("video_ctrl_w: %02x\n", data); logerror("video_ctrl_w: %02x\n", data);
m_video_ctrl = data; m_video_ctrl = data;
} }
SCN2674_DRAW_CHARACTER_MEMBER( freedom220_state::draw_character ) SCN2674_DRAW_CHARACTER_MEMBER( freedom200_state::draw_character )
{ {
// 765----- unknown // 765----- unknown
// ---4---- normal/bold // ---4---- normal/bold
// ----3--- underline // ----3--- underline
// -----2-- invert // -----2-- invert
// ------1- blink // ------1- blink
// -------0 unknown // -------0 invisible
const pen_t *const pen = m_palette->pens(); const pen_t *const pen = m_palette->pens();
// translation table // either save or restore attributes for double-width
const int table = 0; // 0-f if (dw)
{
if (m_dw_active)
{
charcode = m_dw_char;
attrcode = m_dw_attr;
ul = m_dw_ul;
blink = m_dw_blink;
cursor = m_dw_cursor;
}
else
{
m_dw_char = charcode;
m_dw_attr = attrcode;
m_dw_ul = ul;
m_dw_blink = blink;
m_dw_cursor = cursor;
}
}
// apply translation table
const int table = bitswap<4>(m_video_ctrl, 0, 4, 3, 2);
charcode = m_translate[(table << 8) | charcode]; charcode = m_translate[(table << 8) | charcode];
uint8_t data = m_chargen[charcode << 4 | linecount]; uint8_t data = m_chargen[charcode << 4 | linecount];
@ -196,6 +229,9 @@ SCN2674_DRAW_CHARACTER_MEMBER( freedom220_state::draw_character )
if (blink && (BIT(attrcode, 1))) if (blink && (BIT(attrcode, 1)))
data = 0x00; data = 0x00;
if (BIT(attrcode, 0))
data = 0x00;
if (BIT(attrcode, 2)) if (BIT(attrcode, 2))
data = ~data; data = ~data;
@ -247,14 +283,19 @@ GFXDECODE_END
// MACHINE EMULATION // MACHINE EMULATION
//************************************************************************** //**************************************************************************
void freedom220_state::machine_start() void freedom200_state::machine_start()
{ {
// register for save states // register for save states
save_item(NAME(m_video_ctrl)); save_item(NAME(m_video_ctrl));
save_item(NAME(m_dw_active)); save_item(NAME(m_dw_active));
save_item(NAME(m_dw_char));
save_item(NAME(m_dw_attr));
save_item(NAME(m_dw_ul));
save_item(NAME(m_dw_blink));
save_item(NAME(m_dw_cursor));
} }
void freedom220_state::machine_reset() void freedom200_state::machine_reset()
{ {
m_dw_active = false; m_dw_active = false;
@ -268,11 +309,11 @@ void freedom220_state::machine_reset()
// MACHINE DEFINTIONS // MACHINE DEFINTIONS
//************************************************************************** //**************************************************************************
void freedom220_state::freedom220(machine_config &config) void freedom200_state::freedom200(machine_config &config)
{ {
Z80(config, m_maincpu, 4_MHz_XTAL); Z80(config, m_maincpu, 4_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &freedom220_state::mem_map); m_maincpu->set_addrmap(AS_PROGRAM, &freedom200_state::mem_map);
m_maincpu->set_addrmap(AS_IO, &freedom220_state::io_map); m_maincpu->set_addrmap(AS_IO, &freedom200_state::io_map);
input_merger_device &irq(INPUT_MERGER_ANY_HIGH(config, "irq")); input_merger_device &irq(INPUT_MERGER_ANY_HIGH(config, "irq"));
irq.output_handler().set_inputline("maincpu", INPUT_LINE_IRQ0); irq.output_handler().set_inputline("maincpu", INPUT_LINE_IRQ0);
@ -289,12 +330,12 @@ void freedom220_state::freedom220(machine_config &config)
GFXDECODE(config, "gfxdecode", m_palette, chars); GFXDECODE(config, "gfxdecode", m_palette, chars);
SCN2674(config, m_avdc, 16000000 / 8); // clock unverified SCN2674(config, m_avdc, 16000000 / 8); // clock unverified
m_avdc->intr_callback().set(FUNC(freedom220_state::avdc_intr_w)); m_avdc->intr_callback().set(FUNC(freedom200_state::avdc_intr_w));
m_avdc->set_screen(m_screen); m_avdc->set_screen(m_screen);
m_avdc->set_character_width(8); // unverified m_avdc->set_character_width(8); // unverified
m_avdc->set_addrmap(0, &freedom220_state::char_map); m_avdc->set_addrmap(0, &freedom200_state::char_map);
m_avdc->set_addrmap(1, &freedom220_state::attr_map); m_avdc->set_addrmap(1, &freedom200_state::attr_map);
m_avdc->set_display_callback(FUNC(freedom220_state::draw_character)); m_avdc->set_display_callback(FUNC(freedom200_state::draw_character));
pit8253_device &pit(PIT8253(config, "pit", 0)); pit8253_device &pit(PIT8253(config, "pit", 0));
pit.set_clk<0>(18.432_MHz_XTAL / 10); pit.set_clk<0>(18.432_MHz_XTAL / 10);
@ -340,6 +381,19 @@ void freedom220_state::freedom220(machine_config &config)
// ROM DEFINITIONS // ROM DEFINITIONS
//************************************************************************** //**************************************************************************
ROM_START( free200 )
ROM_REGION(0x6000, "maincpu", 0)
ROM_LOAD("m120020.ic213", 0x0000, 0x2000, CRC(869de37e) SHA1(22f9c847aa8d99c22791df7a40a7c1d67f21516b))
ROM_LOAD("m220020.ic212", 0x2000, 0x2000, CRC(85095c20) SHA1(e7515c8b188732e391015f20ad38207876850589))
ROM_LOAD("m320020.ic214", 0x4000, 0x2000, CRC(827cafe6) SHA1(887d78bfbfcdc07efc35a7c560822b1386300632))
ROM_REGION(0x1000, "chargen", 0)
ROM_LOAD("g020010.bin", 0x0000, 0x1000, CRC(b99bf3b1) SHA1(799395694d2f88c68230ce7f6bf5453b799926f4))
ROM_REGION(0x1000, "translate", 0)
ROM_LOAD("t020010.bin", 0x0000, 0x1000, CRC(19f9c677) SHA1(903eb82b2a7b63d79c00085c8c7ec2cb9583e2a0))
ROM_END
ROM_START( free220 ) ROM_START( free220 )
ROM_REGION(0x6000, "maincpu", 0) ROM_REGION(0x6000, "maincpu", 0)
ROM_LOAD("m122010__8cdd.ic213", 0x0000, 0x2000, CRC(a1181809) SHA1(0ec0fd30c8a55f0bb9e1c6453120ab9a696f9041)) ROM_LOAD("m122010__8cdd.ic213", 0x0000, 0x2000, CRC(a1181809) SHA1(0ec0fd30c8a55f0bb9e1c6453120ab9a696f9041))
@ -362,4 +416,5 @@ ROM_END
//************************************************************************** //**************************************************************************
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1984, free220, 0, 0, freedom220, 0, freedom220_state, empty_init, "Liberty Electronics", "Freedom 220", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) COMP( 1983, free200, 0, 0, freedom200, 0, freedom200_state, empty_init, "Liberty Electronics", "Freedom 200", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )
COMP( 1984, free220, 0, 0, freedom200, 0, freedom200_state, empty_init, "Liberty Electronics", "Freedom 220", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE )

View File

@ -24477,7 +24477,8 @@ adm36 //
@source:liberty/freedom120.cpp @source:liberty/freedom120.cpp
free120 // (c) 1993 Liberty Electronics free120 // (c) 1993 Liberty Electronics
@source:liberty/freedom220.cpp @source:liberty/freedom200.cpp
free200 // (c) 1983 Liberty Electronics
free220 // (c) 1984 Liberty Electronics free220 // (c) 1984 Liberty Electronics
@source:lsi/m3.cpp @source:lsi/m3.cpp