convert DSi I2C and camera
This commit is contained in:
parent
7837c169a1
commit
54ebf1b1b2
42
src/DSi.cpp
42
src/DSi.cpp
|
@ -79,6 +79,8 @@ std::unique_ptr<DSi_NAND::NANDImage> NANDImage;
|
|||
DSi_SDHost* SDMMC;
|
||||
DSi_SDHost* SDIO;
|
||||
|
||||
DSi_I2CHost* I2C;
|
||||
DSi_CamModule* CamModule;
|
||||
DSi_AES* AES;
|
||||
|
||||
// FIXME: these currently have no effect (and aren't stored in a savestate)
|
||||
|
@ -102,8 +104,6 @@ bool Init()
|
|||
NWRAM_C = new u8[NWRAMSize];
|
||||
#endif
|
||||
|
||||
if (!DSi_I2C::Init()) return false;
|
||||
if (!DSi_CamModule::Init()) return false;
|
||||
if (!DSi_DSP::Init()) return false;
|
||||
|
||||
NDMAs[0] = new DSi_NDMA(0, 0);
|
||||
|
@ -118,6 +118,8 @@ bool Init()
|
|||
SDMMC = new DSi_SDHost(0);
|
||||
SDIO = new DSi_SDHost(1);
|
||||
|
||||
I2C = new DSi_I2CHost();
|
||||
CamModule = new DSi_CamModule();
|
||||
AES = new DSi_AES();
|
||||
|
||||
return true;
|
||||
|
@ -135,8 +137,6 @@ void DeInit()
|
|||
NWRAM_C = nullptr;
|
||||
#endif
|
||||
|
||||
DSi_I2C::DeInit();
|
||||
DSi_CamModule::DeInit();
|
||||
DSi_DSP::DeInit();
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
|
@ -148,6 +148,8 @@ void DeInit()
|
|||
delete SDMMC; SDMMC = nullptr;
|
||||
delete SDIO; SDIO = nullptr;
|
||||
|
||||
delete I2C; I2C = nullptr;
|
||||
delete CamModule; CamModule = nullptr;
|
||||
delete AES; AES = nullptr;
|
||||
|
||||
NANDImage = nullptr;
|
||||
|
@ -166,8 +168,8 @@ void Reset()
|
|||
NDMACnt[0] = 0; NDMACnt[1] = 0;
|
||||
for (int i = 0; i < 8; i++) NDMAs[i]->Reset();
|
||||
|
||||
DSi_I2C::Reset();
|
||||
DSi_CamModule::Reset();
|
||||
I2C->Reset();
|
||||
CamModule->Reset();
|
||||
DSi_DSP::Reset();
|
||||
|
||||
SDMMC->CloseHandles();
|
||||
|
@ -210,7 +212,7 @@ void Reset()
|
|||
|
||||
void Stop()
|
||||
{
|
||||
DSi_CamModule::Stop();
|
||||
CamModule->Stop();
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
|
@ -285,9 +287,9 @@ void DoSavestate(Savestate* file)
|
|||
NDMAs[i]->DoSavestate(file);
|
||||
|
||||
AES->DoSavestate(file);
|
||||
DSi_CamModule::DoSavestate(file);
|
||||
CamModule->DoSavestate(file);
|
||||
DSi_DSP::DoSavestate(file);
|
||||
DSi_I2C::DoSavestate(file);
|
||||
I2C->DoSavestate(file);
|
||||
SDMMC->DoSavestate(file);
|
||||
SDIO->DoSavestate(file);
|
||||
}
|
||||
|
@ -581,7 +583,7 @@ void SetupDirectBoot()
|
|||
ARM9Write32(0x02FFFC00, cartid);
|
||||
ARM9Write16(0x02FFFC40, 0x0001); // boot indicator
|
||||
|
||||
ARM9Write8(0x02FFFDFA, DSi_BPTWL::GetBootFlag() | 0x80);
|
||||
ARM9Write8(0x02FFFDFA, I2C->GetBPTWL()->GetBootFlag() | 0x80);
|
||||
ARM9Write8(0x02FFFDFB, 0x01);
|
||||
}
|
||||
|
||||
|
@ -2302,7 +2304,7 @@ u8 ARM9IORead8(u32 addr)
|
|||
if ((addr & 0xFFFFFF00) == 0x04004200)
|
||||
{
|
||||
if (!(SCFG_EXT[0] & (1<<17))) return 0;
|
||||
return DSi_CamModule::Read8(addr);
|
||||
return CamModule->Read8(addr);
|
||||
}
|
||||
|
||||
if ((addr & 0xFFFFFF00) == 0x04004300)
|
||||
|
@ -2337,7 +2339,7 @@ u16 ARM9IORead16(u32 addr)
|
|||
if ((addr & 0xFFFFFF00) == 0x04004200)
|
||||
{
|
||||
if (!(SCFG_EXT[0] & (1<<17))) return 0;
|
||||
return DSi_CamModule::Read16(addr);
|
||||
return CamModule->Read16(addr);
|
||||
}
|
||||
|
||||
if ((addr & 0xFFFFFF00) == 0x04004300)
|
||||
|
@ -2402,7 +2404,7 @@ u32 ARM9IORead32(u32 addr)
|
|||
if ((addr & 0xFFFFFF00) == 0x04004200)
|
||||
{
|
||||
if (!(SCFG_EXT[0] & (1<<17))) return 0;
|
||||
return DSi_CamModule::Read32(addr);
|
||||
return CamModule->Read32(addr);
|
||||
}
|
||||
|
||||
if ((addr & 0xFFFFFF00) == 0x04004300)
|
||||
|
@ -2472,7 +2474,7 @@ void ARM9IOWrite8(u32 addr, u8 val)
|
|||
if ((addr & 0xFFFFFF00) == 0x04004200)
|
||||
{
|
||||
if (!(SCFG_EXT[0] & (1<<17))) return;
|
||||
return DSi_CamModule::Write8(addr, val);
|
||||
return CamModule->Write8(addr, val);
|
||||
}
|
||||
|
||||
if ((addr & 0xFFFFFF00) == 0x04004300)
|
||||
|
@ -2532,7 +2534,7 @@ void ARM9IOWrite16(u32 addr, u16 val)
|
|||
if ((addr & 0xFFFFFF00) == 0x04004200)
|
||||
{
|
||||
if (!(SCFG_EXT[0] & (1<<17))) return;
|
||||
return DSi_CamModule::Write16(addr, val);
|
||||
return CamModule->Write16(addr, val);
|
||||
}
|
||||
|
||||
if ((addr & 0xFFFFFF00) == 0x04004300)
|
||||
|
@ -2682,7 +2684,7 @@ void ARM9IOWrite32(u32 addr, u32 val)
|
|||
if ((addr & 0xFFFFFF00) == 0x04004200)
|
||||
{
|
||||
if (!(SCFG_EXT[0] & (1<<17))) return;
|
||||
return DSi_CamModule::Write32(addr, val);
|
||||
return CamModule->Write32(addr, val);
|
||||
}
|
||||
|
||||
if ((addr & 0xFFFFFF00) == 0x04004300)
|
||||
|
@ -2715,8 +2717,8 @@ u8 ARM7IORead8(u32 addr)
|
|||
CASE_READ8_32BIT(0x0400405C, MBK[1][7])
|
||||
CASE_READ8_32BIT(0x04004060, MBK[1][8])
|
||||
|
||||
case 0x04004500: return DSi_I2C::ReadData();
|
||||
case 0x04004501: return DSi_I2C::Cnt;
|
||||
case 0x04004500: return I2C->ReadData();
|
||||
case 0x04004501: return I2C->ReadCnt();
|
||||
|
||||
case 0x04004D00: if (SCFG_BIOS & (1<<10)) return 0; return NANDImage->GetConsoleID() & 0xFF;
|
||||
case 0x04004D01: if (SCFG_BIOS & (1<<10)) return 0; return (NANDImage->GetConsoleID() >> 8) & 0xFF;
|
||||
|
@ -2899,8 +2901,8 @@ void ARM7IOWrite8(u32 addr, u8 val)
|
|||
return;
|
||||
}
|
||||
|
||||
case 0x04004500: DSi_I2C::WriteData(val); return;
|
||||
case 0x04004501: DSi_I2C::WriteCnt(val); return;
|
||||
case 0x04004500: I2C->WriteData(val); return;
|
||||
case 0x04004501: I2C->WriteCnt(val); return;
|
||||
|
||||
case 0x4004700:
|
||||
DSi_DSP::WriteSNDExCnt((u16)val | (DSi_DSP::SNDExCnt & 0xFF00));
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "NDS.h"
|
||||
#include "DSi_SD.h"
|
||||
|
||||
class DSi_I2CHost;
|
||||
class DSi_CamModule;
|
||||
class DSi_AES;
|
||||
|
||||
namespace DSi_NAND
|
||||
|
@ -58,6 +60,8 @@ extern u32 NWRAMStart[2][3];
|
|||
extern u32 NWRAMEnd[2][3];
|
||||
extern u32 NWRAMMask[2][3];
|
||||
|
||||
extern DSi_I2CHost* I2C;
|
||||
extern DSi_CamModule* CamModule;
|
||||
extern DSi_AES* AES;
|
||||
|
||||
bool Init();
|
||||
|
|
|
@ -25,48 +25,27 @@
|
|||
using Platform::Log;
|
||||
using Platform::LogLevel;
|
||||
|
||||
namespace DSi_CamModule
|
||||
{
|
||||
|
||||
Camera* Camera0; // 78 / facing outside
|
||||
Camera* Camera1; // 7A / selfie cam
|
||||
|
||||
u16 ModuleCnt;
|
||||
u16 Cnt;
|
||||
|
||||
u32 CropStart, CropEnd;
|
||||
|
||||
// pixel data buffer holds a maximum of 512 words, regardless of how long scanlines are
|
||||
u32 DataBuffer[512];
|
||||
u32 BufferReadPos, BufferWritePos;
|
||||
u32 BufferNumLines;
|
||||
Camera* CurCamera;
|
||||
|
||||
// note on camera data/etc intervals
|
||||
// on hardware those are likely affected by several factors
|
||||
// namely, how long cameras take to process frames
|
||||
// camera IRQ is fired at roughly 15FPS with default config
|
||||
|
||||
const u32 kIRQInterval = 1120000; // ~30 FPS
|
||||
const u32 kTransferStart = 60000;
|
||||
const u32 DSi_CamModule::kIRQInterval = 1120000; // ~30 FPS
|
||||
const u32 DSi_CamModule::kTransferStart = 60000;
|
||||
|
||||
|
||||
bool Init()
|
||||
DSi_CamModule::DSi_CamModule()
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_DSi_CamIRQ, 0, IRQ);
|
||||
NDS::RegisterEventFunc(NDS::Event_DSi_CamTransfer, 0, TransferScanline);
|
||||
NDS::RegisterEventFunc(NDS::Event_DSi_CamIRQ, 0, MemberEventFunc(DSi_CamModule, IRQ));
|
||||
NDS::RegisterEventFunc(NDS::Event_DSi_CamTransfer, 0, MemberEventFunc(DSi_CamModule, TransferScanline));
|
||||
|
||||
Camera0 = new Camera(0);
|
||||
Camera1 = new Camera(1);
|
||||
|
||||
return true;
|
||||
Camera0 = DSi::I2C->GetOuterCamera();
|
||||
Camera1 = DSi::I2C->GetInnerCamera();
|
||||
}
|
||||
|
||||
void DeInit()
|
||||
DSi_CamModule::~DSi_CamModule()
|
||||
{
|
||||
delete Camera0;
|
||||
delete Camera1;
|
||||
|
||||
Camera0 = nullptr;
|
||||
Camera1 = nullptr;
|
||||
|
||||
|
@ -74,11 +53,8 @@ void DeInit()
|
|||
NDS::UnregisterEventFunc(NDS::Event_DSi_CamTransfer, 0);
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void DSi_CamModule::Reset()
|
||||
{
|
||||
Camera0->Reset();
|
||||
Camera1->Reset();
|
||||
|
||||
ModuleCnt = 0; // CHECKME
|
||||
Cnt = 0;
|
||||
|
||||
|
@ -94,13 +70,13 @@ void Reset()
|
|||
NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, false, kIRQInterval, 0, 0);
|
||||
}
|
||||
|
||||
void Stop()
|
||||
void DSi_CamModule::Stop()
|
||||
{
|
||||
Camera0->Stop();
|
||||
Camera1->Stop();
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
void DSi_CamModule::DoSavestate(Savestate* file)
|
||||
{
|
||||
file->Section("CAMi");
|
||||
|
||||
|
@ -110,15 +86,12 @@ void DoSavestate(Savestate* file)
|
|||
/*file->VarArray(FrameBuffer, sizeof(FrameBuffer));
|
||||
file->Var32(&TransferPos);
|
||||
file->Var32(&FrameLength);*/
|
||||
|
||||
Camera0->DoSavestate(file);
|
||||
Camera1->DoSavestate(file);
|
||||
}
|
||||
|
||||
|
||||
void IRQ(u32 param)
|
||||
void DSi_CamModule::IRQ(u32 param)
|
||||
{
|
||||
Camera* activecam = nullptr;
|
||||
DSi_Camera* activecam = nullptr;
|
||||
|
||||
// TODO: cameras don't have any priority!
|
||||
// activating both together will jumble the image data together
|
||||
|
@ -145,7 +118,7 @@ void IRQ(u32 param)
|
|||
NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, true, kIRQInterval, 0, 0);
|
||||
}
|
||||
|
||||
void TransferScanline(u32 line)
|
||||
void DSi_CamModule::TransferScanline(u32 line)
|
||||
{
|
||||
u32* dstbuf = &DataBuffer[BufferWritePos];
|
||||
int maxlen = 512 - BufferWritePos;
|
||||
|
@ -252,7 +225,7 @@ void TransferScanline(u32 line)
|
|||
}
|
||||
|
||||
|
||||
u8 Read8(u32 addr)
|
||||
u8 DSi_CamModule::Read8(u32 addr)
|
||||
{
|
||||
//
|
||||
|
||||
|
@ -260,7 +233,7 @@ u8 Read8(u32 addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u16 Read16(u32 addr)
|
||||
u16 DSi_CamModule::Read16(u32 addr)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
|
@ -272,7 +245,7 @@ u16 Read16(u32 addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 Read32(u32 addr)
|
||||
u32 DSi_CamModule::Read32(u32 addr)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
|
@ -298,14 +271,14 @@ u32 Read32(u32 addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Write8(u32 addr, u8 val)
|
||||
void DSi_CamModule::Write8(u32 addr, u8 val)
|
||||
{
|
||||
//
|
||||
|
||||
Log(LogLevel::Debug, "unknown DSi cam write8 %08X %02X\n", addr, val);
|
||||
}
|
||||
|
||||
void Write16(u32 addr, u16 val)
|
||||
void DSi_CamModule::Write16(u32 addr, u16 val)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
|
@ -384,7 +357,7 @@ void Write16(u32 addr, u16 val)
|
|||
Log(LogLevel::Debug, "unknown DSi cam write16 %08X %04X\n", addr, val);
|
||||
}
|
||||
|
||||
void Write32(u32 addr, u32 val)
|
||||
void DSi_CamModule::Write32(u32 addr, u32 val)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
|
@ -403,16 +376,15 @@ void Write32(u32 addr, u32 val)
|
|||
|
||||
|
||||
|
||||
Camera::Camera(u32 num)
|
||||
{
|
||||
Num = num;
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
DSi_Camera::DSi_Camera(DSi_I2CHost* host, u32 num) : DSi_I2CDevice(host), Num(num)
|
||||
{
|
||||
}
|
||||
|
||||
void Camera::DoSavestate(Savestate* file)
|
||||
DSi_Camera::~DSi_Camera()
|
||||
{
|
||||
}
|
||||
|
||||
void DSi_Camera::DoSavestate(Savestate* file)
|
||||
{
|
||||
char magic[5] = "CAMx";
|
||||
magic[3] = '0' + Num;
|
||||
|
@ -433,7 +405,7 @@ void Camera::DoSavestate(Savestate* file)
|
|||
file->VarArray(MCURegs, 0x8000);
|
||||
}
|
||||
|
||||
void Camera::Reset()
|
||||
void DSi_Camera::Reset()
|
||||
{
|
||||
Platform::Camera_Stop(Num);
|
||||
|
||||
|
@ -458,12 +430,12 @@ void Camera::Reset()
|
|||
memset(FrameBuffer, 0, (640*480/2)*sizeof(u32));
|
||||
}
|
||||
|
||||
void Camera::Stop()
|
||||
void DSi_Camera::Stop()
|
||||
{
|
||||
Platform::Camera_Stop(Num);
|
||||
}
|
||||
|
||||
bool Camera::IsActivated()
|
||||
bool DSi_Camera::IsActivated()
|
||||
{
|
||||
if (StandbyCnt & (1<<14)) return false; // standby
|
||||
if (!(MiscCnt & (1<<9))) return false; // data transfer not enabled
|
||||
|
@ -472,7 +444,7 @@ bool Camera::IsActivated()
|
|||
}
|
||||
|
||||
|
||||
void Camera::StartTransfer()
|
||||
void DSi_Camera::StartTransfer()
|
||||
{
|
||||
TransferY = 0;
|
||||
|
||||
|
@ -502,12 +474,12 @@ void Camera::StartTransfer()
|
|||
Platform::Camera_CaptureFrame(Num, FrameBuffer, 640, 480, true);
|
||||
}
|
||||
|
||||
bool Camera::TransferDone()
|
||||
bool DSi_Camera::TransferDone()
|
||||
{
|
||||
return TransferY >= FrameHeight;
|
||||
}
|
||||
|
||||
int Camera::TransferScanline(u32* buffer, int maxlen)
|
||||
int DSi_Camera::TransferScanline(u32* buffer, int maxlen)
|
||||
{
|
||||
if (TransferY >= FrameHeight)
|
||||
return 0;
|
||||
|
@ -560,12 +532,12 @@ int Camera::TransferScanline(u32* buffer, int maxlen)
|
|||
}
|
||||
|
||||
|
||||
void Camera::I2C_Start()
|
||||
void DSi_Camera::Acquire()
|
||||
{
|
||||
DataPos = 0;
|
||||
}
|
||||
|
||||
u8 Camera::I2C_Read(bool last)
|
||||
u8 DSi_Camera::Read(bool last)
|
||||
{
|
||||
u8 ret;
|
||||
|
||||
|
@ -586,7 +558,7 @@ u8 Camera::I2C_Read(bool last)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void Camera::I2C_Write(u8 val, bool last)
|
||||
void DSi_Camera::Write(u8 val, bool last)
|
||||
{
|
||||
if (DataPos < 2)
|
||||
{
|
||||
|
@ -615,7 +587,7 @@ void Camera::I2C_Write(u8 val, bool last)
|
|||
else DataPos++;
|
||||
}
|
||||
|
||||
u16 Camera::I2C_ReadReg(u16 addr)
|
||||
u16 DSi_Camera::I2C_ReadReg(u16 addr)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
|
@ -651,7 +623,7 @@ u16 Camera::I2C_ReadReg(u16 addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Camera::I2C_WriteReg(u16 addr, u16 val)
|
||||
void DSi_Camera::I2C_WriteReg(u16 addr, u16 val)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
|
@ -720,14 +692,14 @@ void Camera::I2C_WriteReg(u16 addr, u16 val)
|
|||
// TODO: not sure at all what is the accessible range
|
||||
// or if there is any overlap in the address range
|
||||
|
||||
u8 Camera::MCU_Read(u16 addr)
|
||||
u8 DSi_Camera::MCU_Read(u16 addr)
|
||||
{
|
||||
addr &= 0x7FFF;
|
||||
|
||||
return MCURegs[addr];
|
||||
}
|
||||
|
||||
void Camera::MCU_Write(u16 addr, u8 val)
|
||||
void DSi_Camera::MCU_Write(u16 addr, u8 val)
|
||||
{
|
||||
addr &= 0x7FFF;
|
||||
|
||||
|
@ -749,7 +721,7 @@ void Camera::MCU_Write(u16 addr, u8 val)
|
|||
}
|
||||
|
||||
|
||||
void Camera::InputFrame(u32* data, int width, int height, bool rgb)
|
||||
void DSi_Camera::InputFrame(u32* data, int width, int height, bool rgb)
|
||||
{
|
||||
// TODO: double-buffering?
|
||||
|
||||
|
@ -820,19 +792,3 @@ void Camera::InputFrame(u32* data, int width, int height, bool rgb)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -21,38 +21,15 @@
|
|||
|
||||
#include "types.h"
|
||||
#include "Savestate.h"
|
||||
#include "DSi_I2C.h"
|
||||
|
||||
namespace DSi_CamModule
|
||||
{
|
||||
class DSi_CamModule;
|
||||
|
||||
class Camera;
|
||||
|
||||
extern Camera* Camera0;
|
||||
extern Camera* Camera1;
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
void Reset();
|
||||
void Stop();
|
||||
|
||||
void DoSavestate(Savestate* file);
|
||||
|
||||
void IRQ(u32 param);
|
||||
|
||||
void TransferScanline(u32 line);
|
||||
|
||||
u8 Read8(u32 addr);
|
||||
u16 Read16(u32 addr);
|
||||
u32 Read32(u32 addr);
|
||||
void Write8(u32 addr, u8 val);
|
||||
void Write16(u32 addr, u16 val);
|
||||
void Write32(u32 addr, u32 val);
|
||||
|
||||
class Camera
|
||||
class DSi_Camera : public DSi_I2CDevice
|
||||
{
|
||||
public:
|
||||
Camera(u32 num);
|
||||
~Camera();
|
||||
DSi_Camera(DSi_I2CHost* host, u32 num);
|
||||
~DSi_Camera();
|
||||
|
||||
void DoSavestate(Savestate* file);
|
||||
|
||||
|
@ -66,9 +43,9 @@ public:
|
|||
// lengths in words
|
||||
int TransferScanline(u32* buffer, int maxlen);
|
||||
|
||||
void I2C_Start();
|
||||
u8 I2C_Read(bool last);
|
||||
void I2C_Write(u8 val, bool last);
|
||||
void Acquire();
|
||||
u8 Read(bool last);
|
||||
void Write(u8 val, bool last);
|
||||
|
||||
void InputFrame(u32* data, int width, int height, bool rgb);
|
||||
|
||||
|
@ -101,6 +78,47 @@ private:
|
|||
u32 FrameBuffer[640*480/2]; // YUYV framebuffer, two pixels per word
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class DSi_CamModule
|
||||
{
|
||||
public:
|
||||
DSi_CamModule();
|
||||
~DSi_CamModule();
|
||||
void Reset();
|
||||
void Stop();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
||||
DSi_Camera* GetOuterCamera() { return Camera0; }
|
||||
DSi_Camera* GetInnerCamera() { return Camera1; }
|
||||
|
||||
void IRQ(u32 param);
|
||||
|
||||
void TransferScanline(u32 line);
|
||||
|
||||
u8 Read8(u32 addr);
|
||||
u16 Read16(u32 addr);
|
||||
u32 Read32(u32 addr);
|
||||
void Write8(u32 addr, u8 val);
|
||||
void Write16(u32 addr, u16 val);
|
||||
void Write32(u32 addr, u32 val);
|
||||
|
||||
private:
|
||||
DSi_Camera* Camera0; // 78 / facing outside
|
||||
DSi_Camera* Camera1; // 7A / selfie cam
|
||||
|
||||
u16 ModuleCnt;
|
||||
u16 Cnt;
|
||||
|
||||
u32 CropStart, CropEnd;
|
||||
|
||||
// pixel data buffer holds a maximum of 512 words, regardless of how long scanlines are
|
||||
u32 DataBuffer[512];
|
||||
u32 BufferReadPos, BufferWritePos;
|
||||
u32 BufferNumLines;
|
||||
DSi_Camera* CurCamera;
|
||||
|
||||
static const u32 kIRQInterval;
|
||||
static const u32 kTransferStart;
|
||||
};
|
||||
|
||||
#endif // DSI_CAMERA_H
|
||||
|
|
215
src/DSi_I2C.cpp
215
src/DSi_I2C.cpp
|
@ -29,18 +29,16 @@
|
|||
using Platform::Log;
|
||||
using Platform::LogLevel;
|
||||
|
||||
namespace DSi_BPTWL
|
||||
{
|
||||
|
||||
// TODO: These are purely approximations
|
||||
const double PowerButtonShutdownTime = 0.5;
|
||||
const double PowerButtonForcedShutdownTime = 5.0;
|
||||
const double VolumeSwitchRepeatStart = 0.5;
|
||||
const double VolumeSwitchRepeatRate = 1.0 / 6;
|
||||
const double DSi_BPTWL::PowerButtonShutdownTime = 0.5;
|
||||
const double DSi_BPTWL::PowerButtonForcedShutdownTime = 5.0;
|
||||
const double DSi_BPTWL::VolumeSwitchRepeatStart = 0.5;
|
||||
const double DSi_BPTWL::VolumeSwitchRepeatRate = 1.0 / 6;
|
||||
|
||||
// Could not find a pattern or a decent formula for these,
|
||||
// regardless, they're only 64 bytes in size
|
||||
const u8 VolumeDownTable[32] =
|
||||
const u8 DSi_BPTWL::VolumeDownTable[32] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03,
|
||||
0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
||||
|
@ -48,7 +46,7 @@ const u8 VolumeDownTable[32] =
|
|||
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
|
||||
};
|
||||
|
||||
const u8 VolumeUpTable[32] =
|
||||
const u8 DSi_BPTWL::VolumeUpTable[32] =
|
||||
{
|
||||
0x02, 0x03, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C,
|
||||
0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
|
||||
|
@ -56,27 +54,16 @@ const u8 VolumeUpTable[32] =
|
|||
0x1D, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
|
||||
};
|
||||
|
||||
double PowerButtonTime = 0.0;
|
||||
bool PowerButtonDownFlag = false;
|
||||
bool PowerButtonShutdownFlag = false;
|
||||
double VolumeSwitchTime = 0.0;
|
||||
double VolumeSwitchRepeatTime = 0.0;
|
||||
bool VolumeSwitchDownFlag = false;
|
||||
u32 VolumeSwitchKeysDown = 0;
|
||||
|
||||
u8 Registers[0x100];
|
||||
u32 CurPos;
|
||||
|
||||
bool Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeInit()
|
||||
DSi_BPTWL::DSi_BPTWL(DSi_I2CHost* host) : DSi_I2CDevice(host)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset()
|
||||
DSi_BPTWL::~DSi_BPTWL()
|
||||
{
|
||||
}
|
||||
|
||||
void DSi_BPTWL::Reset()
|
||||
{
|
||||
CurPos = -1;
|
||||
memset(Registers, 0x5A, 0x100);
|
||||
|
@ -115,10 +102,11 @@ void Reset()
|
|||
VolumeSwitchTime = 0.0;
|
||||
VolumeSwitchRepeatTime = 0.0;
|
||||
VolumeSwitchKeysDown = 0;
|
||||
VolumeSwitchDownFlag = false;
|
||||
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
void DSi_BPTWL::DoSavestate(Savestate* file)
|
||||
{
|
||||
file->Section("I2BP");
|
||||
|
||||
|
@ -127,21 +115,21 @@ void DoSavestate(Savestate* file)
|
|||
}
|
||||
|
||||
// TODO: Needs more investigation on the other bits
|
||||
inline bool GetIRQMode()
|
||||
inline bool DSi_BPTWL::GetIRQMode()
|
||||
{
|
||||
return Registers[0x12] & 0x01;
|
||||
}
|
||||
|
||||
u8 GetBootFlag() { return Registers[0x70]; }
|
||||
u8 DSi_BPTWL::GetBootFlag() { return Registers[0x70]; }
|
||||
|
||||
bool GetBatteryCharging() { return Registers[0x20] >> 7; }
|
||||
void SetBatteryCharging(bool charging)
|
||||
bool DSi_BPTWL::GetBatteryCharging() { return Registers[0x20] >> 7; }
|
||||
void DSi_BPTWL::SetBatteryCharging(bool charging)
|
||||
{
|
||||
Registers[0x20] = (((charging ? 0x8 : 0x0) << 4) | (Registers[0x20] & 0x0F));
|
||||
}
|
||||
|
||||
u8 GetBatteryLevel() { return Registers[0x20] & 0xF; }
|
||||
void SetBatteryLevel(u8 batteryLevel)
|
||||
u8 DSi_BPTWL::GetBatteryLevel() { return Registers[0x20] & 0xF; }
|
||||
void DSi_BPTWL::SetBatteryLevel(u8 batteryLevel)
|
||||
{
|
||||
Registers[0x20] = ((Registers[0x20] & 0xF0) | (batteryLevel & 0x0F));
|
||||
//SPI_Powerman::SetBatteryLevelOkay(batteryLevel > batteryLevel_Low ? true : false);
|
||||
|
@ -153,20 +141,20 @@ void SetBatteryLevel(u8 batteryLevel)
|
|||
|
||||
}
|
||||
|
||||
u8 GetVolumeLevel() { return Registers[0x40]; }
|
||||
void SetVolumeLevel(u8 volume)
|
||||
u8 DSi_BPTWL::GetVolumeLevel() { return Registers[0x40]; }
|
||||
void DSi_BPTWL::SetVolumeLevel(u8 volume)
|
||||
{
|
||||
Registers[0x40] = volume & 0x1F;
|
||||
}
|
||||
|
||||
u8 GetBacklightLevel() { return Registers[0x41]; }
|
||||
void SetBacklightLevel(u8 backlight)
|
||||
u8 DSi_BPTWL::GetBacklightLevel() { return Registers[0x41]; }
|
||||
void DSi_BPTWL::SetBacklightLevel(u8 backlight)
|
||||
{
|
||||
Registers[0x41] = backlight > 4 ? 4 : backlight;
|
||||
}
|
||||
|
||||
|
||||
void ResetButtonState()
|
||||
void DSi_BPTWL::ResetButtonState()
|
||||
{
|
||||
PowerButtonTime = 0.0;
|
||||
PowerButtonDownFlag = false;
|
||||
|
@ -178,7 +166,7 @@ void ResetButtonState()
|
|||
VolumeSwitchRepeatTime = 0.0;
|
||||
}
|
||||
|
||||
void DoHardwareReset(bool direct)
|
||||
void DSi_BPTWL::DoHardwareReset(bool direct)
|
||||
{
|
||||
ResetButtonState();
|
||||
|
||||
|
@ -196,14 +184,14 @@ void DoHardwareReset(bool direct)
|
|||
NDS::ARM7->Halt(4);
|
||||
}
|
||||
|
||||
void DoShutdown()
|
||||
void DSi_BPTWL::DoShutdown()
|
||||
{
|
||||
ResetButtonState();
|
||||
NDS::Stop(Platform::StopReason::PowerOff);
|
||||
}
|
||||
|
||||
|
||||
void SetPowerButtonHeld(double time)
|
||||
void DSi_BPTWL::SetPowerButtonHeld(double time)
|
||||
{
|
||||
if (!PowerButtonDownFlag)
|
||||
{
|
||||
|
@ -230,7 +218,7 @@ void SetPowerButtonHeld(double time)
|
|||
}
|
||||
}
|
||||
|
||||
void SetPowerButtonReleased(double time)
|
||||
void DSi_BPTWL::SetPowerButtonReleased(double time)
|
||||
{
|
||||
double elapsed = time - PowerButtonTime;
|
||||
if (elapsed >= 0 && elapsed < PowerButtonShutdownTime)
|
||||
|
@ -243,12 +231,12 @@ void SetPowerButtonReleased(double time)
|
|||
PowerButtonShutdownFlag = false;
|
||||
}
|
||||
|
||||
void SetVolumeSwitchHeld(u32 key)
|
||||
void DSi_BPTWL::SetVolumeSwitchHeld(u32 key)
|
||||
{
|
||||
VolumeSwitchKeysDown |= (1 << key);
|
||||
}
|
||||
|
||||
void SetVolumeSwitchReleased(u32 key)
|
||||
void DSi_BPTWL::SetVolumeSwitchReleased(u32 key)
|
||||
{
|
||||
VolumeSwitchKeysDown &= ~(1 << key);
|
||||
VolumeSwitchDownFlag = false;
|
||||
|
@ -256,7 +244,7 @@ void SetVolumeSwitchReleased(u32 key)
|
|||
VolumeSwitchRepeatTime = 0.0;
|
||||
}
|
||||
|
||||
inline bool CheckVolumeSwitchKeysValid()
|
||||
inline bool DSi_BPTWL::CheckVolumeSwitchKeysValid()
|
||||
{
|
||||
bool up = VolumeSwitchKeysDown & (1 << volumeKey_Up);
|
||||
bool down = VolumeSwitchKeysDown & (1 << volumeKey_Down);
|
||||
|
@ -264,7 +252,7 @@ inline bool CheckVolumeSwitchKeysValid()
|
|||
return up != down;
|
||||
}
|
||||
|
||||
s32 ProcessVolumeSwitchInput(double time)
|
||||
s32 DSi_BPTWL::ProcessVolumeSwitchInput(double time)
|
||||
{
|
||||
if (!CheckVolumeSwitchKeysValid())
|
||||
return -1;
|
||||
|
@ -303,7 +291,7 @@ s32 ProcessVolumeSwitchInput(double time)
|
|||
}
|
||||
|
||||
|
||||
void DoPowerButtonPress()
|
||||
void DSi_BPTWL::DoPowerButtonPress()
|
||||
{
|
||||
// Set button pressed IRQ
|
||||
SetIRQ(IRQ_PowerButtonPressed);
|
||||
|
@ -311,7 +299,7 @@ void DoPowerButtonPress()
|
|||
// There is no default hardware behavior for pressing the power button
|
||||
}
|
||||
|
||||
void DoPowerButtonReset()
|
||||
void DSi_BPTWL::DoPowerButtonReset()
|
||||
{
|
||||
// Reset via IRQ, handled by software
|
||||
SetIRQ(IRQ_PowerButtonReset);
|
||||
|
@ -324,7 +312,7 @@ void DoPowerButtonReset()
|
|||
}
|
||||
}
|
||||
|
||||
void DoPowerButtonShutdown()
|
||||
void DSi_BPTWL::DoPowerButtonShutdown()
|
||||
{
|
||||
// Shutdown via IRQ, handled by software
|
||||
if (!PowerButtonShutdownFlag)
|
||||
|
@ -346,12 +334,12 @@ void DoPowerButtonShutdown()
|
|||
// down the power button, the DSi will still shut down
|
||||
}
|
||||
|
||||
void DoPowerButtonForceShutdown()
|
||||
void DSi_BPTWL::DoPowerButtonForceShutdown()
|
||||
{
|
||||
DoShutdown();
|
||||
}
|
||||
|
||||
void DoVolumeSwitchPress(u32 key)
|
||||
void DSi_BPTWL::DoVolumeSwitchPress(u32 key)
|
||||
{
|
||||
u8 volume = Registers[0x40];
|
||||
|
||||
|
@ -373,7 +361,7 @@ void DoVolumeSwitchPress(u32 key)
|
|||
SetIRQ(IRQ_VolumeSwitchPressed);
|
||||
}
|
||||
|
||||
void SetIRQ(u8 irqFlag)
|
||||
void DSi_BPTWL::SetIRQ(u8 irqFlag)
|
||||
{
|
||||
Registers[0x10] |= irqFlag & IRQ_ValidMask;
|
||||
|
||||
|
@ -383,12 +371,12 @@ void SetIRQ(u8 irqFlag)
|
|||
}
|
||||
}
|
||||
|
||||
void Start()
|
||||
void DSi_BPTWL::Acquire()
|
||||
{
|
||||
//printf("BPTWL: start\n");
|
||||
}
|
||||
|
||||
u8 Read(bool last)
|
||||
u8 DSi_BPTWL::Read(bool last)
|
||||
{
|
||||
//printf("BPTWL: read %02X -> %02X @ %08X\n", CurPos, Registers[CurPos], NDS::GetPC(1));
|
||||
u8 ret = Registers[CurPos];
|
||||
|
@ -409,7 +397,7 @@ u8 Read(bool last)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void Write(u8 val, bool last)
|
||||
void DSi_BPTWL::Write(u8 val, bool last)
|
||||
{
|
||||
if (last)
|
||||
{
|
||||
|
@ -460,51 +448,69 @@ void Write(u8 val, bool last)
|
|||
CurPos++; // CHECKME
|
||||
}
|
||||
|
||||
|
||||
DSi_I2CHost::DSi_I2CHost()
|
||||
{
|
||||
BPTWL = new DSi_BPTWL(this);
|
||||
Camera0 = new DSi_Camera(this, 0);
|
||||
Camera1 = new DSi_Camera(this, 1);
|
||||
}
|
||||
|
||||
|
||||
namespace DSi_I2C
|
||||
DSi_I2CHost::~DSi_I2CHost()
|
||||
{
|
||||
|
||||
u8 Cnt;
|
||||
u8 Data;
|
||||
|
||||
u32 Device;
|
||||
|
||||
bool Init()
|
||||
{
|
||||
if (!DSi_BPTWL::Init()) return false;
|
||||
|
||||
return true;
|
||||
delete BPTWL; BPTWL = nullptr;
|
||||
delete Camera0; Camera0 = nullptr;
|
||||
delete Camera1; Camera1 = nullptr;
|
||||
}
|
||||
|
||||
void DeInit()
|
||||
{
|
||||
DSi_BPTWL::DeInit();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void DSi_I2CHost::Reset()
|
||||
{
|
||||
Cnt = 0;
|
||||
Data = 0;
|
||||
|
||||
Device = -1;
|
||||
CurDeviceID = 0;
|
||||
CurDevice = nullptr;
|
||||
|
||||
DSi_BPTWL::Reset();
|
||||
BPTWL->Reset();
|
||||
Camera0->Reset();
|
||||
Camera1->Reset();
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
void DSi_I2CHost::DoSavestate(Savestate* file)
|
||||
{
|
||||
file->Section("I2Ci");
|
||||
|
||||
file->Var8(&Cnt);
|
||||
file->Var8(&Data);
|
||||
file->Var32(&Device);
|
||||
file->Var8(&CurDeviceID);
|
||||
|
||||
DSi_BPTWL::DoSavestate(file);
|
||||
if (!file->Saving)
|
||||
{
|
||||
GetCurDevice();
|
||||
}
|
||||
|
||||
BPTWL->DoSavestate(file);
|
||||
Camera0->DoSavestate(file);
|
||||
Camera1->DoSavestate(file);
|
||||
}
|
||||
|
||||
void WriteCnt(u8 val)
|
||||
void DSi_I2CHost::GetCurDevice()
|
||||
{
|
||||
switch (CurDeviceID)
|
||||
{
|
||||
case 0x4A: CurDevice = BPTWL; break;
|
||||
case 0x78: CurDevice = Camera0; break;
|
||||
case 0x7A: CurDevice = Camera1; break;
|
||||
case 0xA0:
|
||||
case 0xE0: CurDevice = nullptr; break;
|
||||
default:
|
||||
Log(LogLevel::Warn, "I2C: unknown device %02X\n", CurDeviceID);
|
||||
CurDevice = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DSi_I2CHost::WriteCnt(u8 val)
|
||||
{
|
||||
//printf("I2C: write CNT %02X, %02X, %08X\n", val, Data, NDS::GetPC(1));
|
||||
|
||||
|
@ -522,17 +528,13 @@ void WriteCnt(u8 val)
|
|||
// read
|
||||
val &= 0xF7;
|
||||
|
||||
switch (Device)
|
||||
if (CurDevice)
|
||||
{
|
||||
Data = CurDevice->Read(islast);
|
||||
}
|
||||
else
|
||||
{
|
||||
case 0x4A: Data = DSi_BPTWL::Read(islast); break;
|
||||
case 0x78: Data = DSi_CamModule::Camera0->I2C_Read(islast); break;
|
||||
case 0x7A: Data = DSi_CamModule::Camera1->I2C_Read(islast); break;
|
||||
case 0xA0:
|
||||
case 0xE0: Data = 0xFF; break;
|
||||
default:
|
||||
Log(LogLevel::Warn, "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);
|
||||
|
@ -545,37 +547,30 @@ void WriteCnt(u8 val)
|
|||
|
||||
if (val & (1<<1))
|
||||
{
|
||||
Device = Data & 0xFE;
|
||||
CurDeviceID = Data & 0xFE;
|
||||
//printf("I2C: %s start, device=%02X\n", (Data&0x01)?"read":"write", Device);
|
||||
|
||||
switch (Device)
|
||||
GetCurDevice();
|
||||
if (CurDevice)
|
||||
{
|
||||
CurDevice->Acquire();
|
||||
}
|
||||
else
|
||||
{
|
||||
case 0x4A: DSi_BPTWL::Start(); break;
|
||||
case 0x78: DSi_CamModule::Camera0->I2C_Start(); break;
|
||||
case 0x7A: DSi_CamModule::Camera1->I2C_Start(); break;
|
||||
case 0xA0:
|
||||
case 0xE0: ack = false; break;
|
||||
default:
|
||||
Log(LogLevel::Warn, "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)
|
||||
if (CurDevice)
|
||||
{
|
||||
CurDevice->Write(Data, islast);
|
||||
}
|
||||
else
|
||||
{
|
||||
case 0x4A: DSi_BPTWL::Write(Data, islast); break;
|
||||
case 0x78: DSi_CamModule::Camera0->I2C_Write(Data, islast); break;
|
||||
case 0x7A: DSi_CamModule::Camera1->I2C_Write(Data, islast); break;
|
||||
case 0xA0:
|
||||
case 0xE0: ack = false; break;
|
||||
default:
|
||||
Log(LogLevel::Warn, "I2C: write on unknown device %02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast);
|
||||
ack = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -588,14 +583,12 @@ void WriteCnt(u8 val)
|
|||
Cnt = val;
|
||||
}
|
||||
|
||||
u8 ReadData()
|
||||
u8 DSi_I2CHost::ReadData()
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
|
||||
void WriteData(u8 val)
|
||||
void DSi_I2CHost::WriteData(u8 val)
|
||||
{
|
||||
Data = val;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
225
src/DSi_I2C.h
225
src/DSi_I2C.h
|
@ -22,95 +22,162 @@
|
|||
#include "types.h"
|
||||
#include "Savestate.h"
|
||||
|
||||
namespace DSi_BPTWL
|
||||
class DSi_I2CHost;
|
||||
class DSi_Camera;
|
||||
|
||||
class DSi_I2CDevice
|
||||
{
|
||||
public:
|
||||
DSi_I2CDevice(DSi_I2CHost* host) : Host(host) {}
|
||||
virtual ~DSi_I2CDevice() {}
|
||||
virtual void Reset() = 0;
|
||||
virtual void DoSavestate(Savestate* file) = 0;
|
||||
|
||||
u8 GetBootFlag();
|
||||
virtual void Acquire() = 0;
|
||||
virtual u8 Read(bool last) = 0;
|
||||
virtual void Write(u8 val, bool last) = 0;
|
||||
|
||||
bool GetBatteryCharging();
|
||||
void SetBatteryCharging(bool charging);
|
||||
|
||||
enum
|
||||
{
|
||||
batteryLevel_Critical = 0x0,
|
||||
batteryLevel_AlmostEmpty = 0x1,
|
||||
batteryLevel_Low = 0x3,
|
||||
batteryLevel_Half = 0x7,
|
||||
batteryLevel_ThreeQuarters = 0xB,
|
||||
batteryLevel_Full = 0xF
|
||||
protected:
|
||||
DSi_I2CHost* Host;
|
||||
};
|
||||
|
||||
u8 GetBatteryLevel();
|
||||
void SetBatteryLevel(u8 batteryLevel);
|
||||
|
||||
// 0-31
|
||||
u8 GetVolumeLevel();
|
||||
void SetVolumeLevel(u8 volume);
|
||||
|
||||
// 0-4
|
||||
u8 GetBacklightLevel();
|
||||
void SetBacklightLevel(u8 backlight);
|
||||
|
||||
void DoHardwareReset(bool direct);
|
||||
void DoShutdown();
|
||||
|
||||
enum
|
||||
class DSi_BPTWL : public DSi_I2CDevice
|
||||
{
|
||||
volumeKey_Up,
|
||||
volumeKey_Down,
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
batteryLevel_Critical = 0x0,
|
||||
batteryLevel_AlmostEmpty = 0x1,
|
||||
batteryLevel_Low = 0x3,
|
||||
batteryLevel_Half = 0x7,
|
||||
batteryLevel_ThreeQuarters = 0xB,
|
||||
batteryLevel_Full = 0xF
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
volumeKey_Up,
|
||||
volumeKey_Down,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
IRQ_PowerButtonReset = 0x01, // Triggered after releasing the power button quickly
|
||||
IRQ_PowerButtonShutdown = 0x02, // Triggered after holding the power button for less than a second
|
||||
IRQ_PowerButtonPressed = 0x08, // Triggered after pressing the power button
|
||||
IRQ_BatteryEmpty = 0x10, //
|
||||
IRQ_BatteryLow = 0x20, // Triggered when the battery level reaches 1
|
||||
IRQ_VolumeSwitchPressed = 0x40, // Triggered once when the volume sliders are first pressed and repeatedly when held down
|
||||
/*
|
||||
Bit 2 (0x04) could be set when holding the power button for more than 5 seconds? (forced power off)
|
||||
It is unknown whether it is set as the console powers off immediately.
|
||||
Bit 7 (0x80) is unused?
|
||||
Both bits are never used by the official ARM7 libraries, but could have some undocumented hardware functionality (?).
|
||||
*/
|
||||
IRQ_ValidMask = 0x7B,
|
||||
};
|
||||
|
||||
DSi_BPTWL(DSi_I2CHost* host);
|
||||
~DSi_BPTWL() override;
|
||||
void Reset() override;
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
u8 GetBootFlag();
|
||||
|
||||
bool GetBatteryCharging();
|
||||
void SetBatteryCharging(bool charging);
|
||||
|
||||
u8 GetBatteryLevel();
|
||||
void SetBatteryLevel(u8 batteryLevel);
|
||||
|
||||
// 0-31
|
||||
u8 GetVolumeLevel();
|
||||
void SetVolumeLevel(u8 volume);
|
||||
|
||||
// 0-4
|
||||
u8 GetBacklightLevel();
|
||||
void SetBacklightLevel(u8 backlight);
|
||||
|
||||
void DoHardwareReset(bool direct);
|
||||
void DoShutdown();
|
||||
|
||||
// Used by hotkeys
|
||||
void SetPowerButtonHeld(double time);
|
||||
void SetPowerButtonReleased(double time);
|
||||
void SetVolumeSwitchHeld(u32 key);
|
||||
void SetVolumeSwitchReleased(u32 key);
|
||||
s32 ProcessVolumeSwitchInput(double time);
|
||||
|
||||
void DoPowerButtonPress();
|
||||
void DoPowerButtonReset();
|
||||
void DoPowerButtonShutdown();
|
||||
void DoPowerButtonForceShutdown();
|
||||
void DoVolumeSwitchPress(u32 key);
|
||||
|
||||
void SetIRQ(u8 irqFlag);
|
||||
|
||||
void Acquire() override;
|
||||
u8 Read(bool last) override;
|
||||
void Write(u8 val, bool last) override;
|
||||
|
||||
private:
|
||||
static const double PowerButtonShutdownTime;
|
||||
static const double PowerButtonForcedShutdownTime;
|
||||
static const double VolumeSwitchRepeatStart;
|
||||
static const double VolumeSwitchRepeatRate;
|
||||
|
||||
static const u8 VolumeDownTable[32];
|
||||
static const u8 VolumeUpTable[32];
|
||||
|
||||
double PowerButtonTime;
|
||||
bool PowerButtonDownFlag;
|
||||
bool PowerButtonShutdownFlag;
|
||||
double VolumeSwitchTime;
|
||||
double VolumeSwitchRepeatTime;
|
||||
bool VolumeSwitchDownFlag ;
|
||||
u32 VolumeSwitchKeysDown;
|
||||
|
||||
u8 Registers[0x100];
|
||||
u32 CurPos;
|
||||
|
||||
bool GetIRQMode();
|
||||
|
||||
void ResetButtonState();
|
||||
bool CheckVolumeSwitchKeysValid();
|
||||
};
|
||||
|
||||
// Used by hotkeys
|
||||
void SetPowerButtonHeld(double time);
|
||||
void SetPowerButtonReleased(double time);
|
||||
void SetVolumeSwitchHeld(u32 key);
|
||||
void SetVolumeSwitchReleased(u32 key);
|
||||
s32 ProcessVolumeSwitchInput(double time);
|
||||
|
||||
void DoPowerButtonPress();
|
||||
void DoPowerButtonReset();
|
||||
void DoPowerButtonShutdown();
|
||||
void DoPowerButtonForceShutdown();
|
||||
void DoVolumeSwitchPress(u32 key);
|
||||
|
||||
enum
|
||||
class DSi_I2CHost
|
||||
{
|
||||
IRQ_PowerButtonReset = 0x01, // Triggered after releasing the power button quickly
|
||||
IRQ_PowerButtonShutdown = 0x02, // Triggered after holding the power button for less than a second
|
||||
IRQ_PowerButtonPressed = 0x08, // Triggered after pressing the power button
|
||||
IRQ_BatteryEmpty = 0x10, //
|
||||
IRQ_BatteryLow = 0x20, // Triggered when the battery level reaches 1
|
||||
IRQ_VolumeSwitchPressed = 0x40, // Triggered once when the volume sliders are first pressed and repeatedly when held down
|
||||
/*
|
||||
Bit 2 (0x04) could be set when holding the power button for more than 5 seconds? (forced power off)
|
||||
It is unknown whether it is set as the console powers off immediately.
|
||||
Bit 7 (0x80) is unused?
|
||||
Both bits are never used by the official ARM7 libraries, but could have some undocumented hardware functionality (?).
|
||||
*/
|
||||
IRQ_ValidMask = 0x7B,
|
||||
public:
|
||||
DSi_I2CHost();
|
||||
~DSi_I2CHost();
|
||||
void Reset();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
||||
DSi_BPTWL* GetBPTWL() { return BPTWL; }
|
||||
DSi_Camera* GetOuterCamera() { return Camera0; }
|
||||
DSi_Camera* GetInnerCamera() { return Camera1; }
|
||||
|
||||
u8 ReadCnt() { return Cnt; }
|
||||
void WriteCnt(u8 val);
|
||||
|
||||
u8 ReadData();
|
||||
void WriteData(u8 val);
|
||||
|
||||
private:
|
||||
u8 Cnt;
|
||||
u8 Data;
|
||||
|
||||
DSi_BPTWL* BPTWL; // 4A / BPTWL IC
|
||||
DSi_Camera* Camera0; // 78 / facing outside
|
||||
DSi_Camera* Camera1; // 7A / selfie cam
|
||||
|
||||
u8 CurDeviceID;
|
||||
DSi_I2CDevice* CurDevice;
|
||||
|
||||
void GetCurDevice();
|
||||
};
|
||||
|
||||
void SetIRQ(u8 irqFlag);
|
||||
|
||||
}
|
||||
|
||||
namespace DSi_I2C
|
||||
{
|
||||
|
||||
extern u8 Cnt;
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
void Reset();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
||||
void WriteCnt(u8 val);
|
||||
|
||||
u8 ReadData();
|
||||
void WriteData(u8 val);
|
||||
|
||||
//void TransferDone(u32 param);
|
||||
|
||||
}
|
||||
|
||||
#endif // DSI_I2C_H
|
||||
|
|
|
@ -1365,8 +1365,8 @@ void CamInputFrame(int cam, u32* data, int width, int height, bool rgb)
|
|||
{
|
||||
switch (cam)
|
||||
{
|
||||
case 0: return DSi_CamModule::Camera0->InputFrame(data, width, height, rgb);
|
||||
case 1: return DSi_CamModule::Camera1->InputFrame(data, width, height, rgb);
|
||||
case 0: return DSi::CamModule->GetOuterCamera()->InputFrame(data, width, height, rgb);
|
||||
case 1: return DSi::CamModule->GetInnerCamera()->InputFrame(data, width, height, rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
10
src/SPI.h
10
src/SPI.h
|
@ -46,9 +46,7 @@ class SPIDevice
|
|||
public:
|
||||
SPIDevice(SPIHost* host) : Host(host), Hold(false), DataPos(0) {}
|
||||
virtual ~SPIDevice() {}
|
||||
|
||||
virtual void Reset() = 0;
|
||||
|
||||
virtual void DoSavestate(Savestate* file) = 0;
|
||||
|
||||
virtual u8 Read() { return Data; }
|
||||
|
@ -68,9 +66,7 @@ class FirmwareMem : public SPIDevice
|
|||
public:
|
||||
FirmwareMem(SPIHost* host);
|
||||
~FirmwareMem() override;
|
||||
|
||||
void Reset() override;
|
||||
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
void SetupDirectBoot(bool dsi);
|
||||
|
@ -100,9 +96,7 @@ class PowerMan : public SPIDevice
|
|||
public:
|
||||
PowerMan(SPIHost* host);
|
||||
~PowerMan() override;
|
||||
|
||||
void Reset() override;
|
||||
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
bool GetBatteryLevelOkay();
|
||||
|
@ -122,9 +116,7 @@ class TSC : public SPIDevice
|
|||
public:
|
||||
TSC(SPIHost* host);
|
||||
virtual ~TSC() override;
|
||||
|
||||
virtual void Reset() override;
|
||||
|
||||
virtual void DoSavestate(Savestate* file) override;
|
||||
|
||||
virtual void SetTouchCoords(u16 x, u16 y);
|
||||
|
@ -149,9 +141,7 @@ class SPIHost
|
|||
public:
|
||||
SPIHost();
|
||||
~SPIHost();
|
||||
|
||||
void Reset();
|
||||
|
||||
void DoSavestate(Savestate* file);
|
||||
|
||||
FirmwareMem* GetFirmwareMem() { return (FirmwareMem*)Devices[SPIDevice_FirmwareMem]; }
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "Platform.h"
|
||||
#include "Config.h"
|
||||
#include "NDS.h"
|
||||
#include "DSi.h"
|
||||
#include "DSi_I2C.h"
|
||||
|
||||
#include "AudioSettingsDialog.h"
|
||||
|
@ -126,7 +127,7 @@ void AudioSettingsDialog::onSyncVolumeLevel()
|
|||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
{
|
||||
bool state = ui->slVolume->blockSignals(true);
|
||||
ui->slVolume->setValue(DSi_BPTWL::GetVolumeLevel());
|
||||
ui->slVolume->setValue(DSi::I2C->GetBPTWL()->GetVolumeLevel());
|
||||
ui->slVolume->blockSignals(state);
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +182,7 @@ void AudioSettingsDialog::on_slVolume_valueChanged(int val)
|
|||
{
|
||||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
{
|
||||
DSi_BPTWL::SetVolumeLevel(val);
|
||||
DSi::I2C->GetBPTWL()->SetVolumeLevel(val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -196,7 +197,7 @@ void AudioSettingsDialog::on_chkSyncDSiVolume_clicked(bool checked)
|
|||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
{
|
||||
ui->slVolume->setMaximum(31);
|
||||
ui->slVolume->setValue(DSi_BPTWL::GetVolumeLevel());
|
||||
ui->slVolume->setValue(DSi::I2C->GetBPTWL()->GetVolumeLevel());
|
||||
ui->slVolume->setPageStep(4);
|
||||
ui->slVolume->setTickPosition(QSlider::TicksBelow);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "SPI.h"
|
||||
#include "DSi_I2C.h"
|
||||
#include "NDS.h"
|
||||
#include "DSi.h"
|
||||
#include "Config.h"
|
||||
#include "Platform.h"
|
||||
|
||||
|
@ -42,8 +43,8 @@ PowerManagementDialog::PowerManagementDialog(QWidget* parent) : QDialog(parent),
|
|||
{
|
||||
ui->grpDSBattery->setEnabled(false);
|
||||
|
||||
oldDSiBatteryLevel = DSi_BPTWL::GetBatteryLevel();
|
||||
oldDSiBatteryCharging = DSi_BPTWL::GetBatteryCharging();
|
||||
oldDSiBatteryLevel = DSi::I2C->GetBPTWL()->GetBatteryLevel();
|
||||
oldDSiBatteryCharging = DSi::I2C->GetBPTWL()->GetBatteryCharging();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -54,9 +55,9 @@ PowerManagementDialog::PowerManagementDialog(QWidget* parent) : QDialog(parent),
|
|||
|
||||
updateDSBatteryLevelControls();
|
||||
|
||||
ui->cbDSiBatteryCharging->setChecked(DSi_BPTWL::GetBatteryCharging());
|
||||
ui->cbDSiBatteryCharging->setChecked(DSi::I2C->GetBPTWL()->GetBatteryCharging());
|
||||
int dsiBatterySliderPos;
|
||||
switch (DSi_BPTWL::GetBatteryLevel())
|
||||
switch (DSi::I2C->GetBPTWL()->GetBatteryLevel())
|
||||
{
|
||||
case DSi_BPTWL::batteryLevel_AlmostEmpty: dsiBatterySliderPos = 0; break;
|
||||
case DSi_BPTWL::batteryLevel_Low: dsiBatterySliderPos = 1; break;
|
||||
|
@ -86,8 +87,8 @@ void PowerManagementDialog::done(int r)
|
|||
{
|
||||
if (NDS::ConsoleType == 1)
|
||||
{
|
||||
Config::DSiBatteryLevel = DSi_BPTWL::GetBatteryLevel();
|
||||
Config::DSiBatteryCharging = DSi_BPTWL::GetBatteryCharging();
|
||||
Config::DSiBatteryLevel = DSi::I2C->GetBPTWL()->GetBatteryLevel();
|
||||
Config::DSiBatteryCharging = DSi::I2C->GetBPTWL()->GetBatteryCharging();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -98,8 +99,8 @@ void PowerManagementDialog::done(int r)
|
|||
{
|
||||
if (NDS::ConsoleType == 1)
|
||||
{
|
||||
DSi_BPTWL::SetBatteryLevel(oldDSiBatteryLevel);
|
||||
DSi_BPTWL::SetBatteryCharging(oldDSiBatteryCharging);
|
||||
DSi::I2C->GetBPTWL()->SetBatteryLevel(oldDSiBatteryLevel);
|
||||
DSi::I2C->GetBPTWL()->SetBatteryCharging(oldDSiBatteryCharging);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -132,7 +133,7 @@ void PowerManagementDialog::updateDSBatteryLevelControls()
|
|||
|
||||
void PowerManagementDialog::on_cbDSiBatteryCharging_toggled()
|
||||
{
|
||||
DSi_BPTWL::SetBatteryCharging(ui->cbDSiBatteryCharging->isChecked());
|
||||
DSi::I2C->GetBPTWL()->SetBatteryCharging(ui->cbDSiBatteryCharging->isChecked());
|
||||
}
|
||||
|
||||
void PowerManagementDialog::on_sliderDSiBatteryLevel_valueChanged(int value)
|
||||
|
@ -142,13 +143,13 @@ void PowerManagementDialog::on_sliderDSiBatteryLevel_valueChanged(int value)
|
|||
u8 newBatteryLevel;
|
||||
switch (value)
|
||||
{
|
||||
case 0: newBatteryLevel = DSi_BPTWL::batteryLevel_AlmostEmpty; break;
|
||||
case 1: newBatteryLevel = DSi_BPTWL::batteryLevel_Low; break;
|
||||
case 2: newBatteryLevel = DSi_BPTWL::batteryLevel_Half; break;
|
||||
case 3: newBatteryLevel = DSi_BPTWL::batteryLevel_ThreeQuarters; break;
|
||||
case 4: newBatteryLevel = DSi_BPTWL::batteryLevel_Full; break;
|
||||
case 0: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_AlmostEmpty; break;
|
||||
case 1: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_Low; break;
|
||||
case 2: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_Half; break;
|
||||
case 3: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_ThreeQuarters; break;
|
||||
case 4: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_Full; break;
|
||||
}
|
||||
DSi_BPTWL::SetBatteryLevel(newBatteryLevel);
|
||||
DSi::I2C->GetBPTWL()->SetBatteryLevel(newBatteryLevel);
|
||||
updateDSBatteryLevelControls();
|
||||
}
|
||||
|
||||
|
|
|
@ -583,8 +583,8 @@ void SetBatteryLevels()
|
|||
{
|
||||
if (NDS::ConsoleType == 1)
|
||||
{
|
||||
DSi_BPTWL::SetBatteryLevel(Config::DSiBatteryLevel);
|
||||
DSi_BPTWL::SetBatteryCharging(Config::DSiBatteryCharging);
|
||||
DSi::I2C->GetBPTWL()->SetBatteryLevel(Config::DSiBatteryLevel);
|
||||
DSi::I2C->GetBPTWL()->SetBatteryCharging(Config::DSiBatteryCharging);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -90,8 +90,9 @@
|
|||
#include "Platform.h"
|
||||
#include "LocalMP.h"
|
||||
#include "Config.h"
|
||||
#include "DSi_I2C.h"
|
||||
#include "RTC.h"
|
||||
#include "DSi.h"
|
||||
#include "DSi_I2C.h"
|
||||
|
||||
#include "Savestate.h"
|
||||
|
||||
|
@ -409,33 +410,33 @@ void EmuThread::run()
|
|||
// Handle power button
|
||||
if (Input::HotkeyDown(HK_PowerButton))
|
||||
{
|
||||
DSi_BPTWL::SetPowerButtonHeld(currentTime);
|
||||
DSi::I2C->GetBPTWL()->SetPowerButtonHeld(currentTime);
|
||||
}
|
||||
else if (Input::HotkeyReleased(HK_PowerButton))
|
||||
{
|
||||
DSi_BPTWL::SetPowerButtonReleased(currentTime);
|
||||
DSi::I2C->GetBPTWL()->SetPowerButtonReleased(currentTime);
|
||||
}
|
||||
|
||||
// Handle volume buttons
|
||||
if (Input::HotkeyDown(HK_VolumeUp))
|
||||
{
|
||||
DSi_BPTWL::SetVolumeSwitchHeld(DSi_BPTWL::volumeKey_Up);
|
||||
DSi::I2C->GetBPTWL()->SetVolumeSwitchHeld(DSi::I2C->GetBPTWL()->volumeKey_Up);
|
||||
}
|
||||
else if (Input::HotkeyReleased(HK_VolumeUp))
|
||||
{
|
||||
DSi_BPTWL::SetVolumeSwitchReleased(DSi_BPTWL::volumeKey_Up);
|
||||
DSi::I2C->GetBPTWL()->SetVolumeSwitchReleased(DSi::I2C->GetBPTWL()->volumeKey_Up);
|
||||
}
|
||||
|
||||
if (Input::HotkeyDown(HK_VolumeDown))
|
||||
{
|
||||
DSi_BPTWL::SetVolumeSwitchHeld(DSi_BPTWL::volumeKey_Down);
|
||||
DSi::I2C->GetBPTWL()->SetVolumeSwitchHeld(DSi::I2C->GetBPTWL()->volumeKey_Down);
|
||||
}
|
||||
else if (Input::HotkeyReleased(HK_VolumeDown))
|
||||
{
|
||||
DSi_BPTWL::SetVolumeSwitchReleased(DSi_BPTWL::volumeKey_Down);
|
||||
DSi::I2C->GetBPTWL()->SetVolumeSwitchReleased(DSi::I2C->GetBPTWL()->volumeKey_Down);
|
||||
}
|
||||
|
||||
DSi_BPTWL::ProcessVolumeSwitchInput(currentTime);
|
||||
DSi::I2C->GetBPTWL()->ProcessVolumeSwitchInput(currentTime);
|
||||
}
|
||||
|
||||
if (EmuRunning == emuStatus_Running || EmuRunning == emuStatus_FrameStep)
|
||||
|
@ -562,7 +563,7 @@ void EmuThread::run()
|
|||
|
||||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
{
|
||||
u8 volumeLevel = DSi_BPTWL::GetVolumeLevel();
|
||||
u8 volumeLevel = DSi::I2C->GetBPTWL()->GetVolumeLevel();
|
||||
if (volumeLevel != dsiVolumeLevel)
|
||||
{
|
||||
dsiVolumeLevel = volumeLevel;
|
||||
|
|
Loading…
Reference in New Issue