103 lines
2.0 KiB
C++
103 lines
2.0 KiB
C++
/*
|
|
this file contains the sio subsystem emulation.
|
|
*/
|
|
|
|
#include "psx.h"
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stddef.h>
|
|
|
|
|
|
static u8 getPrescaler(const u32 prescaler_type)
|
|
{
|
|
static const u8 prescalers[] = {0,1,16,64};
|
|
return prescalers[prescaler_type];
|
|
}
|
|
|
|
|
|
//information in this file is derived from observatoins in mednafen and mame
|
|
|
|
void PSX::SioController::Reset()
|
|
{
|
|
status.TX_EMPTY = 1;
|
|
status.TX_RDY = 1;
|
|
status.RX_RDY = 0;
|
|
status.OVERRUN = 0;
|
|
status.IRQ = 0;
|
|
}
|
|
|
|
float PSX::SioController::CalculateBaud()
|
|
{
|
|
return (float)PSX_CLOCK / this->baud_reg / getPrescaler(mode.prescaler_type);
|
|
}
|
|
|
|
void PSX::sio_wr(const int size, const u32 addr, const u32 val)
|
|
{
|
|
assert(size==2);
|
|
assert((addr&1)==0);
|
|
DEBUG_SIO("sio write size %d addr %08X = %08X\n",size,addr,val);
|
|
const u32 portnum = (addr>>4)&1;
|
|
SioController &port = sio[portnum];
|
|
|
|
switch(addr&0xF)
|
|
{
|
|
case 0x00:
|
|
break;
|
|
case 0x08:
|
|
port.mode.value = val;
|
|
printf("baud set to approx %f\n",port.CalculateBaud());
|
|
break;
|
|
case 0x0A:
|
|
{
|
|
SioController::ControlReg reg;
|
|
reg.value = val;
|
|
if(reg.RESET)
|
|
{
|
|
DEBUG_SIO("reset port %d\n",portnum);
|
|
port.Reset();
|
|
}
|
|
if(reg.IACK)
|
|
{
|
|
port.status.IRQ = 0;
|
|
port.control.IACK = 0;
|
|
//todo - irq sync
|
|
}
|
|
|
|
//check for rising edge of DTR signal and alert the appropriate port
|
|
if(port.control.DTR == 0 && reg.DTR == 1)
|
|
{
|
|
sio_dtr(port.control.PORT_SEL);
|
|
}
|
|
|
|
//replicate stored bits
|
|
port.control.TX_IENA = reg.RX_IENA;
|
|
port.control.RX_IENA = reg.RX_IENA;
|
|
port.control.DSR_IENA = reg.DSR_IENA;
|
|
port.control.DTR = reg.DTR;
|
|
port.control.PORT_SEL = reg.PORT_SEL;
|
|
}
|
|
break;
|
|
case 0x0E:
|
|
port.baud_reg = val;
|
|
printf("baud set to approx %f\n",port.CalculateBaud());
|
|
break;
|
|
default:
|
|
DEBUG_SIO("UNHANDLED\n");
|
|
}
|
|
}
|
|
|
|
void PSX::sio_dtr(const u32 port)
|
|
{
|
|
}
|
|
|
|
u32 PSX::sio_rd(const int size, const u32 addr)
|
|
{
|
|
assert(size==2);
|
|
assert((addr&1)==0);
|
|
u32 ret = 0;
|
|
DEBUG_SIO("sio read size %d addr %08X = %08X\n",size,addr,ret);
|
|
const u32 port = (addr>>4)&1;
|
|
|
|
return 0;
|
|
}
|