public byte Read(byte[] saveRAM) { switch (ReadMode) { case EEPROMReadMode.ReadNew: // A new value clocking out ReadMode = EEPROMReadMode.ReadOld; byte ret = Read(saveRAM); if (++BitsRead == 8) { // Increment address BitsRead = 0; ++Address; if (Address % 2 == 0) { WriteMode = EEPROMWriteMode.Instruction; ReadMode = EEPROMReadMode.Hold; BitsWritten = 0; Value = 0; } } return(ret); case EEPROMReadMode.ReadOld: // repeat old value byte bit = (byte)((saveRAM[Address % saveRAM.Length] >> (7 - BitsRead)) & 1); return((byte)((byte)(Flags | EEPROMFlags.Clock) | bit)); default: // ready/busy flag is always ready in this emulation return((byte)(Flags | EEPROMFlags.Clock | EEPROMFlags.Ready)); } }
public void Write(byte bit, byte[] saveRAM) { // new instruction? if ((bit & 4) == 0) { WriteMode = EEPROMWriteMode.Instruction; ReadMode = EEPROMReadMode.Hold; BitsWritten = 0; Value = 0; Flags = (EEPROMFlags)bit & ~EEPROMFlags.Ready; return; } // clock low to high? if ((bit & (byte)EEPROMFlags.Clock) != 0 && (Flags & EEPROMFlags.Clock) == 0) { // all modes shift in a larger value Value = (ushort)((Value << 1) | (bit & 1)); ++BitsWritten; switch (WriteMode) { case EEPROMWriteMode.Instruction: // Process opcode including start bit // check start bit if ((Value & 0x100) == 0) { return; } byte op = (byte)Value; Value = 0; BitsWritten = 0; switch (op & 0xC0) { case 0x00: // non-addressed commands switch (op & 0xF0) { case 0x00: // EWDS: write disable WriteEnable = false; return; case 0x10: // WRAL: write to all addresses (silly) WriteMode = EEPROMWriteMode.WriteAll; ReadMode = EEPROMReadMode.Hold; return; case 0x20: // ERAL: erase all addresses if (WriteEnable) { for (int i = 0; i < saveRAM.Length; ++i) { saveRAM[i] = 0xFF; } } ReadMode = EEPROMReadMode.Hold; return; case 0x30: // EWEN: write enable WriteEnable = true; return; default: // impossible return; } case 0x40: // WRITE Address = (ushort)((op & 0x3F) << 1); WriteMode = EEPROMWriteMode.WriteData; ReadMode = EEPROMReadMode.Hold; return; case 0x80: // READ Address = (ushort)((op & 0x3F) << 1); ReadMode = EEPROMReadMode.Hold; WriteMode = EEPROMWriteMode.Read; BitsRead = 0; return; case 0xC0: // ERASE Address = (ushort)((op & 0x3F) << 1); if (WriteEnable) { saveRAM[Address % saveRAM.Length] = 0xFF; saveRAM[(Address + 1) % saveRAM.Length] = 0xFF; } ReadMode = EEPROMReadMode.Hold; return; default: // impossible return; } case EEPROMWriteMode.WriteData: // Write bits if (BitsWritten < 16) { return; } if (WriteEnable) { saveRAM[Address % saveRAM.Length] = (byte)(Value >> 8); saveRAM[(Address + 1) % saveRAM.Length] = (byte)Value; } WriteMode = EEPROMWriteMode.Instruction; Value = 0; BitsWritten = 0; return; case EEPROMWriteMode.WriteAll: // write to ALL addresses if (BitsWritten < 16) { return; } Value = 0; BitsWritten = 0; if (WriteEnable) { for (int i = 0; i < saveRAM.Length; i += 2) { saveRAM[i % saveRAM.Length] = (byte)Value; saveRAM[(i + 1) % saveRAM.Length] = (byte)(Value >> 8); } } WriteMode = EEPROMWriteMode.Instruction; return; case EEPROMWriteMode.Read: // Clock a new value out ReadMode = EEPROMReadMode.ReadNew; return; } } Flags = (EEPROMFlags)bit & ~EEPROMFlags.Ready; }