melonDS/src/SPI.h

176 lines
4.1 KiB
C++

/*
Copyright 2016-2024 melonDS team
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/.
*/
#ifndef SPI_H
#define SPI_H
#include <algorithm>
#include <array>
#include <memory>
#include <string_view>
#include <string.h>
#include "Savestate.h"
#include "SPI_Firmware.h"
namespace melonDS
{
enum
{
SPIDevice_PowerMan = 0,
SPIDevice_FirmwareMem,
SPIDevice_TSC,
SPIDevice_MAX
};
u16 CRC16(const u8* data, u32 len, u32 start);
class SPIHost;
class NDS;
class SPIDevice
{
public:
SPIDevice(melonDS::NDS& nds) : NDS(nds), Hold(false), DataPos(0) {}
virtual ~SPIDevice() {}
virtual void Reset() = 0;
virtual void DoSavestate(Savestate* file) = 0;
virtual u8 Read() const { return Data; }
virtual void Write(u8 val) = 0;
virtual void Release() { Hold = false; DataPos = 0; }
protected:
melonDS::NDS& NDS;
bool Hold;
u32 DataPos;
u8 Data;
};
class FirmwareMem : public SPIDevice
{
public:
FirmwareMem(melonDS::NDS& nds, melonDS::Firmware&& firmware);
~FirmwareMem() override;
void Reset() override;
void DoSavestate(Savestate* file) override;
void SetupDirectBoot();
Firmware& GetFirmware() noexcept { return FirmwareData; }
[[nodiscard]] const Firmware& GetFirmware() const noexcept { return FirmwareData; }
void SetFirmware(Firmware&& firmware) { FirmwareData = std::move(firmware); }
bool IsLoadedFirmwareBuiltIn() const;
void Write(u8 val) override;
void Release() override;
private:
Firmware FirmwareData;
u8 CurCmd;
u8 StatusReg;
u32 Addr;
bool VerifyCRC16(u32 start, u32 offset, u32 len, u32 crcoffset) const;
};
class PowerMan : public SPIDevice
{
public:
PowerMan(melonDS::NDS& nds);
~PowerMan() override;
void Reset() override;
void DoSavestate(Savestate* file) override;
bool GetBatteryLevelOkay() const;
void SetBatteryLevelOkay(bool okay);
void Write(u8 val) override;
private:
u8 Index;
u8 Registers[8];
u8 RegMasks[8];
};
class TSC : public SPIDevice
{
public:
TSC(melonDS::NDS& nds);
virtual ~TSC() override;
virtual void Reset() override;
virtual void DoSavestate(Savestate* file) override;
virtual void SetTouchCoords(u16 x, u16 y);
virtual void MicInputFrame(const s16* data, int samples);
virtual void Write(u8 val) override;
protected:
u8 ControlByte;
u16 ConvResult;
u16 TouchX, TouchY;
s16 MicBuffer[1024];
int MicBufferLen;
};
class SPIHost
{
public:
SPIHost(melonDS::NDS& nds, Firmware&& firmware);
~SPIHost();
void Reset();
void DoSavestate(Savestate* file);
FirmwareMem* GetFirmwareMem() { return (FirmwareMem*)Devices[SPIDevice_FirmwareMem]; }
const FirmwareMem* GetFirmwareMem() const { return (FirmwareMem*)Devices[SPIDevice_FirmwareMem]; }
PowerMan* GetPowerMan() { return (PowerMan*)Devices[SPIDevice_PowerMan]; }
const PowerMan* GetPowerMan() const { return (PowerMan*)Devices[SPIDevice_PowerMan]; }
TSC* GetTSC() { return (TSC*)Devices[SPIDevice_TSC]; }
const TSC* GetTSC() const { return (TSC*)Devices[SPIDevice_TSC]; }
const Firmware& GetFirmware() const { return GetFirmwareMem()->GetFirmware(); }
Firmware& GetFirmware() { return GetFirmwareMem()->GetFirmware(); }
void SetFirmware(Firmware&& firmware) { GetFirmwareMem()->SetFirmware(std::move(firmware)); }
u16 ReadCnt() const { return Cnt; }
void WriteCnt(u16 val);
u8 ReadData() const;
void WriteData(u8 val);
void TransferDone(u32 param);
private:
melonDS::NDS& NDS;
u16 Cnt;
SPIDevice* Devices[3];
};
}
#endif