src/mess/drivers/hp49gp.c
| r0 | r9843 | |
| 1 | /*******************************************************************************
|
| 2 | |
| 3 | Hewlett Packard 49G+ Graphing Calculator
|
| 4 | |
| 5 | *******************************************************************************/
|
| 6 | |
| 7 | #include "emu.h"
|
| 8 | #include "cpu/arm7/arm7.h"
|
| 9 | #include "machine/s3c2410.h"
|
| 10 | |
| 11 | #define VERBOSE_LEVEL ( 0 )
|
| 12 | |
| 13 | INLINE void ATTR_PRINTF(3,4) verboselog( running_machine *machine, int n_level, const char *s_fmt, ...)
|
| 14 | {
|
| 15 | if (VERBOSE_LEVEL >= n_level)
|
| 16 | {
|
| 17 | va_list v;
|
| 18 | char buf[32768];
|
| 19 | va_start( v, s_fmt);
|
| 20 | vsprintf( buf, s_fmt, v);
|
| 21 | va_end( v);
|
| 22 | logerror( "%s: %s", cpuexec_describe_context( machine), buf);
|
| 23 | }
|
| 24 | }
|
| 25 | |
| 26 | typedef struct
|
| 27 | {
|
| 28 | int l1;
|
| 29 | int data;
|
| 30 | int l3;
|
| 31 | UINT32 shift, bits;
|
| 32 | } lcd_spi_t;
|
| 33 | |
| 34 | class hp49gp_state : public driver_device
|
| 35 | {
|
| 36 | public:
|
| 37 | hp49gp_state(running_machine &machine, const driver_device_config_base &config)
|
| 38 | : driver_device(machine, config) { }
|
| 39 | |
| 40 | UINT32 port[9];
|
| 41 | running_device *s3c2410;
|
| 42 | UINT32 *steppingstone;
|
| 43 | lcd_spi_t lcd_spi;
|
| 44 | };
|
| 45 | |
| 46 | /***************************************************************************
|
| 47 | MACHINE HARDWARE
|
| 48 | ***************************************************************************/
|
| 49 | |
| 50 | // LCD SPI
|
| 51 | |
| 52 | enum
|
| 53 | {
|
| 54 | LCD_SPI_LINE_1,
|
| 55 | LCD_SPI_LINE_DATA,
|
| 56 | LCD_SPI_LINE_3
|
| 57 | };
|
| 58 | |
| 59 | static void lcd_spi_reset( running_machine *machine)
|
| 60 | {
|
| 61 | hp49gp_state *hp49gp = machine->driver_data<hp49gp_state>();
|
| 62 | verboselog( machine, 5, "lcd_spi_reset\n");
|
| 63 | hp49gp->lcd_spi.l1 = 0;
|
| 64 | hp49gp->lcd_spi.data = 0;
|
| 65 | hp49gp->lcd_spi.l3 = 0;
|
| 66 | }
|
| 67 | |
| 68 | static void lcd_spi_init( running_machine *machine)
|
| 69 | {
|
| 70 | verboselog( machine, 5, "lcd_spi_init\n");
|
| 71 | lcd_spi_reset( machine);
|
| 72 | }
|
| 73 | |
| 74 | static void lcd_spi_line_w( running_machine *machine, int line, int data)
|
| 75 | {
|
| 76 | hp49gp_state *hp49gp = machine->driver_data<hp49gp_state>();
|
| 77 | switch (line)
|
| 78 | {
|
| 79 | case LCD_SPI_LINE_1 :
|
| 80 | {
|
| 81 | if (data != hp49gp->lcd_spi.l1)
|
| 82 | {
|
| 83 | if (data == 0)
|
| 84 | {
|
| 85 | hp49gp->lcd_spi.shift = 0;
|
| 86 | hp49gp->lcd_spi.bits = 0;
|
| 87 | }
|
| 88 | verboselog( machine, 5, "LCD_SPI_LINE_1 <- %d\n", data);
|
| 89 | hp49gp->lcd_spi.l1 = data;
|
| 90 | }
|
| 91 | }
|
| 92 | break;
|
| 93 | case LCD_SPI_LINE_DATA :
|
| 94 | {
|
| 95 | if (data != hp49gp->lcd_spi.data)
|
| 96 | {
|
| 97 | verboselog( machine, 5, "LCD_SPI_LINE_DATA <- %d\n", data);
|
| 98 | hp49gp->lcd_spi.data = data;
|
| 99 | }
|
| 100 | }
|
| 101 | break;
|
| 102 | case LCD_SPI_LINE_3 :
|
| 103 | {
|
| 104 | if (data != hp49gp->lcd_spi.l3)
|
| 105 | {
|
| 106 | if ((data != 0) && (hp49gp->lcd_spi.l1 == 0))
|
| 107 | {
|
| 108 | verboselog( machine, 5, "LCD SPI write bit %d\n", hp49gp->lcd_spi.data ? 1 : 0);
|
| 109 | if (hp49gp->lcd_spi.bits < 8)
|
| 110 | {
|
| 111 | hp49gp->lcd_spi.shift = (hp49gp->lcd_spi.shift << 1) | (hp49gp->lcd_spi.data ? 1 : 0);
|
| 112 | }
|
| 113 | hp49gp->lcd_spi.bits++;
|
| 114 | if (hp49gp->lcd_spi.bits == 8)
|
| 115 | {
|
| 116 | verboselog( machine, 5, "LCD SPI write byte %02X\n", hp49gp->lcd_spi.shift);
|
| 117 | }
|
| 118 | else if (hp49gp->lcd_spi.bits == 9)
|
| 119 | {
|
| 120 | verboselog( machine, 5, "LCD SPI write ack %d\n", (hp49gp->lcd_spi.data ? 1 : 0));
|
| 121 | }
|
| 122 | }
|
| 123 | verboselog( machine, 5, "LCD_SPI_LINE_3 <- %d\n", data);
|
| 124 | hp49gp->lcd_spi.l3 = data;
|
| 125 | }
|
| 126 | }
|
| 127 | break;
|
| 128 | }
|
| 129 | }
|
| 130 | |
| 131 | static int lcd_spi_line_r( running_machine *machine, int line)
|
| 132 | {
|
| 133 | hp49gp_state *hp49gp = machine->driver_data<hp49gp_state>();
|
| 134 | switch (line)
|
| 135 | {
|
| 136 | case LCD_SPI_LINE_1 :
|
| 137 | {
|
| 138 | verboselog( machine, 7, "LCD_SPI_LINE_1 -> %d\n", hp49gp->lcd_spi.l1);
|
| 139 | return hp49gp->lcd_spi.l1;
|
| 140 | }
|
| 141 | break;
|
| 142 | case LCD_SPI_LINE_DATA :
|
| 143 | {
|
| 144 | verboselog( machine, 7, "LCD_SPI_LINE_DATA -> %d\n", hp49gp->lcd_spi.data);
|
| 145 | return hp49gp->lcd_spi.data;
|
| 146 | }
|
| 147 | break;
|
| 148 | case LCD_SPI_LINE_3 :
|
| 149 | {
|
| 150 | verboselog( machine, 7, "LCD_SPI_LINE_3 -> %d\n", hp49gp->lcd_spi.l3);
|
| 151 | return hp49gp->lcd_spi.l3;
|
| 152 | }
|
| 153 | break;
|
| 154 | }
|
| 155 | return 0;
|
| 156 | }
|
| 157 | |
| 158 | // I/O PORT
|
| 159 | |
| 160 | static UINT32 s3c2410_gpio_port_r( running_device *device, int port)
|
| 161 | {
|
| 162 | hp49gp_state *hp49gp = device->machine->driver_data<hp49gp_state>();
|
| 163 | UINT32 data = hp49gp->port[port];
|
| 164 | switch (port)
|
| 165 | {
|
| 166 | case S3C2410_GPIO_PORT_C :
|
| 167 | {
|
| 168 | data = data | 0xF000;
|
| 169 | }
|
| 170 | break;
|
| 171 | case S3C2410_GPIO_PORT_D :
|
| 172 | {
|
| 173 | data = data | 0x0008;
|
| 174 | data = data & ~0x3200;
|
| 175 | data |= (lcd_spi_line_r( device->machine, LCD_SPI_LINE_1) ? 1 : 0) << 9;
|
| 176 | data |= (lcd_spi_line_r( device->machine, LCD_SPI_LINE_DATA) ? 1 : 0) << 12;
|
| 177 | data |= (lcd_spi_line_r( device->machine, LCD_SPI_LINE_3) ? 1 : 0) << 13;
|
| 178 | }
|
| 179 | break;
|
| 180 | case S3C2410_GPIO_PORT_E :
|
| 181 | {
|
| 182 | data = data | 0xC000;
|
| 183 | }
|
| 184 | break;
|
| 185 | case S3C2410_GPIO_PORT_F :
|
| 186 | {
|
| 187 | data = data | 0x0008;
|
| 188 | }
|
| 189 | break;
|
| 190 | case S3C2410_GPIO_PORT_G :
|
| 191 | {
|
| 192 | data = data & ~0xFF00;
|
| 193 | if ((data & 0x02) == 0) data |= (input_port_read( device->machine, "ROW1") << 8);
|
| 194 | if ((data & 0x04) == 0) data |= (input_port_read( device->machine, "ROW2") << 8);
|
| 195 | if ((data & 0x08) == 0) data |= (input_port_read( device->machine, "ROW3") << 8);
|
| 196 | if ((data & 0x10) == 0) data |= (input_port_read( device->machine, "ROW4") << 8);
|
| 197 | if ((data & 0x20) == 0) data |= (input_port_read( device->machine, "ROW5") << 8);
|
| 198 | if ((data & 0x40) == 0) data |= (input_port_read( device->machine, "ROW6") << 8);
|
| 199 | if ((data & 0x80) == 0) data |= (input_port_read( device->machine, "ROW7") << 8);
|
| 200 | }
|
| 201 | break;
|
| 202 | case S3C2410_GPIO_PORT_H :
|
| 203 | {
|
| 204 | data = (data | 0x0080) & ~0x0040;
|
| 205 | }
|
| 206 | break;
|
| 207 | }
|
| 208 | return data;
|
| 209 | }
|
| 210 | |
| 211 | static void s3c2410_gpio_port_w( running_device *device, int port, UINT32 data)
|
| 212 | {
|
| 213 | hp49gp_state *hp49gp = device->machine->driver_data<hp49gp_state>();
|
| 214 | hp49gp->port[port] = data;
|
| 215 | switch (port)
|
| 216 | {
|
| 217 | case S3C2410_GPIO_PORT_D :
|
| 218 | {
|
| 219 | lcd_spi_line_w( device->machine, LCD_SPI_LINE_1, BIT( data, 9) ? 1 : 0);
|
| 220 | lcd_spi_line_w( device->machine, LCD_SPI_LINE_DATA, BIT( data, 12) ? 1 : 0);
|
| 221 | lcd_spi_line_w( device->machine, LCD_SPI_LINE_3, BIT( data, 13) ? 1 : 0);
|
| 222 | }
|
| 223 | break;
|
| 224 | }
|
| 225 | }
|
| 226 | |
| 227 | // ...
|
| 228 | |
| 229 | static INPUT_CHANGED( port_changed )
|
| 230 | {
|
| 231 | hp49gp_state *hp49gp = field->port->machine->driver_data<hp49gp_state>();
|
| 232 | s3c2410_request_eint( hp49gp->s3c2410, (int)param + 8);
|
| 233 | }
|
| 234 | |
| 235 | // ...
|
| 236 | |
| 237 | static MACHINE_START( hp49gp )
|
| 238 | {
|
| 239 | hp49gp_state *hp49gp = machine->driver_data<hp49gp_state>();
|
| 240 | hp49gp->s3c2410 = machine->device( "s3c2410");
|
| 241 | }
|
| 242 | |
| 243 | static MACHINE_RESET( hp49gp )
|
| 244 | {
|
| 245 | // hp49gp_state *hp49gp = machine->driver_data<hp49gp_state>();
|
| 246 | devtag_reset( machine, "maincpu");
|
| 247 | }
|
| 248 | |
| 249 | /***************************************************************************
|
| 250 | ADDRESS MAPS
|
| 251 | ***************************************************************************/
|
| 252 | |
| 253 | static ADDRESS_MAP_START( hp49gp_map, ADDRESS_SPACE_PROGRAM, 32 )
|
| 254 | AM_RANGE(0x00000000, 0x001fffff) AM_ROM
|
| 255 | AM_RANGE(0x08000000, 0x0801ffff) AM_RAM
|
| 256 | AM_RANGE(0x08020000, 0x0803ffff) AM_RAM
|
| 257 | AM_RANGE(0x08040000, 0x0807ffff) AM_RAM
|
| 258 | AM_RANGE(0x40000000, 0x40000fff) AM_RAM AM_BASE_MEMBER(hp49gp_state, steppingstone)
|
| 259 | ADDRESS_MAP_END
|
| 260 | |
| 261 | /***************************************************************************
|
| 262 | MACHINE DRIVERS
|
| 263 | ***************************************************************************/
|
| 264 | |
| 265 | static DRIVER_INIT( hp49gp )
|
| 266 | {
|
| 267 | hp49gp_state *hp49gp = machine->driver_data<hp49gp_state>();
|
| 268 | UINT8 *rom = (UINT8 *)memory_region( machine, "maincpu");
|
| 269 | memcpy( hp49gp->steppingstone, rom, 1024);
|
| 270 | lcd_spi_init( machine);
|
| 271 | }
|
| 272 | |
| 273 | static S3C2410_INTERFACE( hp49gp_s3c2410_intf )
|
| 274 | {
|
| 275 | // GPIO (port read / port write)
|
| 276 | { s3c2410_gpio_port_r, s3c2410_gpio_port_w },
|
| 277 | // I2C (scl write / sda read / sda write)
|
| 278 | { NULL, NULL, NULL },
|
| 279 | // ADC (data read)
|
| 280 | { NULL },
|
| 281 | // I2S (data write)
|
| 282 | { NULL },
|
| 283 | // NAND (command write, address write, data read, data write)
|
| 284 | { NULL, NULL, NULL, NULL }
|
| 285 | };
|
| 286 | |
| 287 | static MACHINE_CONFIG_START( hp49gp, hp49gp_state )
|
| 288 | MDRV_CPU_ADD("maincpu", ARM9, 400000000)
|
| 289 | MDRV_CPU_PROGRAM_MAP(hp49gp_map)
|
| 290 | |
| 291 | MDRV_PALETTE_LENGTH(32768)
|
| 292 | |
| 293 | MDRV_SCREEN_ADD("screen", LCD)
|
| 294 | MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
|
| 295 | MDRV_SCREEN_REFRESH_RATE(60)
|
| 296 | MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
|
| 297 | MDRV_SCREEN_SIZE(160, 85)
|
| 298 | MDRV_SCREEN_VISIBLE_AREA(0, 131 - 1, 0, 80 - 1)
|
| 299 | MDRV_DEFAULT_LAYOUT(layout_lcd)
|
| 300 | |
| 301 | MDRV_VIDEO_START(s3c2410)
|
| 302 | MDRV_VIDEO_UPDATE(s3c2410)
|
| 303 | |
| 304 | MDRV_MACHINE_START(hp49gp)
|
| 305 | MDRV_MACHINE_RESET(hp49gp)
|
| 306 | |
| 307 | MDRV_S3C2410_ADD("s3c2410", 12000000, hp49gp_s3c2410_intf)
|
| 308 | MACHINE_CONFIG_END
|
| 309 | |
| 310 | static INPUT_PORTS_START( hp49gp )
|
| 311 | PORT_START("ROW1")
|
| 312 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED(port_changed, (void *)1) PORT_NAME("F1 | A | Y=") PORT_CODE(KEYCODE_F1) PORT_CODE(KEYCODE_A) PORT_CHAR('A')
|
| 313 | PORT_BIT( 0xDF, IP_ACTIVE_LOW, IPT_UNUSED)
|
| 314 | PORT_START("ROW2")
|
| 315 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED(port_changed, (void *)2) PORT_NAME("F2 | B | WIN") PORT_CODE(KEYCODE_F2)
|
| 316 | PORT_BIT( 0xDF, IP_ACTIVE_LOW, IPT_UNUSED)
|
| 317 | PORT_START("ROW3")
|
| 318 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED(port_changed, (void *)3) PORT_NAME("F3 | C | GRAPH") PORT_CODE(KEYCODE_F3)
|
| 319 | PORT_BIT( 0xDF, IP_ACTIVE_LOW, IPT_UNUSED)
|
| 320 | PORT_START("ROW4")
|
| 321 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED(port_changed, (void *)4) PORT_NAME("F4 | D | 2D/3D") PORT_CODE(KEYCODE_F4)
|
| 322 | PORT_BIT( 0xDF, IP_ACTIVE_LOW, IPT_UNUSED)
|
| 323 | PORT_START("ROW5")
|
| 324 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED(port_changed, (void *)5) PORT_NAME("F5 | E | TBLSET") PORT_CODE(KEYCODE_F5)
|
| 325 | PORT_BIT( 0xDF, IP_ACTIVE_LOW, IPT_UNUSED)
|
| 326 | PORT_START("ROW6")
|
| 327 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED(port_changed, (void *)6) PORT_NAME("F6 | F | TABLE") PORT_CODE(KEYCODE_F6)
|
| 328 | PORT_BIT( 0xDF, IP_ACTIVE_LOW, IPT_UNUSED)
|
| 329 | PORT_START("ROW7")
|
| 330 | PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHANGED(port_changed, (void *)7) PORT_NAME("APPS | G | FILES | BEGIN") PORT_CODE(KEYCODE_G) PORT_CHAR('G')
|
| 331 | PORT_BIT( 0xDF, IP_ACTIVE_LOW, IPT_UNUSED)
|
| 332 | INPUT_PORTS_END
|
| 333 | |
| 334 | /***************************************************************************
|
| 335 | GAME DRIVERS
|
| 336 | ***************************************************************************/
|
| 337 | |
| 338 | ROM_START( hp49gp )
|
| 339 | ROM_REGION( 0x200000, "maincpu", 0 )
|
| 340 | ROM_SYSTEM_BIOS( 0, "319", "Version 3.19" )
|
| 341 | ROMX_LOAD( "319.bin", 0x0000, 0x4000, CRC(6bb5ebfb) SHA1(089c4e4ee7223b489e2f06c30aab0b89131d1c3c), ROM_BIOS(1) )
|
| 342 | ROM_SYSTEM_BIOS( 1, "315", "Version 3.15.04" )
|
| 343 | ROMX_LOAD( "31504.bin", 0x0000, 0x4000, CRC(9c71825e) SHA1(0a12b2b70a8573bc90ab5be06e6b2f814b8544ae), ROM_BIOS(2) )
|
| 344 | ROM_END
|
| 345 | |
| 346 | COMP(2009, hp49gp, 0, 0, hp49gp, hp49gp, hp49gp, "Hewlett Packard", "HP49G+", GAME_NOT_WORKING | GAME_NO_SOUND)
|