aboutsummaryrefslogtreecommitdiff
path: root/src/DSi_I2C.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/DSi_I2C.cpp')
-rw-r--r--src/DSi_I2C.cpp252
1 files changed, 252 insertions, 0 deletions
diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp
new file mode 100644
index 0000000..0ab7008
--- /dev/null
+++ b/src/DSi_I2C.cpp
@@ -0,0 +1,252 @@
+/*
+ Copyright 2016-2019 Arisotura
+
+ 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 "DSi.h"
+#include "DSi_I2C.h"
+#include "DSi_Camera.h"
+
+
+namespace DSi_BPTWL
+{
+
+u8 Registers[0x100];
+u32 CurPos;
+
+bool Init()
+{
+ return true;
+}
+
+void DeInit()
+{
+}
+
+void Reset()
+{
+ CurPos = -1;
+ memset(Registers, 0x5A, 0x100);
+
+ Registers[0x00] = 0x33; // TODO: support others??
+ Registers[0x01] = 0x00;
+ Registers[0x02] = 0x50;
+ Registers[0x10] = 0x00; // power btn
+ Registers[0x11] = 0x00; // reset
+ Registers[0x12] = 0x00; // power btn tap
+ Registers[0x20] = 0x83; // battery
+ Registers[0x21] = 0x07;
+ Registers[0x30] = 0x13;
+ Registers[0x31] = 0x00; // camera power
+ Registers[0x40] = 0x1F; // volume
+ Registers[0x41] = 0x04; // backlight
+ Registers[0x60] = 0x00;
+ Registers[0x61] = 0x01;
+ Registers[0x62] = 0x50;
+ Registers[0x63] = 0x00;
+ Registers[0x70] = 0x00; // boot flag
+ Registers[0x71] = 0x00;
+ Registers[0x72] = 0x00;
+ Registers[0x73] = 0x00;
+ Registers[0x74] = 0x00;
+ Registers[0x75] = 0x00;
+ Registers[0x76] = 0x00;
+ Registers[0x77] = 0x00;
+ Registers[0x80] = 0x10;
+ Registers[0x81] = 0x64;
+}
+
+void Start()
+{
+ //printf("BPTWL: start\n");
+}
+
+u8 Read(bool last)
+{
+ if (last)
+ {
+ CurPos = -1;
+ return 0;
+ }
+
+ //printf("BPTWL: read %02X -> %02X\n", CurPos, Registers[CurPos]);
+ return Registers[CurPos++];
+}
+
+void Write(u8 val, bool last)
+{
+ if (last)
+ {
+ CurPos = -1;
+ return;
+ }
+
+ if (CurPos == -1)
+ {
+ CurPos = val;
+ //printf("BPTWL: reg=%02X\n", val);
+ return;
+ }
+
+ if (CurPos == 0x11 && val == 0x01)
+ {
+ printf("BPTWL: soft-reset\n");
+ val = 0; // checkme
+ DSi::SoftReset();
+ }
+
+ if (CurPos == 0x11 || CurPos == 0x12 ||
+ CurPos == 0x21 ||
+ CurPos == 0x30 || CurPos == 0x31 ||
+ CurPos == 0x40 || CurPos == 0x31 ||
+ CurPos == 0x60 || CurPos == 0x63 ||
+ (CurPos >= 0x70 && CurPos <= 0x77) ||
+ CurPos == 0x80 || CurPos == 0x81)
+ {
+ Registers[CurPos] = val;
+ }
+
+ //printf("BPTWL: write %02X -> %02X\n", CurPos, val);
+ CurPos++; // CHECKME
+}
+
+}
+
+
+namespace DSi_I2C
+{
+
+u8 Cnt;
+u8 Data;
+
+u32 Device;
+
+bool Init()
+{
+ if (!DSi_BPTWL::Init()) return false;
+ if (!DSi_Camera::Init()) return false;
+
+ return true;
+}
+
+void DeInit()
+{
+ DSi_BPTWL::DeInit();
+ DSi_Camera::DeInit();
+}
+
+void Reset()
+{
+ Cnt = 0;
+ Data = 0;
+
+ Device = -1;
+
+ DSi_BPTWL::Reset();
+ DSi_Camera::Reset();
+}
+
+void WriteCnt(u8 val)
+{
+ //printf("I2C: write CNT %02X, %08X\n", val, NDS::GetPC(1));
+
+ // TODO: check ACK flag
+ // TODO: transfer delay
+ // TODO: IRQ
+ // TODO: check read/write direction
+
+ if (val & (1<<7))
+ {
+ bool islast = val & (1<<0);
+
+ if (val & (1<<5))
+ {
+ // read
+ val &= 0xF7;
+
+ switch (Device)
+ {
+ case 0x4A: Data = DSi_BPTWL::Read(islast); break;
+ case 0x78: Data = DSi_Camera0->Read(islast); break;
+ case 0x7A: Data = DSi_Camera1->Read(islast); break;
+ default:
+ printf("I2C: read on unknown device %02X, cnt=%02X, data=%02X, last=%d\n", Device, val, 0, islast);
+ Data = 0xFF;
+ break;
+ }
+
+ //printf("I2C read, device=%02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast);
+ }
+ else
+ {
+ // write
+ val &= 0xE7;
+ bool ack = true;
+
+ if (val & (1<<1))
+ {
+ Device = Data & 0xFE;
+ //printf("I2C: %s start, device=%02X\n", (Data&0x01)?"read":"write", Device);
+
+ switch (Device)
+ {
+ case 0x4A: DSi_BPTWL::Start(); break;
+ case 0x78: DSi_Camera0->Start(); break;
+ case 0x7A: DSi_Camera1->Start(); break;
+ default:
+ printf("I2C: %s start on unknown device %02X\n", (Data&0x01)?"read":"write", Device);
+ ack = false;
+ break;
+ }
+ }
+ else
+ {
+ //printf("I2C write, device=%02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast);
+
+ switch (Device)
+ {
+ case 0x4A: DSi_BPTWL::Write(Data, islast); break;
+ case 0x78: DSi_Camera0->Write(Data, islast); break;
+ case 0x7A: DSi_Camera1->Write(Data, islast); break;
+ default:
+ printf("I2C: write on unknown device %02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast);
+ ack = false;
+ break;
+ }
+ }
+
+ if (ack) val |= (1<<4);
+ }
+
+ val &= 0x7F;
+ }
+
+ Cnt = val;
+}
+
+u8 ReadData()
+{
+ return Data;
+}
+
+void WriteData(u8 val)
+{
+ Data = val;
+}
+
+}