diff options
Diffstat (limited to 'RTC.cpp')
-rw-r--r-- | RTC.cpp | 250 |
1 files changed, 250 insertions, 0 deletions
@@ -0,0 +1,250 @@ +/* + Copyright 2016-2017 StapleButter + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include <stdio.h> +#include <string.h> +#include "RTC.h" + + +namespace RTC +{ + +u16 IO; + +u8 Input; +u32 InputBit; +u32 InputPos; + +u8 Output[8]; +u32 OutputBit; +u32 OutputPos; + +u8 CurCmd; + +u8 StatusReg1; +u8 StatusReg2; +u8 Alarm1[3]; +u8 Alarm2[3]; +u8 ClockAdjust; +u8 FreeReg; + + +void Init() +{ +} + +void Reset() +{ + Input = 0; + InputBit = 0; + InputPos = 0; + + memset(Output, 0, sizeof(Output)); + OutputPos = 0; + + CurCmd = 0; + + StatusReg1 = 0; + StatusReg2 = 0; + memset(Alarm1, 0, sizeof(Alarm1)); + memset(Alarm2, 0, sizeof(Alarm2)); + ClockAdjust = 0; + FreeReg = 0; +} + + +void ByteIn(u8 val) +{ + //printf("RTC IN: %02X\n", val); + if (InputPos == 0) + { + if ((val & 0xF0) == 0x60) + { + u8 rev[16] = {0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6}; + CurCmd = rev[val & 0xF]; + } + else + CurCmd = val; + + if (CurCmd & 0x80) + { + switch (CurCmd & 0x70) + { + case 0x00: Output[0] = StatusReg1; break; + case 0x40: Output[0] = StatusReg2; break; + + case 0x20: + // TODO: get actual system time + Output[0] = 0x16; + Output[1] = 0x01; + Output[2] = 0x19; + Output[3] = 0x03; // day of week. checkme + Output[4] = 0x06; + Output[5] = 0x30; + Output[6] = 0x30; + break; + + case 0x60: + // TODO: get actual system time + Output[0] = 0x06; + Output[1] = 0x30; + Output[2] = 0x30; + break; + + case 0x10: + if (StatusReg2 & 0x04) + { + Output[0] = Alarm1[0]; + Output[1] = Alarm1[1]; + Output[2] = Alarm1[2]; + } + else + Output[0] = Alarm1[2]; + break; + + case 0x50: + Output[0] = Alarm2[0]; + Output[1] = Alarm2[1]; + Output[2] = Alarm2[2]; + break; + + case 0x30: Output[0] = ClockAdjust; break; + case 0x70: Output[0] = FreeReg; break; + } + } + InputPos++; + return; + } + + switch (CurCmd & 0x70) + { + case 0x00: + if (InputPos == 1) StatusReg1 = val & 0x0E; + break; + + case 0x40: + if (InputPos == 1) StatusReg2 = val; + if (StatusReg2 & 0x4F) printf("RTC INTERRUPT ON: %02X\n", StatusReg2); + break; + + case 0x20: + // TODO: set time somehow?? + break; + + case 0x60: + // same shit + break; + + case 0x10: + if (StatusReg2 & 0x04) + { + if (InputPos <= 3) Alarm1[InputPos-1] = val; + } + else + { + if (InputPos == 1) Alarm1[2] = val; + } + break; + + case 0x50: + if (InputPos <= 3) Alarm2[InputPos-1] = val; + break; + + case 0x30: + if (InputPos == 1) ClockAdjust = val; + break; + + case 0x70: + if (InputPos == 1) FreeReg = val; + break; + } + + InputPos++; +} + + +u16 Read() +{ + //printf("RTC READ %04X\n", IO); + return IO; +} + +void Write(u16 val, bool byte) +{ + if (byte) val |= (IO & 0xFF00); + + //printf("RTC WRITE %04X\n", val); + if (val & 0x0004) + { + if (!(IO & 0x0004)) + { + // start transfer + Input = 0; + InputBit = 0; + InputPos = 0; + + memset(Output, 0, sizeof(Output)); + OutputBit = 0; + OutputPos = 0; + } + else + { + if (!(val & 0x0002)) // clock low + { + if (val & 0x0010) + { + // write + if (val & 0x0001) + Input |= (1<<InputBit); + + InputBit++; + if (InputBit >= 8) + { + InputBit = 0; + ByteIn(Input); + Input = 0; + InputPos++; + } + } + else + { + // read + if (Output[OutputPos] & (1<<OutputBit)) + IO |= 0x0001; + else + IO &= 0xFFFE; + + OutputBit++; + if (OutputBit >= 8) + { + OutputBit = 0; + if (OutputPos < 7) + OutputPos++; + } + } + } + } + } + + if (val & 0x0010) + IO = val; + else + IO = (IO & 0x0001) | (val & 0xFFFE); +} + +} |