-psion5: Renamed to psion5mx, added ETNA device, many fixes, nw

This commit is contained in:
MooglyGuy 2020-01-04 14:02:03 +01:00
parent 88909dc0d0
commit ae494b6d0f
4 changed files with 931 additions and 341 deletions

File diff suppressed because it is too large Load Diff

194
src/mame/includes/psion5.h Normal file
View File

@ -0,0 +1,194 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz, Ash Wolf
/***************************************************************************
Psion 5mx (EPOC R5) series and peripherals
Skeleton driver by Ryan Holtz, ported from work by Ash Wolf
****************************************************************************/
#ifndef MAME_INCLUDES_PSION5_H
#define MAME_INCLUDES_PSION5_H
#pragma once
#include "emu.h"
#include "cpu/arm7/arm7.h"
#include "cpu/arm7/arm7core.h"
#include "machine/etna.h"
#include "screen.h"
class psion5mx_state : public driver_device
{
public:
psion5mx_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_etna(*this, "etna")
, m_lcd_ram(*this, "lcd_ram")
{
}
void psion5mx(machine_config &config);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
DECLARE_READ32_MEMBER(periphs_r);
DECLARE_WRITE32_MEMBER(periphs_w);
void update_timer(int timer);
void set_timer_ctrl(int timer, uint32_t value);
void check_interrupts();
static constexpr device_timer_id TID_TIMER1 = 0;
static constexpr device_timer_id TID_TIMER2 = 1;
static constexpr device_timer_id TID_PERIODIC = 2;
static constexpr device_timer_id TID_RTC_TICKER = 3;
enum
{
REG_MEMCFG1 = 0x0000,
REG_MEMCFG2 = 0x0004,
REG_DRAMCFG = 0x0100,
REG_LCDCTL = 0x0200,
REG_LCDST = 0x0204,
REG_LCD_DBAR1 = 0x0210,
REG_LCDT0 = 0x0220,
REG_LCDT1 = 0x0224,
REG_LCDT2 = 0x0228,
REG_PWRSR = 0x0400,
REG_PWRCNT = 0x0404,
REG_HALT = 0x0408,
REG_STBY = 0x040c,
REG_BLEOI = 0x0410,
REG_MCEOI = 0x0414,
REG_TEOI = 0x0418,
REG_STFCLR = 0x041c,
REG_E2EOI = 0x0420,
REG_INTSR = 0x0500,
REG_INTRSR = 0x0504,
REG_INTENS = 0x0508,
REG_INTENC = 0x050c,
REG_INTTEST1 = 0x0514,
REG_INTTEST2 = 0x0518,
REG_PUMPCON = 0x0900,
REG_CODR = 0x0a00,
REG_CONFG = 0x0a04,
REG_COLFG = 0x0a08,
REG_COEOI = 0x0a0c,
REG_COTEST = 0x0a10,
REG_SSCR0 = 0x0b00,
REG_SSCR1 = 0x0b04,
REG_SSDR = 0x0b0c,
REG_SSSR = 0x0b14,
REG_TC1LOAD = 0x0c00,
REG_TC1VAL = 0x0c04,
REG_TC1CTRL = 0x0c08,
REG_TC1EOI = 0x0c0c,
REG_TC2LOAD = 0x0c20,
REG_TC2VAL = 0x0c24,
REG_TC2CTRL = 0x0c28,
REG_TC2EOI = 0x0c2c,
REG_BZCONT = 0x0c40,
REG_RTCDRL = 0x0d00,
REG_RTCDRU = 0x0d04,
REG_RTCMRL = 0x0d08,
REG_RTCMRU = 0x0d0c,
REG_RTCEOI = 0x0d10,
REG_PADR = 0x0e00,
REG_PBDR = 0x0e04,
REG_PCDR = 0x0e08,
REG_PDDR = 0x0e0c,
REG_PADDR = 0x0e10,
REG_PBDDR = 0x0e14,
REG_PCDDR = 0x0e18,
REG_PDDDR = 0x0e1c,
REG_PEDR = 0x0e20,
REG_PEDDR = 0x0e24,
REG_KSCAN = 0x0e28,
REG_LCDMUX = 0x0e2c
};
enum
{
IRQ_EXTFIQ = 0, // FiqExternal
IRQ_BLINT = 1, // FiqBatLow
IRQ_WEINT = 2, // FiqWatchDog
IRQ_MCINT = 3, // FiqMediaChg
IRQ_CSINT = 4, // IrqCodec
IRQ_EINT1 = 5, // IrqExt1
IRQ_EINT2 = 6, // IrqExt2
IRQ_EINT3 = 7, // IrqExt3
IRQ_TC1OI = 8, // IrqTimer1
IRQ_TC2OI = 9, // IrqTimer2
IRQ_RTCMI = 10, // IrqRtcMatch
IRQ_TINT = 11, // IrqTick
IRQ_UART1 = 12, // IrqUart1
IRQ_UART2 = 13, // IrqUart2
IRQ_LCDINT = 14, // IrqLcd
IRQ_SSEOTI = 15, // IrqSpi
IRQ_FIQ_MASK = 0x000f,
IRQ_IRQ_MASK = 0xfff0
};
enum
{
PORTA,
PORTB,
PORTC,
PORTD,
PORTE
};
void main_map(address_map &map);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
uint8_t read_keyboard();
required_device<arm710t_cpu_device> m_maincpu;
required_device<etna_device> m_etna;
required_shared_ptr<uint32_t> m_lcd_ram;
emu_timer *m_timers[2];
uint16_t m_timer_reload[2];
uint16_t m_timer_ctrl[2];
uint16_t m_timer_value[2];
uint32_t m_pending_ints;
uint32_t m_int_mask;
uint32_t m_lcd_display_base_addr;
uint32_t m_rtc;
uint32_t m_pwrsr;
uint32_t m_last_ssi_request;
uint32_t m_ssi_read_counter;
uint8_t m_ports[5];
emu_timer *m_periodic;
emu_timer *m_rtc_ticker;
};
#endif // MAME_INCLUDES_PSION5_H

257
src/mame/machine/etna.cpp Normal file
View File

@ -0,0 +1,257 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz, Ash Wolf
/***************************************************************************
Psion 5mx (EPOC R5) series ETNA peripheral
Skeleton device by Ryan Holtz, ported from work by Ash Wolf
More info:
https://github.com/Treeki/WindEmu
****************************************************************************/
#include "etna.h"
#define LOG_READS (1 << 0)
#define LOG_WRITES (1 << 1)
#define LOG_UNKNOWNS (1 << 2)
#define LOG_PROM (1 << 3)
#define LOG_ALL (LOG_READS | LOG_WRITES | LOG_UNKNOWNS | LOG_PROM)
#define VERBOSE (LOG_ALL)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(ETNA, etna_device, "etna", "Psion 5mx ETNA")
etna_device::etna_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, ETNA, tag, owner, clock)
, m_eeprom_data_out(*this)
{
}
void etna_device::device_start()
{
save_item(NAME(m_prom_addr_count));
save_item(NAME(m_prom_addr));
save_item(NAME(m_prom_value));
save_item(NAME(m_prom_cs));
save_item(NAME(m_prom_clk));
save_item(NAME(m_pending_ints));
save_item(NAME(m_regs));
save_item(NAME(m_prom));
}
void etna_device::device_reset()
{
m_prom_addr_count = 0;
m_prom_addr = 0;
m_prom_value = 0;
m_prom_cs = false;
m_prom_clk = false;
m_pending_ints = 0;
memset(m_regs, 0, ARRAY_LENGTH(m_regs));
memset(m_prom, 0, ARRAY_LENGTH(m_prom));
// defaults expected by the touchscreen code
m_prom[0x0a] = 20;
m_prom[0x0b] = 20;
m_prom[0x0c] = 20;
m_prom[0x0d] = 30;
// some basic stuff to begin with
// set up the Psion's unique ID
m_prom[0x1b] = 0xde;
m_prom[0x1a] = 0xad;
m_prom[0x19] = 0xbe;
m_prom[0x18] = 0xef;
// give ourselves a neat custom device name
const char *key = "PSION";
const char *name = "MAME!";
m_prom[0x28] = strlen(name);
for (int i = 0; i < m_prom[0x28]; i++)
m_prom[0x29 + i] = name[i] ^ key[i];
// calculate the checksum
uint8_t chk = 0;
for (int i = 0; i < 0x7F; i++)
chk ^= m_prom[i];
// EPOC is expecting 66
m_prom[0x7f] = chk ^ 66;
}
WRITE8_MEMBER(etna_device::regs_w)
{
switch (offset)
{
case REG_UNK0:
LOGMASKED(LOG_WRITES, "%s: etna reg write: UNK0 = %02x\n", machine().describe_context(), data);
break;
case REG_UNK1:
LOGMASKED(LOG_WRITES, "%s: etna reg write: UNK1 = %02x\n", machine().describe_context(), data);
break;
case REG_UART_INT_STATUS:
LOGMASKED(LOG_WRITES, "%s: etna reg write: INT_STATUS = %02x\n", machine().describe_context(), data);
break;
case REG_UART_INT_MASK:
LOGMASKED(LOG_WRITES, "%s: etna reg write: INT_MASK = %02x\n", machine().describe_context(), data);
break;
case REG_UART_BAUD_LO:
LOGMASKED(LOG_WRITES, "%s: etna reg write: BAUD_LO = %02x\n", machine().describe_context(), data);
break;
case REG_UART_BAUD_HI:
LOGMASKED(LOG_WRITES, "%s: etna reg write: BAUD_HI = %02x\n", machine().describe_context(), data);
break;
case REG_PCCD_INT_STATUS:
LOGMASKED(LOG_WRITES, "%s: etna reg write: PCCD_INT_STATUS = %02x\n", machine().describe_context(), data);
break;
case REG_PCCD_INT_MASK:
LOGMASKED(LOG_WRITES, "%s: etna reg write: PCCD_INT_MASK = %02x\n", machine().describe_context(), data);
break;
case REG_INT_CLEAR:
LOGMASKED(LOG_WRITES, "%s: etna reg write: INT_CLEAR = %02x\n", machine().describe_context(), data);
m_pending_ints &= ~data;
break;
case REG_SKT_VAR_A0:
LOGMASKED(LOG_WRITES, "%s: etna reg write: SKT_VAR_A0 = %02x\n", machine().describe_context(), data);
break;
case REG_SKT_VAR_A1:
LOGMASKED(LOG_WRITES, "%s: etna reg write: SKT_VAR_A1 = %02x\n", machine().describe_context(), data);
break;
case REG_SKT_CTRL:
LOGMASKED(LOG_WRITES, "%s: etna reg write: SKT_CTRL = %02x\n", machine().describe_context(), data);
break;
case REG_WAKE1:
LOGMASKED(LOG_WRITES, "%s: etna reg write: WAKE1 = %02x\n", machine().describe_context(), data);
m_regs[REG_WAKE1] = data;
break;
case REG_SKT_VAR_B0:
LOGMASKED(LOG_WRITES, "%s: etna reg write: SKT_VAR_B0 = %02x\n", machine().describe_context(), data);
break;
case REG_SKT_VAR_B1:
LOGMASKED(LOG_WRITES, "%s: etna reg write: SKT_VAR_B1 = %02x\n", machine().describe_context(), data);
break;
case REG_WAKE2:
LOGMASKED(LOG_WRITES, "%s: etna reg write: WAKE2 = %02x\n", machine().describe_context(), data);
m_regs[REG_WAKE2] = data;
break;
default:
LOGMASKED(LOG_UNKNOWNS, "%s: etna reg write: Unknown = %02x\n", machine().describe_context(), data);
break;
}
}
READ8_MEMBER(etna_device::regs_r)
{
uint8_t data = 0;
switch (offset)
{
case REG_UNK0:
LOGMASKED(LOG_READS, "%s: etna reg read: UNK0 = %02x\n", machine().describe_context(), data);
break;
case REG_UNK1:
LOGMASKED(LOG_READS, "%s: etna reg read: UNK1 = %02x\n", machine().describe_context(), data);
break;
case REG_UART_INT_STATUS:
LOGMASKED(LOG_READS, "%s: etna reg read: INT_STATUS = %02x\n", machine().describe_context(), data);
break;
case REG_UART_INT_MASK:
LOGMASKED(LOG_READS, "%s: etna reg read: INT_MASK = %02x\n", machine().describe_context(), data);
break;
case REG_UART_BAUD_LO:
LOGMASKED(LOG_READS, "%s: etna reg read: BAUD_LO = %02x\n", machine().describe_context(), data);
break;
case REG_UART_BAUD_HI:
LOGMASKED(LOG_READS, "%s: etna reg read: BAUD_HI = %02x\n", machine().describe_context(), data);
break;
case REG_PCCD_INT_STATUS:
LOGMASKED(LOG_READS, "%s: etna reg read: PCCD_INT_STATUS = %02x\n", machine().describe_context(), data);
break;
case REG_PCCD_INT_MASK:
LOGMASKED(LOG_READS, "%s: etna reg read: PCCD_INT_MASK = %02x\n", machine().describe_context(), data);
break;
case REG_INT_CLEAR:
LOGMASKED(LOG_READS, "%s: etna reg read: INT_CLEAR = %02x\n", machine().describe_context(), data);
break;
case REG_SKT_VAR_A0:
LOGMASKED(LOG_READS, "%s: etna reg read: SKT_VAR_A0 = %02x\n", machine().describe_context(), data);
data = 1;
break;
case REG_SKT_VAR_A1:
LOGMASKED(LOG_READS, "%s: etna reg read: SKT_VAR_A1 = %02x\n", machine().describe_context(), data);
break;
case REG_SKT_CTRL:
LOGMASKED(LOG_READS, "%s: etna reg read: SKT_CTRL = %02x\n", machine().describe_context(), data);
break;
case REG_WAKE1:
data = m_regs[REG_WAKE1];
LOGMASKED(LOG_READS, "%s: etna reg read: WAKE1 = %02x\n", machine().describe_context(), data);
break;
case REG_SKT_VAR_B0:
LOGMASKED(LOG_READS, "%s: etna reg read: SKT_VAR_B0 = %02x\n", machine().describe_context(), data);
break;
case REG_SKT_VAR_B1:
LOGMASKED(LOG_READS, "%s: etna reg read: SKT_VAR_B1 = %02x\n", machine().describe_context(), data);
break;
case REG_WAKE2:
data = m_regs[REG_WAKE2];
LOGMASKED(LOG_READS, "%s: etna reg read: WAKE2 = %02x\n", machine().describe_context(), data);
break;
default:
LOGMASKED(LOG_UNKNOWNS, "%s: etna reg read: Unknown = %02x\n", machine().describe_context(), data);
break;
}
return data;
}
WRITE_LINE_MEMBER(etna_device::eeprom_cs_in)
{
bool old = m_prom_cs;
m_prom_cs = state;
if (!old && m_prom_cs)
{
m_prom_addr_count = 0;
m_prom_addr = 0;
m_prom_value = 0;
}
}
WRITE_LINE_MEMBER(etna_device::eeprom_clk_in)
{
bool old = m_prom_clk;
m_prom_clk = state;
if (!old && m_prom_clk)
{
if (m_prom_addr_count < 10)
{
m_prom_addr <<= 1;
m_prom_addr |= BIT(m_regs[REG_WAKE1], 2);
m_prom_addr_count++;
if (m_prom_addr_count == 10)
{
LOGMASKED(LOG_PROM, "PROM Address: %03x\n", m_prom_addr);
uint16_t byte_addr = (m_prom_addr << 1) % ARRAY_LENGTH(m_prom);
m_prom_value = m_prom[byte_addr] | (m_prom[byte_addr + 1] << 8);
LOGMASKED(LOG_PROM, "PROM Value: %04x\n", m_prom_value);
}
}
else
{
m_regs[REG_WAKE1] &= ~0x08;
m_regs[REG_WAKE1] |= BIT(m_prom_value, 15) << 3;
LOGMASKED(LOG_PROM, "PROM Bit: %d\n", BIT(m_prom_value, 15));
m_prom_value <<= 1;
}
}
}
WRITE_LINE_MEMBER(etna_device::eeprom_data_in)
{
}

73
src/mame/machine/etna.h Normal file
View File

@ -0,0 +1,73 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz, Ash Wolf
/***************************************************************************
Psion 5mx (EPOC R5) series ETNA peripheral
Skeleton driver by Ryan Holtz, ported from work by Ash Wolf
****************************************************************************/
#ifndef MAME_MACHINE_ETNA_H
#define MAME_MACHINE_ETNA_H
#pragma once
#include "emu.h"
class etna_device : public device_t
{
public:
etna_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
DECLARE_WRITE8_MEMBER(regs_w);
DECLARE_READ8_MEMBER(regs_r);
DECLARE_WRITE_LINE_MEMBER(eeprom_cs_in);
DECLARE_WRITE_LINE_MEMBER(eeprom_clk_in);
DECLARE_WRITE_LINE_MEMBER(eeprom_data_in);
auto eeprom_data_out() { return m_eeprom_data_out.bind(); }
private:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
enum
{
REG_UNK0,
REG_UNK1,
REG_UART_INT_STATUS,
REG_UART_INT_MASK,
REG_UART_BAUD_LO,
REG_UART_BAUD_HI,
REG_PCCD_INT_STATUS,
REG_PCCD_INT_MASK,
REG_INT_CLEAR,
REG_SKT_VAR_A0,
REG_SKT_VAR_A1,
REG_SKT_CTRL,
REG_WAKE1,
REG_SKT_VAR_B0,
REG_SKT_VAR_B1,
REG_WAKE2
};
devcb_write_line m_eeprom_data_out;
uint8_t m_prom_addr_count;
uint16_t m_prom_addr;
uint16_t m_prom_value;
bool m_prom_cs;
bool m_prom_clk;
uint8_t m_pending_ints;
uint8_t m_regs[0x10];
uint8_t m_prom[0x80];
};
DECLARE_DEVICE_TYPE(ETNA, etna_device)
#endif // MAME_MACHINE_ETNA_H