|
|
nono 1.7.0
//
// nono
// Copyright (C) 2022 nono project
// Licensed under nono-license.txt
//
//
// ADPCM (MSM6258V)
//
#pragma once
#include "device.h"
class DMACDevice;
class SoundRenderer;
class SoundTrack;
class ADPCMDevice : public IODevice
{
using inherited = IODevice;
static const uint32 baseaddr = 0xe92000;
static const uint8 STAT_PLAY = 0x80;
static const uint8 REC_START = 0x04;
static const uint8 PLAY_START = 0x02;
static const uint8 STOP = 0x01;
public:
ADPCMDevice();
~ADPCMDevice() override;
bool Init() override;
void ResetHard(bool poweron) override;
// CT1 によるクロック切り替え。OPM から呼ばれる。
void SetClock(bool);
// DMAC から呼ばれる。
void AssertDACK();
// PPI
bool GetPanOutL() const { return panout_L; }
bool GetPanOutR() const { return panout_R; }
void SetPanOutL(bool on);
void SetPanOutR(bool on);
void SetRate(uint32 idx);
protected:
// BusIO インタフェース
static const uint32 NPORT = 2;
busdata ReadPort(uint32 offset);
busdata WritePort(uint32 offset, uint32 data);
busdata PeekPort(uint32 offset);
bool PokePort(uint32 offset, uint32 data);
private:
DECLARE_MONITOR_SCREEN(MonitorScreen);
uint32 GetSTAT() const;
void StartPlay();
void StopPlay();
void WriteData(uint32 data);
void CalcRate();
void EventCallback(Event *);
void DecodeADPCM(uint32 data);
void WritePCM(uint64 vtime, int16 target);
uint32 pcm2adpcm_step(int16 pcm);
int16 adpcm2pcm_step(uint32 data);
inline uint32 adpcm_encode(int32 dn);
inline int32 adpcm_decode(uint32 data, int32 xn);
inline void adpcm_calcstep(uint32 data);
bool playing {};
int clkMHz {}; // 入力クロック[MHz] (4 or 8)
int div {}; // 512, 768, 1024
bool panout_L {};
bool panout_R {};
// 選択周波数での 1フレームにかかる時間 [tsec]
uint64 guest_frame_tsec {};
// 周波数
uint32 freq {};
// データバッファ(1バイト)
uint8 databuf {};
// ADPCM<->PCM 変換
int32 xprev {};
int stepidx {};
// 最後に書き込んだサンプル値 (線形補間用)
int16 pcm0 {};
// ミキサー周波数での1フレームにかかる時間 [tsec]
uint64 mixer_frame_tsec {};
// ミキサー周波数にアップスキャンするための倍率。
// 15625 Hz なら 4(倍)。
uint scale_factor {};
DMACDevice *dmac {};
SoundRenderer *sound {};
SoundTrack *track {};
Event *event {};
Monitor *monitor {};
static const int adpcm_stepadj[16];
static const int32 adpcm_stepsize[49];
};
inline ADPCMDevice *GetADPCMDevice() {
return Object::GetObject<ADPCMDevice>(OBJ_ADPCM);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.