BizHawk/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/SerialPort.cs

152 lines
2.9 KiB
C#
Raw Normal View History

using System;
using BizHawk.Emulation.Common;
using BizHawk.Common.NumberExtensions;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
public class SerialPort
{
public GBHawk Core { get; set; }
public byte serial_control;
public byte serial_data;
public bool serial_start;
public int serial_clock;
public int serial_bits;
public bool clk_internal;
public int clk_rate;
public byte ReadReg(int addr)
{
switch (addr)
{
case 0xFF01:
return serial_data;
case 0xFF02:
return serial_control;
}
2017-11-22 16:10:45 +00:00
return 0xFF;
}
public void WriteReg(int addr, byte value)
{
switch (addr)
{
case 0xFF01:
serial_data = value;
break;
case 0xFF02:
if (((value & 0x80) > 0) && !serial_start)
{
serial_start = true;
serial_bits = 8;
if ((value & 1) > 0)
{
clk_internal = true;
clk_rate = 512;
serial_clock = clk_rate;
}
else
{
clk_internal = false;
clk_rate = get_external_clock();
serial_clock = clk_rate;
}
}
2017-11-22 16:10:45 +00:00
else if (serial_start)
{
if ((value & 1) > 0)
{
clk_internal = true;
clk_rate = 512;
serial_clock = clk_rate;
}
else
{
clk_internal = false;
clk_rate = get_external_clock();
serial_clock = clk_rate;
}
}
serial_control = (byte)(0x7E | (value & 0x81)); // middle six bits always 1
break;
}
}
public void serial_transfer_tick()
{
if (serial_start)
{
2017-11-22 16:10:45 +00:00
if (serial_clock > 0) { serial_clock--; }
if (serial_clock == 0)
{
if (serial_bits > 0)
{
send_external_bit((byte)(serial_data & 0x80));
byte temp = get_external_bit();
serial_data = (byte)((serial_data << 1) | temp);
serial_bits--;
if (serial_bits == 0)
{
serial_control &= 0x7F;
serial_start = false;
if (Core.REG_FFFF.Bit(3)) { Core.cpu.FlagI = true; }
Core.REG_FF0F |= 0x08;
}
else
{
serial_clock = clk_rate;
}
}
}
}
}
// call this function to get the clock rate of a connected device
2017-11-22 16:10:45 +00:00
// if no external device, the clocking doesn't occur
public int get_external_clock()
{
2017-11-22 16:10:45 +00:00
return -1;
}
// call this function to get the next bit from the connected device
// no device connected returns 0xFF
public byte get_external_bit()
{
return 1;
}
public void send_external_bit(byte bit_send)
{
}
public void Reset()
{
serial_control = 0x7E;
serial_start = false;
2017-11-22 16:10:45 +00:00
serial_data = 0x00;
}
public void SyncState(Serializer ser)
{
ser.Sync("serial_control", ref serial_control);
ser.Sync("serial_data", ref serial_data);
ser.Sync("serial_start", ref serial_start);
ser.Sync("serial_clock", ref serial_clock);
ser.Sync("serial_bits", ref serial_bits);
ser.Sync("clk_internal", ref clk_internal);
ser.Sync("clk_rate", ref clk_rate);
}
}
}