Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
321 lines (261 sloc) 12.1 KB
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
/***************************************************************************
Driver for Casio CFX-9850
To operate:
The unit is switched off by default, you have to switch it on by pressing 'Q'.
Currently (year2011) it is on by default, the only key that works is '\'
which turns it off. After that nothing happens.
Normal operation:
- AC/ON - turns the unit on
- SHIFT + OFF - turns the unit off
The unit automatically powers off after no operation for about 6 minutes (intro/quick start, page viii).
Debugging information:
1. g 10b3 (Initialise system)
2. cs=23
3. ip= one of these: ip=d1a4,d1af,d1ba,d1c5,d1d0,d1db,d1ea,d1f9,d208,d217,
d226,d235,d244
4. g 23108c to get a test pattern on the screen.
***************************************************************************/
#include "emu.h"
#include "cpu/hcd62121/hcd62121.h"
#include "emupal.h"
#include "screen.h"
class cfx9850_state : public driver_device
{
public:
cfx9850_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_video_ram(*this, "video_ram")
, m_display_ram(*this, "display_ram")
, m_ko_port(*this, "KO%u", 1)
, m_maincpu(*this, "maincpu")
, m_ko(0)
, m_port(0)
, m_opt(0)
{ }
DECLARE_WRITE8_MEMBER(kol_w);
DECLARE_WRITE8_MEMBER(koh_w);
DECLARE_WRITE8_MEMBER(port_w);
DECLARE_WRITE8_MEMBER(opt_w);
DECLARE_READ8_MEMBER(ki_r);
DECLARE_READ8_MEMBER(in0_r);
required_shared_ptr<u8> m_video_ram;
required_shared_ptr<u8> m_display_ram;
void cfx9850_palette(palette_device &palette) const;
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void cfx9850(machine_config &config);
void cfx9850_mem(address_map &map);
protected:
required_ioport_array<12> m_ko_port;
required_device<hcd62121_cpu_device> m_maincpu;
private:
u16 m_ko; // KO lines KO1 - KO14
u8 m_port; // PORT lines PORT0 - PORT7 (serial I/O)
u8 m_opt; // OPT lines OPT0 - OPT7 (contrast)
};
void cfx9850_state::cfx9850_mem(address_map &map)
{
map(0x000000, 0x007fff).rom();
map(0x080000, 0x0807ff).ram().share("video_ram");
// map(0x100000, 0x10ffff) // some memory mapped i/o???
// map(0x110000, 0x11ffff) // some memory mapped i/o???
map(0x200000, 0x27ffff).rom().region("bios", 0);
map(0x400000, 0x407fff).mirror(0x008000).ram();
map(0x600000, 0x6007ff).mirror(0xf800).ram().share("display_ram");
// map(0xe10000, 0xe1ffff) // some memory mapped i/o???
}
WRITE8_MEMBER(cfx9850_state::kol_w)
{
m_ko = (m_ko & 0xff00) | data;
logerror("KO is now %04x\n", m_ko);
}
WRITE8_MEMBER(cfx9850_state::koh_w)
{
m_ko = (m_ko & 0x00ff) | (data << 8);
logerror("KO is now %04x\n", m_ko);
}
// 7------- PORT7 - RX enable?
// -6------ PORT6 - NC / CP45
// --5----- PORT5 - TX enable?
// ---4---- PORT4 - data out (see code at 2225A0)
// ----3--- PORT3 - NC / CP28
// -----2-- PORT2 - NC / CP29
// ------1- PORT1 - NC / CP30
// -------0 PORT0 - display (enable?) related? + CP31
WRITE8_MEMBER(cfx9850_state::port_w)
{
m_port = data;
logerror("PORT is now %02x\n", m_port);
}
// 7------- OPT7 - NC / CP46
// -6------ OPT6 - NC / CP25
// --5----- OPT5 - NC / CP26
// ---4---- OPT4 - NC / CP27
// ----3--- OPT3 - contrast (TC74HC4066AFS pin 12)
// -----2-- OPT2 - contrast (TC74HC4066AFS pin 6)
// ------1- OPT1 - contrast (TC74HC4066AFS pin 5)
// -------0 OPT0 - contrast (TC74HC4066AFS pin 13)
WRITE8_MEMBER(cfx9850_state::opt_w)
{
m_opt = data;
logerror("OPT is now %02x\n", m_opt);
}
READ8_MEMBER(cfx9850_state::ki_r)
{
u8 data = 0;
for (int i = 0; i < 12; i++)
{
if (BIT(m_ko, i))
{
data |= m_ko_port[i]->read();
}
}
return data;
}
READ8_MEMBER(cfx9850_state::in0_r)
{
// battery level?
// bit4 -> if reset CPU keeps restarting (several unknown instructions before jumping to 0)
// perhaps a battery present check?
// bit 5 -> 0 = low battery
// --XX ---- VDET
// ---- -X-- data-in
return 0x30 & ~ 0x00;
}
static INPUT_PORTS_START(cfx9850)
PORT_START("KO1")
/* KI1 */ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("AC On/Off") PORT_CODE(KEYCODE_BACKSLASH)
PORT_BIT(0xfe, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("KO2")
/* KI3 */ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("EXE Enter") PORT_CODE(KEYCODE_ENTER)
/* KI4 */ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(-) Ans") PORT_CODE(KEYCODE_MINUS)
/* KI5 */ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("EXP Pi") PORT_CODE(KEYCODE_EQUALS)
/* KI6 */ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(". SPACE") PORT_CODE(KEYCODE_SPACE)
/* KI7 */ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("0 Z") PORT_CODE(KEYCODE_Z)
PORT_BIT(0x83, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("KO3")
/* KI3 */ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("- ] Y") PORT_CODE(KEYCODE_Y)
/* KI4 */ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("+ [ X") PORT_CODE(KEYCODE_X)
/* KI5 */ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("3 W") PORT_CODE(KEYCODE_W)
/* KI6 */ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("2 V") PORT_CODE(KEYCODE_V)
/* KI7 */ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("1 U") PORT_CODE(KEYCODE_U)
PORT_BIT(0x83, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("KO4")
/* KI3 */ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("/ } T") PORT_CODE(KEYCODE_T)
/* KI4 */ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("* { S") PORT_CODE(KEYCODE_S)
/* KI5 */ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("6 R") PORT_CODE(KEYCODE_R)
/* KI6 */ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("5 Q") PORT_CODE(KEYCODE_Q)
/* KI7 */ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("4 P") PORT_CODE(KEYCODE_P)
PORT_BIT(0x83, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("KO5")
/* KI4 */ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DEL INS") PORT_CODE(KEYCODE_BACKSPACE)
/* KI5 */ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("9 O") PORT_CODE(KEYCODE_O)
/* KI6 */ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("8 N") PORT_CODE(KEYCODE_N)
/* KI7 */ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("7 M") PORT_CODE(KEYCODE_M)
PORT_BIT(0x87, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("KO6")
/* KI2 */ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("-> L") PORT_CODE(KEYCODE_L)
/* KI3 */ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(", K") PORT_CODE(KEYCODE_K)
/* KI4 */ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(") x^-1 J") PORT_CODE(KEYCODE_J)
/* KI5 */ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("( x^(1/3) I") PORT_CODE(KEYCODE_I)
/* KI6 */ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F<=>D H") PORT_CODE(KEYCODE_H)
/* KI7 */ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("a b/c G") PORT_CODE(KEYCODE_G)
PORT_BIT(0x81, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("KO7")
/* KI2 */ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("tan tan^-1 F") PORT_CODE(KEYCODE_F)
/* KI3 */ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("cos cos^-1 E") PORT_CODE(KEYCODE_E)
/* KI4 */ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("sin sin^-1 D") PORT_CODE(KEYCODE_D)
/* KI5 */ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ln e^x C") PORT_CODE(KEYCODE_C)
/* KI6 */ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("log 10^x B") PORT_CODE(KEYCODE_B)
/* KI7 */ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("x,theta,t A") PORT_CODE(KEYCODE_A)
PORT_BIT(0x81, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("KO8")
/* KI2 */ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT)
/* KI3 */ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN)
/* KI4 */ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("EXIT QUIT") PORT_CODE(KEYCODE_STOP)
/* KI5 */ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("^ root theta") PORT_CODE(KEYCODE_COMMA)
/* KI6 */ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("x^2 sqrt ro") PORT_CODE(KEYCODE_SLASH)
/* KI7 */ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ALPHA ALPHA-LOCK") PORT_CODE(KEYCODE_CAPSLOCK)
PORT_BIT(0x81, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("KO9")
/* KI2 */ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP)
/* KI3 */ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT)
/* KI4 */ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("MENU SET UP") PORT_CODE(KEYCODE_OPENBRACE)
/* KI5 */ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("VARS PRGM") PORT_CODE(KEYCODE_CLOSEBRACE)
/* KI6 */ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("OPTN") PORT_CODE(KEYCODE_LCONTROL)
/* KI7 */ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT)
PORT_BIT(0x81, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("KO10")
/* KI2 */ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F6 G<=>T") PORT_CODE(KEYCODE_F6)
/* KI3 */ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F5 G-Solv") PORT_CODE(KEYCODE_F5)
/* KI4 */ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F4 Sketch") PORT_CODE(KEYCODE_F4)
/* KI5 */ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F3 V-Window") PORT_CODE(KEYCODE_F3)
/* KI6 */ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F2 Zoom") PORT_CODE(KEYCODE_F2)
/* KI7 */ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F1 Trace") PORT_CODE(KEYCODE_F1)
PORT_BIT(0x81, IP_ACTIVE_HIGH, IPT_UNUSED)
// KO11 is not connected
PORT_START("KO11")
PORT_BIT(0xff, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("KO12")
/* KI4 */ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("TEST") PORT_CODE(KEYCODE_TILDE)
PORT_BIT(0xf7, IP_ACTIVE_HIGH, IPT_UNUSED)
INPUT_PORTS_END
void cfx9850_state::cfx9850_palette(palette_device &palette) const
{
palette.set_pen_color(0, 0xff, 0xff, 0xff);
palette.set_pen_color(1, 0x00, 0x00, 0xff);
palette.set_pen_color(2, 0x00, 0xff, 0x00);
palette.set_pen_color(3, 0xff, 0x00, 0x00);
}
u32 cfx9850_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
u16 offset = 0;
for (int i = 0; i < 16; i++)
{
int x = 120 - i * 8;
for (int j = 0; j < 64; j++)
{
u8 data1 = m_display_ram[offset];
u8 data2 = m_display_ram[offset + 0x400];
for (int b = 0; b < 8; b++)
{
bitmap.pix16(63-j, x+b) = ( data1 & 0x80 ) ? ( data2 & 0x80 ? 3 : 2 ) : ( data2 & 0x80 ? 1 : 0 );
data1 <<= 1;
data2 <<= 1;
}
offset++;
}
}
return 0;
}
void cfx9850_state::cfx9850(machine_config &config)
{
HCD62121(config, m_maincpu, 4300000); /* X1 - 4.3 MHz */
m_maincpu->set_addrmap(AS_PROGRAM, &cfx9850_state::cfx9850_mem);
m_maincpu->kol_cb().set(FUNC(cfx9850_state::kol_w));
m_maincpu->koh_cb().set(FUNC(cfx9850_state::koh_w));
m_maincpu->port_cb().set(FUNC(cfx9850_state::port_w));
m_maincpu->opt_cb().set(FUNC(cfx9850_state::opt_w));
m_maincpu->ki_cb().set(FUNC(cfx9850_state::ki_r));
m_maincpu->in0_cb().set(FUNC(cfx9850_state::in0_r));
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
screen.set_refresh_hz(60);
screen.set_size(128, 64);
screen.set_visarea(0, 127, 0, 63);
screen.set_screen_update(FUNC(cfx9850_state::screen_update));
screen.set_palette("palette");
// TODO: Verify amount of colors and palette. Colors can be changed by changing the contrast.
PALETTE(config, "palette", FUNC(cfx9850_state::cfx9850_palette), 4);
}
ROM_START(cfx9850)
ROM_REGION(0x8000, "maincpu", 0)
ROM_LOAD("hcd62121.bin", 0x0000, 0x8000, CRC(e72075f8) SHA1(f50d176e1c225dab69abfc67702c9dfb296b6a78))
ROM_REGION(0x80000, "bios", 0)
// Unknown yet which rom is which version.
ROM_SYSTEM_BIOS(0, "rom1", "rom1, version unknown")
ROMX_LOAD("cfx9850.bin", 0x00000, 0x80000, CRC(6c9bd903) SHA1(d5b6677ab4e0d3f84e5769e89e8f3d101f98f848), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "rom2", "rom2, version unknown")
ROMX_LOAD("cfx9850b.bin", 0x00000, 0x80000, CRC(cd3c497f) SHA1(1d1aa38205eec7aba3ed6bef7389767e38afe075), ROM_BIOS(1))
ROM_END
COMP(1996, cfx9850, 0, 0, cfx9850, cfx9850, cfx9850_state, empty_init, "Casio", "CFX-9850G", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)
You can’t perform that action at this time.